Add automatic native Windows GPU quick-test packaging
This commit is contained in:
1 parent
3d5f42865f
commit
21ed0a8c88
7 files changed
+502
No files matched your search
@@ -0,0 +1,89 @@
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[string]$GamePackagePrefix, [Parameter(Mandatory=$true)][string]$PackageRoot,
|
||||
[string]$ArchivePath
|
||||
)
|
||||
$ErrorActionPreference='Stop'
|
||||
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
|
||||
$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
|
||||
if (!$GamePackagePrefix) { $GamePackagePrefix=Join-Path $repo 'dist/windows-gpu-coverage-game' }
|
||||
$PackageRoot=[IO.Path]::GetFullPath($PackageRoot)
|
||||
if (Test-Path -LiteralPath $PackageRoot) { throw 'Use a new output directory to avoid mixing releases.' }
|
||||
$commit=(& git -C $repo rev-parse HEAD).Trim()
|
||||
if ($ArchivePath -and [bool](& git -C $repo status --porcelain)) { throw 'Commit source changes before creating a public ZIP.' }
|
||||
New-Item -ItemType Directory -Force $PackageRoot | Out-Null
|
||||
$files=[Collections.Generic.List[object]]::new()
|
||||
function Stage([string]$Source,[string]$Relative) {
|
||||
$destination=Join-Path $PackageRoot $Relative
|
||||
New-Item -ItemType Directory -Force (Split-Path $destination) | Out-Null
|
||||
Copy-Item -LiteralPath $Source -Destination $destination
|
||||
$item=Get-Item -LiteralPath $destination
|
||||
$entry=@{path=$Relative.Replace('\','/'); sha256=(Get-FileHash -LiteralPath $destination -Algorithm SHA256).Hash; version=$item.VersionInfo.FileVersion}
|
||||
$files.Add($entry)
|
||||
return $entry
|
||||
}
|
||||
$targets=[ordered]@{}; $common=@(); $baseline=$null
|
||||
foreach ($gpu in Get-D4RGpuTargets) {
|
||||
$arch=$gpu.architecture; $source="$GamePackagePrefix-$arch"
|
||||
$metadata=Get-Content -LiteralPath (Join-Path $source 'package.json') -Raw | ConvertFrom-Json
|
||||
if ($metadata.architecture -ne $arch -or $metadata.d4rWorkingTreeDirty) { throw "Uncommitted or wrong-target input: $source" }
|
||||
$targetFiles=@()
|
||||
foreach ($file in $metadata.files) {
|
||||
$relative=$file.path.Replace('\','/')
|
||||
if ((Get-FileHash -LiteralPath (Join-Path $source $file.path) -Algorithm SHA256).Hash -ne $file.sha256) { throw "Input file changed: $source/$relative" }
|
||||
if ($relative.EndsWith('.hsaco')) { Assert-D4RCodeObjectTarget (Join-Path $source $file.path) $arch }
|
||||
if ($relative -eq 'gpu-target.json' -or $relative -eq 'd4r/_nvngx.dll' -or $relative -eq 'd4r/d4r_gpu_inventory.exe' -or $relative -eq 'd4r/d4r_debug_launcher.exe' -or $relative -eq 'd4r/nvapi/nvapi64.dll' -or
|
||||
$relative.StartsWith('d4r/native/') -or $relative -like 'd4r/pixel_convert_*.hsaco') {
|
||||
$entry=Stage (Join-Path $source $file.path) "files/targets/$arch/$relative"
|
||||
$targetFiles+=@{path=$relative; sha256=$entry.sha256; version=$entry.version}
|
||||
} elseif ($relative -eq 'OptiScaler.dll' -or $relative.StartsWith('d4r/') -or $relative.StartsWith('licenses/')) {
|
||||
$publicPath=if ($relative.StartsWith('licenses/')) { $relative } else { "files/common/$relative" }
|
||||
if (!$baseline) {
|
||||
$entry=Stage (Join-Path $source $file.path) $publicPath
|
||||
if (!$relative.StartsWith('licenses/')) { $common+=@{path=$relative; sha256=$entry.sha256; version=$entry.version} }
|
||||
} elseif ((Get-FileHash -LiteralPath (Join-Path $PackageRoot $publicPath) -Algorithm SHA256).Hash -ne $file.sha256) {
|
||||
throw "Shared runtime differs in $arch : $relative"
|
||||
}
|
||||
}
|
||||
}
|
||||
if (@($targetFiles | Where-Object { $_.path.EndsWith('.hsaco') }).Count -ne 17) { throw "Expected 17 code objects for $arch" }
|
||||
$targets[$arch]=@{binarySourceCommit=$metadata.d4rCommit; hardwareValidation=$metadata.hardwareValidation; dlssSha256=$metadata.dlssSha256; files=$targetFiles}
|
||||
if (!$baseline) { $baseline=$metadata }
|
||||
if ($metadata.dlssSha256 -ne $baseline.dlssSha256 -or $metadata.zludaBuild.sourceCommit -ne $baseline.zludaBuild.sourceCommit) { throw 'Input packages do not use the same validated dependencies.' }
|
||||
}
|
||||
foreach ($name in @('windows-game.ps1','gpu-target.ps1','gpu-preflight.ps1')) {
|
||||
$entry=Stage (Join-Path $PSScriptRoot $name) "files/common/$name"
|
||||
$common+=@{path=$name; sha256=$entry.sha256; version=$entry.version}
|
||||
}
|
||||
$entry=Stage (Join-Path $repo 'tools/windows/gpu-targets.json') 'files/common/gpu-targets.json'
|
||||
$common+=@{path='gpu-targets.json'; sha256=$entry.sha256; version=$entry.version}
|
||||
[void](Stage (Join-Path $PSScriptRoot 'quick-test.ps1') 'files/quick-test.ps1')
|
||||
[void](Stage (Join-Path $repo 'docs/windows-quick-test.txt') 'READ-ME-FIRST.txt')
|
||||
foreach ($launch in @(@{name='START-K.cmd'; arguments='-Preset 11'},@{name='START-M.cmd'; arguments='-Preset 13'},@{name='RESTORE-GAME.cmd'; arguments='-Action restore'})) {
|
||||
$path=Join-Path $PackageRoot $launch.name
|
||||
@('@echo off','cd /d "%~dp0"',('"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -STA -ExecutionPolicy Bypass -File "%~dp0files\quick-test.ps1" '+$launch.arguments),'pause') |
|
||||
Set-Content -LiteralPath $path -Encoding ASCII
|
||||
$files.Add(@{path=$launch.name; sha256=(Get-FileHash -LiteralPath $path -Algorithm SHA256).Hash; version=$null})
|
||||
}
|
||||
# Publicly supplied original identity, never the binary itself.
|
||||
$metadata=[ordered]@{schema=1; packageCommit=$commit; binarySourceCommit=$baseline.d4rCommit;
|
||||
ngxCoreSha256='66767018C36B3BAB46398DADE3ADF173DAA3730FDA75965689EA848C9BC4E79B';
|
||||
dependencies=@{optiScalerSourceCommit=$baseline.optiScaler.sourceCommit; zludaSourceCommit=$baseline.zludaBuild.sourceCommit;
|
||||
llvmSource=$baseline.zludaBuild.llvmSource; hipRuntime=$baseline.hipRuntime};
|
||||
commonFiles=$common; targets=$targets; files=$files}
|
||||
$metadata | ConvertTo-Json -Depth 12 | Set-Content -LiteralPath (Join-Path $PackageRoot 'files/package.json') -Encoding UTF8
|
||||
if ($ArchivePath) {
|
||||
$ArchivePath=[IO.Path]::GetFullPath($ArchivePath)
|
||||
if ($ArchivePath.StartsWith($PackageRoot+'\',[StringComparison]::OrdinalIgnoreCase)) { throw 'Place the ZIP outside the output directory.' }
|
||||
New-Item -ItemType Directory -Force (Split-Path $ArchivePath) | Out-Null
|
||||
Add-Type -AssemblyName System.IO.Compression,System.IO.Compression.FileSystem
|
||||
$stream=[IO.File]::Open($ArchivePath,[IO.FileMode]::Create,[IO.FileAccess]::ReadWrite,[IO.FileShare]::None)
|
||||
$archive=$null
|
||||
try {
|
||||
$archive=[IO.Compression.ZipArchive]::new($stream,[IO.Compression.ZipArchiveMode]::Create)
|
||||
foreach ($relative in @($files.path)+@('files/package.json')) {
|
||||
[void][IO.Compression.ZipFileExtensions]::CreateEntryFromFile($archive,(Join-Path $PackageRoot $relative),$relative,[IO.Compression.CompressionLevel]::Optimal)
|
||||
}
|
||||
} finally { if ($archive) { $archive.Dispose() }; $stream.Dispose() }
|
||||
}
|
||||
Write-Host "Quick-test package: $PackageRoot (11 targets, automatic GPU selection, no NVIDIA DLLs)"
|
||||
@@ -0,0 +1,166 @@
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[ValidateSet('run','install','restore')][string]$Action='run',
|
||||
[ValidateSet(11,13)][int]$Preset=11,
|
||||
[string]$GameExe, [string]$NgxCore, [string]$DlssDll
|
||||
)
|
||||
$ErrorActionPreference='Stop'
|
||||
$root=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '..'))
|
||||
$work=Join-Path $root 'work'
|
||||
$settingsPath=Join-Path $work 'settings.json'
|
||||
New-Item -ItemType Directory -Force $work | Out-Null
|
||||
$saved=$null
|
||||
if (Test-Path -LiteralPath $settingsPath) {
|
||||
try { $saved=Get-Content -LiteralPath $settingsPath -Raw | ConvertFrom-Json }
|
||||
catch { Write-Host 'Saved choices could not be read. Select the files again.' }
|
||||
}
|
||||
function Select-LocalFile([string]$Title, [string]$FileName, [string]$Previous) {
|
||||
if ($Previous -and (Test-Path -LiteralPath $Previous -PathType Leaf)) { return (Get-Item -LiteralPath $Previous).FullName }
|
||||
Add-Type -AssemblyName System.Windows.Forms
|
||||
$dialog=New-Object Windows.Forms.OpenFileDialog
|
||||
try {
|
||||
$dialog.Title=$Title; $dialog.FileName=$FileName
|
||||
$dialog.Filter=if ($FileName -eq '*.exe') { 'Game executable (*.exe)|*.exe' } else { "$FileName|$FileName" }
|
||||
if ($dialog.ShowDialog() -ne [Windows.Forms.DialogResult]::OK) { throw 'File selection cancelled. No test was launched.' }
|
||||
return $dialog.FileName
|
||||
} finally { $dialog.Dispose() }
|
||||
}
|
||||
function Copy-Payload([string]$Source, [string]$Destination, [string]$Relative) {
|
||||
$path=[IO.Path]::GetFullPath((Join-Path $Destination $Relative))
|
||||
if (!$path.StartsWith($Destination+'\',[StringComparison]::OrdinalIgnoreCase)) { throw 'Invalid package path.' }
|
||||
New-Item -ItemType Directory -Force (Split-Path $path) | Out-Null
|
||||
Copy-Item -LiteralPath (Join-Path $Source $Relative) -Destination $path -Force
|
||||
}
|
||||
if ($Action -eq 'restore') {
|
||||
$GameExe=Select-LocalFile 'Select the SAME game executable used for the test' '*.exe' $(if ($GameExe) { $GameExe } elseif ($saved) { $saved.game })
|
||||
& (Join-Path $PSScriptRoot 'common/windows-game.ps1') -Action restore -GameExe $GameExe
|
||||
Write-Host 'RESTORED. Launch the game normally again.' -ForegroundColor Green
|
||||
return
|
||||
}
|
||||
$output=Join-Path $root ('results/test-'+(Get-Date -Format 'yyyyMMdd-HHmmss-fff'))
|
||||
New-Item -ItemType Directory -Force $output | Out-Null
|
||||
$status=[ordered]@{action=$Action; preset=$Preset; status='starting'; hardwareValidationCompleted=$false}
|
||||
$selectedPackage=$null
|
||||
try {
|
||||
Write-Host 'd4r Windows quick test - keep this window open until you EXIT the game.'
|
||||
Write-Host 'Checking package and detecting the GPU...'
|
||||
$manifest=Get-Content -LiteralPath (Join-Path $PSScriptRoot 'package.json') -Raw | ConvertFrom-Json
|
||||
foreach ($file in $manifest.files) {
|
||||
$path=[IO.Path]::GetFullPath((Join-Path $root $file.path))
|
||||
if (!$path.StartsWith($root+'\',[StringComparison]::OrdinalIgnoreCase) -or
|
||||
(Get-FileHash -LiteralPath $path -Algorithm SHA256).Hash -ne $file.sha256) { throw "Package is incomplete or changed. Extract the ZIP again. File: $($file.path)" }
|
||||
}
|
||||
$status.packageCommit=$manifest.packageCommit
|
||||
$inventoryDir=Join-Path $output 'gpu'
|
||||
New-Item -ItemType Directory -Force $inventoryDir | Out-Null
|
||||
$info=New-Object Diagnostics.ProcessStartInfo
|
||||
$info.FileName=Join-Path $PSScriptRoot 'targets/gfx1201/d4r/d4r_gpu_inventory.exe'
|
||||
$info.Arguments='--hip-root "'+(Join-Path $PSScriptRoot 'common/d4r/hip')+'" --output-dir "'+$inventoryDir+'"'
|
||||
$info.UseShellExecute=$false; $info.CreateNoWindow=$true
|
||||
$info.EnvironmentVariables['D4R_DIAG_DIR']=$inventoryDir
|
||||
$info.RedirectStandardOutput=$true; $info.RedirectStandardError=$true
|
||||
$process=New-Object Diagnostics.Process; $process.StartInfo=$info
|
||||
try {
|
||||
if (!$process.Start()) { throw 'GPU detection could not start.' }
|
||||
$stdout=$process.StandardOutput.ReadToEndAsync(); $stderr=$process.StandardError.ReadToEndAsync()
|
||||
$timedOut=!$process.WaitForExit(30000)
|
||||
if ($timedOut) { $process.Kill(); $process.WaitForExit() }
|
||||
$stdout.GetAwaiter().GetResult() | Set-Content (Join-Path $inventoryDir 'stdout.log') -Encoding UTF8
|
||||
$stderr.GetAwaiter().GetResult() | Set-Content (Join-Path $inventoryDir 'stderr.log') -Encoding UTF8
|
||||
$status.inventoryExit='0x{0:X8}' -f [BitConverter]::ToUInt32([BitConverter]::GetBytes([int]$process.ExitCode),0)
|
||||
if ($timedOut -or $process.ExitCode) { throw 'HIP could not detect your GPU. The diagnostic ZIP contains the details.' }
|
||||
} finally { $process.Dispose() }
|
||||
$inventory=Get-Content -LiteralPath (Join-Path $inventoryDir 'gpu-inventory.json') -Raw | ConvertFrom-Json
|
||||
$devices=@($inventory.devices | Where-Object { $_.buildEligible -and $_.wavefrontSize -eq 32 -and $manifest.targets.PSObject.Properties.Name -contains $_.architecture } | Sort-Object vramBytes -Descending)
|
||||
if (!$devices.Count) { throw 'No supported RDNA3/RDNA4 HIP device was detected. See the GPU inventory in the diagnostic ZIP.' }
|
||||
$device=$devices[0]
|
||||
if (@($devices.architecture | Select-Object -Unique).Count -gt 1) {
|
||||
for ($i=0; $i -lt $devices.Count; $i++) { Write-Host "$($i+1): $($devices[$i].name) ($($devices[$i].architecture))" }
|
||||
$choice=Read-Host 'Select the GPU used by your game (press Enter for 1)'
|
||||
if ($choice) {
|
||||
$index=0
|
||||
if (![int]::TryParse($choice,[ref]$index) -or $index -lt 1 -or $index -gt $devices.Count) { throw 'Invalid GPU selection.' }
|
||||
$device=$devices[$index-1]
|
||||
}
|
||||
}
|
||||
$arch=$device.architecture; $target=$manifest.targets.$arch
|
||||
$status.gpu=$device; $status.binarySourceCommit=$target.binarySourceCommit
|
||||
Write-Host "Detected: $($device.name) / $arch" -ForegroundColor Cyan
|
||||
Write-Host 'Experimental build. This run is a correctness test, not an FPS benchmark.'
|
||||
$previousGame=if ($saved) { $saved.game } else { $null }
|
||||
if (!$GameExe -and $previousGame -and (Test-Path -LiteralPath $previousGame)) {
|
||||
Write-Host "Remembered game: $previousGame"
|
||||
$reuse=Read-Host 'Press Enter to use this game, or type C to choose another (restore the old game first)'
|
||||
if ($reuse -match '^(?i)c$') { $previousGame=$null }
|
||||
elseif ($reuse) { throw 'Invalid choice. Press Enter or type C on the next run.' }
|
||||
}
|
||||
$GameExe=Select-LocalFile 'Select the actual D3D12 game .exe (not Steam or a launcher)' '*.exe' $(if ($GameExe) { $GameExe } else { $previousGame })
|
||||
$NgxCore=Select-LocalFile 'Select your ORIGINAL NVIDIA _nvngx.dll (32.0.16.1714)' '_nvngx.dll' $(if ($NgxCore) { $NgxCore } elseif ($saved) { $saved.ngxCore })
|
||||
$DlssDll=Select-LocalFile 'Select your NVIDIA nvngx_dlss.dll (310.9.1)' 'nvngx_dlss.dll' $(if ($DlssDll) { $DlssDll } elseif ($saved) { $saved.dlssDll })
|
||||
$status.game=$GameExe
|
||||
$status.localDlls=@($NgxCore,$DlssDll | ForEach-Object { $item=Get-Item -LiteralPath $_; @{path=$item.FullName; version=$item.VersionInfo.FileVersion; sha256=(Get-FileHash -LiteralPath $_ -Algorithm SHA256).Hash} })
|
||||
if ((Get-FileHash -LiteralPath $NgxCore -Algorithm SHA256).Hash -ne $manifest.ngxCoreSha256) {
|
||||
throw 'Wrong _nvngx.dll. This test needs the original NVIDIA 32.0.16.1714 DLL, not the d4r shim. Select the correct file on the next run.'
|
||||
}
|
||||
if ((Get-FileHash -LiteralPath $DlssDll -Algorithm SHA256).Hash -ne $target.dlssSha256) {
|
||||
throw 'Wrong nvngx_dlss.dll. This test needs exactly NVIDIA DLSS 310.9.1. Select the correct file on the next run.'
|
||||
}
|
||||
if ($GameExe.StartsWith($root+'\',[StringComparison]::OrdinalIgnoreCase)) { throw 'Select the installed GAME executable, outside this extracted package.' }
|
||||
# Save only validated choices. Wrong DLLs are never remembered.
|
||||
@{game=$GameExe; ngxCore=$NgxCore; dlssDll=$DlssDll; architecture=$arch} | ConvertTo-Json | Set-Content -LiteralPath $settingsPath -Encoding UTF8
|
||||
$selectedPackage=Join-Path $work "package-$arch"
|
||||
New-Item -ItemType Directory -Force $selectedPackage | Out-Null
|
||||
$selectedFiles=@()
|
||||
foreach ($file in $manifest.commonFiles) {
|
||||
Copy-Payload (Join-Path $PSScriptRoot 'common') $selectedPackage $file.path
|
||||
$selectedFiles+=$file
|
||||
}
|
||||
foreach ($file in $target.files) {
|
||||
Copy-Payload (Join-Path $PSScriptRoot "targets/$arch") $selectedPackage $file.path
|
||||
$selectedFiles+=$file
|
||||
}
|
||||
@{architecture=$arch; d4rCommit=$target.binarySourceCommit; packageCommit=$manifest.packageCommit;
|
||||
dlssSha256=$target.dlssSha256; hardwareValidation=$target.hardwareValidation; files=$selectedFiles} |
|
||||
ConvertTo-Json -Depth 8 | Set-Content -LiteralPath (Join-Path $selectedPackage 'package.json') -Encoding UTF8
|
||||
Write-Host 'Original game files will be backed up. RESTORE-GAME.cmd reverses the installation.'
|
||||
Write-Host 'In the game: select DLSS if available; otherwise select FSR/XeSS to let OptiScaler intercept it.'
|
||||
Write-Host 'The first launch compiles shaders and can take several minutes. Then play for 30 seconds and EXIT the game normally.'
|
||||
& (Join-Path $selectedPackage 'windows-game.ps1') -Action $Action -GameExe $GameExe -NgxCore $NgxCore -DlssDll $DlssDll `
|
||||
-Preset $Preset -ValidateOutput -CaptureExceptions -OutputDirectory $output
|
||||
if ($Action -eq 'install') { $status.status='installed-only' }
|
||||
else {
|
||||
$summary=Get-Content -LiteralPath (Join-Path $output 'summary.json') -Raw | ConvertFrom-Json
|
||||
$status.gameSummary=$summary
|
||||
$required=Get-Content -LiteralPath (Join-Path $selectedPackage 'd4r/native/d4r-kernels.txt') | Where-Object {
|
||||
if ($Preset -eq 11) { $_ -match '^dltss_pwin_' } else { $_ -match '^rrlite_' }
|
||||
} | ForEach-Object { $_.Split(' ')[0] }
|
||||
$hits=@($summary.kernels | Where-Object { $_.backend -eq 'native' -and $_.launches -gt 0 } | ForEach-Object { $_.kernel })
|
||||
$status.missingNativeKernels=@($required | Where-Object { $hits -notcontains $_ })
|
||||
$status.translatedNativeKernels=@($summary.kernels | Where-Object { $_.backend -eq 'translated' -and $required -contains $_.kernel } | ForEach-Object { $_.kernel })
|
||||
$passed=$summary.exitCode -eq '0x0' -and $summary.completedFrames -gt 0 -and $summary.nativeLaunches -gt 0 -and
|
||||
$summary.outputGpuChecks -gt 0 -and $summary.failures -eq 0 -and $summary.nonfiniteOutputs -eq 0 -and
|
||||
$summary.previousFrameOutputs -eq 0 -and $summary.cpuImageCopyFrames -eq 0 -and
|
||||
@($required).Count -eq $(if ($Preset -eq 11) { 11 } else { 5 }) -and
|
||||
$status.missingNativeKernels.Count -eq 0 -and $status.translatedNativeKernels.Count -eq 0
|
||||
$status.hardwareValidationCompleted=[bool]$passed
|
||||
$status.status=if ($passed) { 'backend-checks-passed-image-still-needs-user-review' } else { 'backend-checks-failed-or-no-dlss-frames' }
|
||||
Write-Host $(if ($passed) { 'Backend checks PASSED. Please also report whether the image looked correct.' } else { 'Test did not pass. Send the diagnostic ZIP; do not guess from the FPS.' }) -ForegroundColor $(if ($passed) { 'Green' } else { 'Yellow' })
|
||||
}
|
||||
} catch {
|
||||
$status.status='failed'; $status.error=$_.Exception.Message
|
||||
$_ | Out-String | Set-Content -LiteralPath (Join-Path $output 'error.txt') -Encoding UTF8
|
||||
Write-Host "TEST STOPPED: $($status.error)" -ForegroundColor Red
|
||||
} finally {
|
||||
if ($selectedPackage) {
|
||||
$preflights=Join-Path $selectedPackage 'results'
|
||||
$latest=Get-ChildItem -LiteralPath $preflights -Directory -ErrorAction SilentlyContinue | Sort-Object Name -Descending | Select-Object -First 1
|
||||
if ($latest) { Copy-Item -LiteralPath $latest.FullName -Destination (Join-Path $output 'preflight') -Recurse -Force }
|
||||
}
|
||||
try { Get-CimInstance Win32_VideoController | Select-Object Name,DriverVersion,DriverDate | ConvertTo-Json | Set-Content -LiteralPath (Join-Path $output 'driver.json') -Encoding UTF8 } catch {}
|
||||
$status | ConvertTo-Json -Depth 12 | Set-Content -LiteralPath (Join-Path $output 'quick-test.json') -Encoding UTF8
|
||||
Compress-Archive -LiteralPath $output -DestinationPath ($output+'.zip') -Force
|
||||
Write-Host "SEND THIS ONE FILE: $output.zip" -ForegroundColor Cyan
|
||||
Write-Host 'Also tell us: GPU model, game name, K or M, and whether the image was correct.'
|
||||
Write-Host 'Close the game before running RESTORE-GAME.cmd.'
|
||||
}
|
||||
if ($status.status -eq 'failed' -or $status.status -eq 'backend-checks-failed-or-no-dlss-frames') { exit 1 }
|
||||
@@ -0,0 +1,67 @@
|
||||
# Isolated installer checks; never starts a real game or launches GPU kernels.
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory=$true)][string]$PackageRoot,
|
||||
[Parameter(Mandatory=$true)][string]$NgxCore,
|
||||
[Parameter(Mandatory=$true)][string]$DlssDll,
|
||||
[string]$OutputDirectory
|
||||
)
|
||||
$ErrorActionPreference='Stop'
|
||||
$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
|
||||
$PackageRoot=(Get-Item -LiteralPath $PackageRoot).FullName
|
||||
if (!$OutputDirectory) { $OutputDirectory=Join-Path $repo ('test-results/windows-quick-test/'+(Get-Date -Format 'yyyyMMdd-HHmmss-fff')) }
|
||||
$OutputDirectory=[IO.Path]::GetFullPath($OutputDirectory)
|
||||
New-Item -ItemType Directory -Force $OutputDirectory | Out-Null
|
||||
function Invoke-Child([string]$Name,[string[]]$Arguments,[int]$ExpectedExit=0) {
|
||||
$log=Join-Path $OutputDirectory "$Name.log"
|
||||
& "$env:SystemRoot/System32/WindowsPowerShell/v1.0/powershell.exe" -NoProfile -STA -ExecutionPolicy Bypass `
|
||||
-File (Join-Path $PackageRoot 'files/quick-test.ps1') @Arguments *> $log
|
||||
if ($LASTEXITCODE -ne $ExpectedExit) { throw "Unexpected exit $LASTEXITCODE for $Name; see $log" }
|
||||
}
|
||||
function Fixture([string]$Name) {
|
||||
$dir=Join-Path $OutputDirectory $Name
|
||||
New-Item -ItemType Directory -Force $dir | Out-Null
|
||||
$exe=Join-Path $dir 'Fixture.exe'
|
||||
Set-Content -LiteralPath $exe 'installer fixture; do not execute' -Encoding ASCII
|
||||
return $exe
|
||||
}
|
||||
$results=@()
|
||||
$exe=Fixture ('space GPU '+[char]0x03a9+' test')
|
||||
$game=Split-Path $exe
|
||||
$before=@{}
|
||||
foreach ($name in @('dxgi.dll','OptiScaler.ini')) {
|
||||
Set-Content -LiteralPath (Join-Path $game $name) "original $name" -Encoding ASCII
|
||||
$before[$name]=(Get-FileHash -LiteralPath (Join-Path $game $name)).Hash
|
||||
}
|
||||
Invoke-Child 'install' @('-Action','install','-GameExe',$exe,'-NgxCore',$NgxCore,'-DlssDll',$DlssDll)
|
||||
$saved=Get-Content -LiteralPath (Join-Path $PackageRoot 'work/settings.json') -Raw | ConvertFrom-Json
|
||||
if ($saved.game -ne $exe -or $saved.architecture -ne 'gfx1201') { throw 'GPU detection or remembered selection failed on this RX9070XT fixture.' }
|
||||
# Restore uses remembered game selection and needs neither HIP nor NVIDIA DLLs.
|
||||
Invoke-Child 'restore' @('-Action','restore')
|
||||
foreach ($name in $before.Keys) { if ((Get-FileHash -LiteralPath (Join-Path $game $name)).Hash -ne $before[$name]) { throw 'Original game bytes not restored.' } }
|
||||
if (Test-Path -LiteralPath (Join-Path $game 'd4r')) { throw 'Runtime directory remains after restore.' }
|
||||
$results+=@{case='auto-gfx1201-install-remember-restore'; passed=$true; gpuKernelsExecuted=$false}
|
||||
foreach ($case in @('wrong-core','wrong-dlss','vkd3d')) {
|
||||
$exe=Fixture $case; $game=Split-Path $exe
|
||||
$core=if ($case -eq 'wrong-core') { Join-Path $PackageRoot 'files/targets/gfx1201/d4r/_nvngx.dll' } else { $NgxCore }
|
||||
$dlss=if ($case -eq 'wrong-dlss') { $NgxCore } else { $DlssDll }
|
||||
if ($case -eq 'vkd3d') { Set-Content -LiteralPath (Join-Path $game 'd3d12.dll') 'vkd3d-proton fixture; do not load' -Encoding ASCII }
|
||||
Invoke-Child $case @('-Action','install','-GameExe',$exe,'-NgxCore',$core,'-DlssDll',$dlss) 1
|
||||
if ((Test-Path -LiteralPath (Join-Path $game '.d4r-backup')) -or (Test-Path -LiteralPath (Join-Path $game 'dxgi.dll'))) { throw "$case changed game files before rejection." }
|
||||
$message=Get-Content -LiteralPath (Join-Path $OutputDirectory "$case.log") -Raw
|
||||
$match=[regex]::Match($message,'SEND THIS ONE FILE: (.+\.zip)')
|
||||
if (!$match.Success -or !(Test-Path -LiteralPath $match.Groups[1].Value.Trim())) { throw "$case did not produce its single report ZIP." }
|
||||
$results+=@{case=$case; passed=$true; rejectedBeforeGameChanges=$true; gpuKernelsExecuted=$false}
|
||||
}
|
||||
$readme=Join-Path $PackageRoot 'READ-ME-FIRST.txt'
|
||||
$original=[IO.File]::ReadAllBytes($readme)
|
||||
try {
|
||||
Add-Content -LiteralPath $readme 'tampered fixture'
|
||||
$exe=Fixture 'tampered-package'
|
||||
Invoke-Child 'tampered-package' @('-Action','install','-GameExe',$exe,'-NgxCore',$NgxCore,'-DlssDll',$DlssDll) 1
|
||||
$game=Split-Path $exe
|
||||
if ((Test-Path -LiteralPath (Join-Path $game '.d4r-backup')) -or (Test-Path -LiteralPath (Join-Path $game 'dxgi.dll'))) { throw 'Tampered package changed game files.' }
|
||||
$results+=@{case='tampered-package'; passed=$true; rejectedBeforeGameChanges=$true; gpuKernelsExecuted=$false}
|
||||
} finally { [IO.File]::WriteAllBytes($readme,$original) }
|
||||
$results | ConvertTo-Json | Set-Content -LiteralPath (Join-Path $OutputDirectory 'summary.json') -Encoding UTF8
|
||||
Write-Host "PASS QUICK_TEST_FIXTURES positive=1 negative=4 real_game_untouched=1 Report: $OutputDirectory"
|
||||
Reference in new issue
Block a user