Windows: drag-in install with a per-game d4r.ini
Players extract one ZIP into the game folder, copy their two NVIDIA DLLs, and start the game from Steam, Epic or a shortcut. No launcher script is needed; settings live in d4r\d4r.ini. - Shim player mode: when the launcher has not set D4R_HIP_ROOT and d4r.ini sits beside the shim, derive the backend environment from it. Codegen flags stay at the Windows-validated values. NVIDIA DLLs must match an exact SHA256 in dll-pins.txt, with "you have X, you need Y" errors. Rejects a vkd3d/Wine d3d12.dll and code objects built for another GPU. [DLSS] Model accepts K or M and is applied by rewriting the render preset hints. - d4r.ini exposes only options that exist on Windows: Model, AsyncInterop, ValidateOutput, Log, CacheDir. Invalid values fall back with a note in d4r_nvngx.log. - d4r_nvngx_loader: one _nvngx.dll for all GPUs. It matches the game's adapter by LUID and loads _nvngx_<arch>.dll from the same folder. - OptiScaler patch 0006: relative NvngxPath/NvngxDlssPath/ NvngxFeaturePath resolve against OptiScaler's folder. - package-windows-release.ps1 builds the release from the per-target game packages and refuses mixed targets or differing shared runtimes. - Tests: test-player-config.ps1 (ini and DLL-pin decisions, loader selection on the local GPU) and test-windows-release-package.ps1.
This commit is contained in:
1 parent
7ab56d42fc
commit
65ab1460a8
13 files changed
+1004
-1
No files matched your search
@@ -0,0 +1,98 @@
|
||||
# Builds the Windows drag-in release: extract it into the game folder, copy
|
||||
# the two NVIDIA DLLs, edit d4r\d4r.ini. Like the Linux release, no installer
|
||||
# or launcher is involved. Inputs are the per-target game packages that
|
||||
# package-windows-game.ps1 produces (the same inputs as the quick test).
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[string]$GamePackagePrefix,
|
||||
[Parameter(Mandatory=$true)][string]$LoaderDll,
|
||||
[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.' }
|
||||
$git=Get-Command git -ErrorAction SilentlyContinue
|
||||
$commit=if ($git) { (& git -C $repo rev-parse HEAD).Trim() } else { $null }
|
||||
if ($ArchivePath -and (!$git -or [bool](& git -C $repo status --porcelain))) { throw 'A public ZIP needs git and committed sources.' }
|
||||
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
|
||||
if (Test-Path -LiteralPath $destination) { throw "Duplicate release path: $Relative" }
|
||||
New-Item -ItemType Directory -Force (Split-Path $destination) | Out-Null
|
||||
Copy-Item -LiteralPath $Source -Destination $destination
|
||||
$item=Get-Item -LiteralPath $destination
|
||||
$files.Add(@{path=$Relative.Replace('\','/'); sha256=(Get-FileHash -LiteralPath $destination -Algorithm SHA256).Hash; version=$item.VersionInfo.FileVersion})
|
||||
}
|
||||
$targets=[ordered]@{}; $baseline=$null; $commonStaged=$false
|
||||
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" }
|
||||
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.' }
|
||||
$objects=0
|
||||
foreach ($file in $metadata.files) {
|
||||
$relative=$file.path.Replace('\','/'); $path=Join-Path $source $file.path
|
||||
if ((Get-FileHash -LiteralPath $path -Algorithm SHA256).Hash -ne $file.sha256) { throw "Input file changed: $source/$relative" }
|
||||
if ($relative.EndsWith('.hsaco')) { Assert-D4RCodeObjectTarget $path $arch; $objects++ }
|
||||
# Per-target files get target-specific names so one folder serves every GPU.
|
||||
if ($relative -eq 'd4r/_nvngx.dll') { Stage $path "d4r/_nvngx_$arch.dll" }
|
||||
elseif ($relative -eq 'd4r/nvapi/nvapi64.dll') { Stage $path "d4r/nvapi/$arch/nvapi64.dll" }
|
||||
elseif ($relative -like 'd4r/pixel_convert_*.hsaco') { Stage $path $relative }
|
||||
elseif ($relative.StartsWith('d4r/native/')) { Stage $path ("d4r/native/$arch/" + $relative.Substring('d4r/native/'.Length)) }
|
||||
elseif ($relative -eq 'OptiScaler.dll' -or $relative.StartsWith('licenses/') -or
|
||||
($relative.StartsWith('d4r/hip/') -or $relative.StartsWith('d4r/zluda/'))) {
|
||||
$public=if ($relative -eq 'OptiScaler.dll') { 'dxgi.dll' } elseif ($relative.StartsWith('licenses/')) { "d4r/$relative" } else { $relative }
|
||||
if (!$commonStaged) { Stage $path $public }
|
||||
elseif ((Get-FileHash -LiteralPath (Join-Path $PackageRoot $public) -Algorithm SHA256).Hash -ne $file.sha256) { throw "Shared runtime differs in $arch : $relative" }
|
||||
}
|
||||
# Installer-only files (launcher, inventory, PowerShell, docs) are not part of a drag-in install.
|
||||
}
|
||||
if ($objects -ne 17) { throw "Expected 17 code objects for $arch" }
|
||||
$commonStaged=$true
|
||||
$targets[$arch]=@{binarySourceCommit=$metadata.d4rCommit; hardwareValidation=$metadata.hardwareValidation}
|
||||
}
|
||||
$loader=(Get-Item -LiteralPath $LoaderDll).FullName
|
||||
if ([IO.Path]::GetFileName($loader) -ne 'd4r_nvngx_loader.dll') { throw 'Pass the d4r_nvngx_loader.dll built by CMake.' }
|
||||
Stage $loader 'd4r/_nvngx.dll'
|
||||
Stage (Join-Path $repo 'packaging/windows/OptiScaler.ini') 'OptiScaler.ini'
|
||||
Stage (Join-Path $repo 'packaging/windows/d4r.ini') 'd4r/d4r.ini'
|
||||
Stage (Join-Path $repo 'tools/windows/dll-pins.txt') 'd4r/dll-pins.txt'
|
||||
foreach ($optional in @(@{source='packaging/windows/WINDOWS_README.txt'; path='WINDOWS_README.txt'},
|
||||
@{source='scripts/windows/d4r-check.ps1'; path='d4r/d4r-check.ps1'})) {
|
||||
$path=Join-Path $repo $optional.source
|
||||
if (Test-Path -LiteralPath $path) { Stage $path $optional.path }
|
||||
}
|
||||
# Shows players where the NGX core goes; a ZIP cannot carry an empty folder.
|
||||
$placeholder=Join-Path $PackageRoot 'd4r/ngx/PUT _nvngx.dll HERE.txt'
|
||||
New-Item -ItemType Directory -Force (Split-Path $placeholder) | Out-Null
|
||||
"Copy NVIDIA's _nvngx.dll into this folder. See WINDOWS_README.txt." | Set-Content -LiteralPath $placeholder -Encoding ASCII
|
||||
$files.Add(@{path='d4r/ngx/PUT _nvngx.dll HERE.txt'; sha256=(Get-FileHash -LiteralPath $placeholder -Algorithm SHA256).Hash; version=$null})
|
||||
if (Get-ChildItem -LiteralPath $PackageRoot -Recurse -File | Where-Object { $_.Name -eq 'nvngx_dlss.dll' -or ($_.Name -eq '_nvngx.dll' -and $_.DirectoryName -ne (Join-Path $PackageRoot 'd4r')) }) {
|
||||
throw 'Proprietary NVIDIA binaries must not be in the release.'
|
||||
}
|
||||
# Read by d4r-check.ps1: every shipped file's hash, so a damaged or mixed install is reported.
|
||||
$manifest=[ordered]@{schema=1; kind='windows-drag-in'; packageCommit=$commit; binarySourceCommit=$baseline.d4rCommit;
|
||||
dependencies=@{optiScalerSourceCommit=$baseline.optiScaler.sourceCommit; zludaSourceCommit=$baseline.zludaBuild.sourceCommit; hipRuntime=$baseline.hipRuntime};
|
||||
targets=$targets; files=$files}
|
||||
$manifest | ConvertTo-Json -Depth 8 | Set-Content -LiteralPath (Join-Path $PackageRoot 'd4r/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)+@('d4r/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 "Windows drag-in release: $PackageRoot ($($targets.Count) GPU targets, no NVIDIA DLLs)"
|
||||
@@ -0,0 +1,88 @@
|
||||
# Drag-in player mode checks. Builds with the vendored llvm-mingw; needs no
|
||||
# NVIDIA DLLs and launches no GPU kernels. The loader case enumerates HIP
|
||||
# devices and is skipped (reported, not passed) without a supported AMD GPU.
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[string]$CompilerRoot, [string]$HipRoot, [string]$OutputDirectory
|
||||
)
|
||||
$ErrorActionPreference='Stop'
|
||||
$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
|
||||
if (!$CompilerRoot) { $CompilerRoot=Join-Path $repo '.tools/llvm-mingw-20260922-ucrt-x86_64' }
|
||||
if (!$HipRoot) { $HipRoot=Join-Path $repo '.tools/therock-10.2.0a20260929/_rocm_sdk_core' }
|
||||
if (!$OutputDirectory) { $OutputDirectory=Join-Path $repo ('test-results/player-config/'+(Get-Date -Format 'yyyyMMdd-HHmmss-fff')) }
|
||||
$OutputDirectory=[IO.Path]::GetFullPath($OutputDirectory)
|
||||
New-Item -ItemType Directory -Force $OutputDirectory | Out-Null
|
||||
$cxx=Join-Path $CompilerRoot 'bin/x86_64-w64-mingw32-clang++.exe'
|
||||
if (!(Test-Path -LiteralPath $cxx)) { throw "llvm-mingw not found: $cxx" }
|
||||
if (!(Test-Path -LiteralPath (Join-Path $HipRoot 'include/hip/hip_runtime_api.h'))) { throw "HIP headers not found under $HipRoot" }
|
||||
|
||||
# Same generated target table as CMakeLists.txt.
|
||||
$targets=(Get-Content -LiteralPath (Join-Path $repo 'tools/windows/gpu-targets.json') -Raw | ConvertFrom-Json).targets
|
||||
$generated=Join-Path $OutputDirectory 'generated'
|
||||
New-Item -ItemType Directory -Force $generated | Out-Null
|
||||
$entries=($targets | ForEach-Object { " GpuTarget{`"$($_.architecture)`", $($_.elfMachine), $($_.isaMajor), `"$($_.family)`"}," }) -join "`n"
|
||||
@('#pragma once','#include <array>','namespace d4r::diag {',
|
||||
'struct GpuTarget { const char* architecture; unsigned elf_machine; unsigned isa_major; const char* family; };',
|
||||
"inline constexpr std::array<GpuTarget, $($targets.Count)> gpu_targets = {{",$entries,'}};','}') |
|
||||
Set-Content -LiteralPath (Join-Path $generated 'gpu_targets.generated.h') -Encoding ASCII
|
||||
$common=@('-std=c++17','-O1','-static','-DWIN32_LEAN_AND_MEAN','-DNOMINMAX','-D__HIP_PLATFORM_AMD__','-DD4R_TARGET_ARCH="gfx1201"',
|
||||
'-I',$generated,'-I',(Join-Path $repo 'tools/windows'),'-I',(Join-Path $repo 'tools'),'-I',(Join-Path $HipRoot 'include'))
|
||||
# Windows PowerShell turns native stderr into terminating errors under Stop;
|
||||
# judge native tools by exit code and keep their output in the log.
|
||||
function Invoke-Native([string]$Log,[string]$Exe,[string[]]$Arguments) {
|
||||
$ErrorActionPreference='Continue'
|
||||
& $Exe @Arguments *> $Log
|
||||
return $LASTEXITCODE
|
||||
}
|
||||
function Build([string]$Name,[string[]]$Arguments) {
|
||||
$log=Join-Path $OutputDirectory "build-$Name.log"
|
||||
# PowerShell 5 strips embedded quotes from native arguments; escape them.
|
||||
if (Invoke-Native $log $cxx @($Arguments | ForEach-Object { $_.Replace('"','\"') })) { throw "Build failed: $Name; see $log" }
|
||||
}
|
||||
$results=@()
|
||||
|
||||
# 1. d4r.ini validation and DLL pin decisions (the shim's own header).
|
||||
$probe=Join-Path $OutputDirectory 'player_config_probe.exe'
|
||||
Build 'player-config' ($common+@('-municode',(Join-Path $repo 'tools/windows/player_config_probe.cpp'),'-o',$probe,'-lversion','-ldbghelp','-lbcrypt'))
|
||||
if (Invoke-Native (Join-Path $OutputDirectory 'player-config.log') $probe @((Join-Path $OutputDirectory 'pins-fixture'))) { throw "player_config_probe failed; see $(Join-Path $OutputDirectory 'player-config.log')" }
|
||||
$results+=@{case='d4r-ini-and-dll-pins'; passed=$true}
|
||||
|
||||
# 2. Loader: GPU-free marker, LUID-based target selection, forwarding, and a
|
||||
# clear failure when the folder has no build for the detected GPU.
|
||||
$folder=Join-Path $OutputDirectory 'game/d4r'
|
||||
New-Item -ItemType Directory -Force (Join-Path $folder 'hip/bin') | Out-Null
|
||||
Build 'loader' ($common+@('-shared',(Join-Path $repo 'tools/windows/d4r_nvngx_loader.cpp'),'-o',(Join-Path $folder '_nvngx.dll'),'-lversion','-ldbghelp'))
|
||||
$harness=Join-Path $OutputDirectory 'loader_selection_probe.exe'
|
||||
Build 'harness' @('-municode','-static',(Join-Path $repo 'tools/windows/loader_selection_probe.cpp'),'-o',$harness,'-ldxgi','-ldxguid')
|
||||
$stub=Join-Path $OutputDirectory 'stub.cpp'
|
||||
@('#define API extern "C" __declspec(dllexport)',
|
||||
'struct Req { unsigned FeatureSupported, MinHWArchitecture; char MinOSVersion[255]; };',
|
||||
'API unsigned NVSDK_NGX_D3D12_GetFeatureRequirements(void*, const void*, Req* r) { r->FeatureSupported = 0; r->MinHWArchitecture = 0x5101; return 1; }') |
|
||||
Set-Content -LiteralPath $stub -Encoding ASCII
|
||||
$stubDll=Join-Path $OutputDirectory 'stub.dll'
|
||||
Build 'stub' @('-shared','-static',$stub,'-o',$stubDll)
|
||||
foreach ($name in @('amdhip64_7.dll','amd_comgr.dll','rocm_kpack.dll')) {
|
||||
$source=Join-Path $HipRoot "bin/$name"
|
||||
if (Test-Path -LiteralPath $source) { Copy-Item -LiteralPath $source -Destination (Join-Path $folder 'hip/bin') }
|
||||
}
|
||||
$log=Join-Path $OutputDirectory 'loader-without-builds.log'
|
||||
[void](Invoke-Native $log $harness @((Join-Path $folder '_nvngx.dll')))
|
||||
$text=Get-Content -LiteralPath $log -Raw
|
||||
if ($text -notmatch 'MARKER version=1 hip_loaded=0') { throw "Discovery marker loaded HIP or failed; see $log" }
|
||||
if ($text -match 'supported=0') { throw "An adapter was reported supported without any target build; see $log" }
|
||||
$gpuLog=Join-Path $folder 'd4r_nvngx.log'
|
||||
$detected=$null
|
||||
if (Test-Path -LiteralPath $gpuLog) { $detected=[regex]::Match((Get-Content -LiteralPath $gpuLog -Raw),'no build for your GPU \((gfx[0-9a-f]+)\)').Groups[1].Value }
|
||||
if (!$detected) {
|
||||
$results+=@{case='loader-selection'; passed=$null; skipped='no supported AMD HIP device detected'}
|
||||
Write-Host 'SKIP loader selection: no supported AMD HIP device detected on this machine.' -ForegroundColor Yellow
|
||||
} else {
|
||||
if ((Get-Content -LiteralPath $gpuLog -Raw) -notmatch 'It supports: none \(the d4r folder is incomplete') { throw "Unclear unsupported-GPU message; see $gpuLog" }
|
||||
Copy-Item -LiteralPath $stubDll -Destination (Join-Path $folder "_nvngx_$detected.dll")
|
||||
$log=Join-Path $OutputDirectory 'loader-with-build.log'
|
||||
[void](Invoke-Native $log $harness @((Join-Path $folder '_nvngx.dll')))
|
||||
if ((Get-Content -LiteralPath $log -Raw) -notmatch 'vendor=0x1002 status=0x1 supported=0 marker=0x5101') { throw "AMD adapter was not forwarded to _nvngx_$detected.dll; see $log" }
|
||||
$results+=@{case='loader-selection'; passed=$true; architecture=$detected; gpuKernelsExecuted=$false}
|
||||
}
|
||||
$results | ConvertTo-Json | Set-Content -LiteralPath (Join-Path $OutputDirectory 'summary.json') -Encoding UTF8
|
||||
Write-Host "PASS PLAYER_CONFIG cases=$(@($results | Where-Object { $_.passed }).Count) skipped=$(@($results | Where-Object { $_.skipped }).Count) Report: $OutputDirectory"
|
||||
@@ -0,0 +1,97 @@
|
||||
# Drag-in release packaging with synthetic per-target inputs. No GPU, no
|
||||
# NVIDIA DLLs, no game. Code objects carry real AMDGPU ELF target headers.
|
||||
[CmdletBinding()]
|
||||
param([string]$OutputDirectory)
|
||||
$ErrorActionPreference='Stop'
|
||||
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
|
||||
$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
|
||||
if (!$OutputDirectory) { $OutputDirectory=Join-Path $repo ('test-results/windows-release-package/'+(Get-Date -Format 'yyyyMMdd-HHmmss-fff')) }
|
||||
$OutputDirectory=[IO.Path]::GetFullPath($OutputDirectory)
|
||||
New-Item -ItemType Directory -Force $OutputDirectory | Out-Null
|
||||
$targets=@(Get-D4RGpuTargets)
|
||||
|
||||
function Write-CodeObject([string]$Path,[int]$Machine) {
|
||||
$header=New-Object byte[] 64
|
||||
$header[0]=127; $header[1]=69; $header[2]=76; $header[3]=70; $header[4]=2; $header[5]=1; $header[18]=224; $header[48]=$Machine
|
||||
New-Item -ItemType Directory -Force (Split-Path $Path) | Out-Null
|
||||
[IO.File]::WriteAllBytes($Path,$header)
|
||||
}
|
||||
function New-Inputs([string]$Prefix,[scriptblock]$Mutate) {
|
||||
foreach ($target in $targets) {
|
||||
$arch=$target.architecture; $root="$Prefix-$arch"
|
||||
$text=@{'OptiScaler.dll'='optiscaler'; 'd4r/_nvngx.dll'="shim $arch"; 'd4r/nvapi/nvapi64.dll'="nvapi $arch";
|
||||
'd4r/hip/bin/amdhip64_7.dll'='hip'; 'd4r/zluda/nvcuda.dll'='zluda'; 'licenses/d4r.txt'='license';
|
||||
'd4r/d4r_gpu_inventory.exe'='inventory'; 'd4r/d4r_debug_launcher.exe'='launcher'; 'windows-game.ps1'='installer';
|
||||
'd4r/native/d4r-kernels.txt'='manifest'}
|
||||
foreach ($entry in $text.GetEnumerator()) {
|
||||
$path=Join-Path $root $entry.Key; New-Item -ItemType Directory -Force (Split-Path $path) | Out-Null
|
||||
Set-Content -LiteralPath $path $entry.Value -Encoding ASCII
|
||||
}
|
||||
$objects=@("d4r/pixel_convert_$arch.hsaco")+@(1..16 | ForEach-Object { "d4r/native/kernel$_.hsaco" })
|
||||
foreach ($object in $objects) { Write-CodeObject (Join-Path $root $object) $target.elfMachine }
|
||||
if ($Mutate) { & $Mutate $root $arch }
|
||||
$files=@(Get-ChildItem -LiteralPath $root -Recurse -File | Where-Object { $_.Name -ne 'package.json' } | ForEach-Object {
|
||||
@{path=$_.FullName.Substring($root.Length+1).Replace('\','/'); sha256=(Get-FileHash -LiteralPath $_.FullName -Algorithm SHA256).Hash}
|
||||
})
|
||||
@{architecture=$arch; d4rWorkingTreeDirty=$false; d4rCommit='fixture'; hardwareValidation='fixture';
|
||||
dlssSha256='3975567b8943c53acce397f2b72380092f84f162d00b0d2c7d08a1025c563983';
|
||||
zludaBuild=@{sourceCommit='fixture'}; optiScaler=@{sourceCommit='fixture'}; hipRuntime='fixture'; files=$files} |
|
||||
ConvertTo-Json -Depth 6 | Set-Content -LiteralPath (Join-Path $root 'package.json') -Encoding UTF8
|
||||
}
|
||||
}
|
||||
function Invoke-Package([string]$Prefix,[string]$Root) {
|
||||
& (Join-Path $PSScriptRoot 'package-windows-release.ps1') -GamePackagePrefix $Prefix -LoaderDll $loader -PackageRoot $Root | Out-Null
|
||||
}
|
||||
$loader=Join-Path $OutputDirectory 'build/d4r_nvngx_loader.dll'
|
||||
New-Item -ItemType Directory -Force (Split-Path $loader) | Out-Null
|
||||
Set-Content -LiteralPath $loader 'loader fixture' -Encoding ASCII
|
||||
$results=@()
|
||||
|
||||
# 1. Layout of a good release.
|
||||
$prefix=Join-Path $OutputDirectory 'inputs/good/game'
|
||||
New-Inputs $prefix
|
||||
$release=Join-Path $OutputDirectory 'release'
|
||||
Invoke-Package $prefix $release
|
||||
foreach ($path in @('dxgi.dll','OptiScaler.ini','d4r/_nvngx.dll','d4r/d4r.ini','d4r/dll-pins.txt','d4r/package.json',
|
||||
'd4r/hip/bin/amdhip64_7.dll','d4r/zluda/nvcuda.dll','d4r/licenses/d4r.txt','d4r/ngx/PUT _nvngx.dll HERE.txt')) {
|
||||
if (!(Test-Path -LiteralPath (Join-Path $release $path))) { throw "Release lacks $path" }
|
||||
}
|
||||
if ((Get-Content -LiteralPath (Join-Path $release 'd4r/_nvngx.dll') -Raw).Trim() -ne 'loader fixture') { throw 'd4r/_nvngx.dll is not the loader.' }
|
||||
foreach ($target in $targets) {
|
||||
$arch=$target.architecture
|
||||
if ((Get-Content -LiteralPath (Join-Path $release "d4r/_nvngx_$arch.dll") -Raw).Trim() -ne "shim $arch") { throw "Wrong shim for $arch" }
|
||||
if ((Get-Content -LiteralPath (Join-Path $release "d4r/nvapi/$arch/nvapi64.dll") -Raw).Trim() -ne "nvapi $arch") { throw "Wrong NVAPI for $arch" }
|
||||
Assert-D4RCodeObjectTarget (Join-Path $release "d4r/pixel_convert_$arch.hsaco") $arch
|
||||
$native=@(Get-ChildItem -LiteralPath (Join-Path $release "d4r/native/$arch") -Filter '*.hsaco')
|
||||
if ($native.Count -ne 16 -or !(Test-Path -LiteralPath (Join-Path $release "d4r/native/$arch/d4r-kernels.txt"))) { throw "Native folder for $arch is incomplete" }
|
||||
foreach ($object in $native) { Assert-D4RCodeObjectTarget $object.FullName $arch }
|
||||
}
|
||||
foreach ($excluded in @('d4r/d4r_gpu_inventory.exe','d4r/d4r_debug_launcher.exe','windows-game.ps1','d4r/native/kernel1.hsaco','d4r/nvapi/nvapi64.dll')) {
|
||||
if (Test-Path -LiteralPath (Join-Path $release $excluded)) { throw "Installer-only or untargeted file shipped: $excluded" }
|
||||
}
|
||||
$manifest=Get-Content -LiteralPath (Join-Path $release 'd4r/package.json') -Raw | ConvertFrom-Json
|
||||
foreach ($file in $manifest.files) {
|
||||
if ((Get-FileHash -LiteralPath (Join-Path $release $file.path) -Algorithm SHA256).Hash -ne $file.sha256) { throw "Manifest hash wrong: $($file.path)" }
|
||||
}
|
||||
$shipped=@(Get-ChildItem -LiteralPath $release -Recurse -File | ForEach-Object { $_.FullName.Substring($release.Length+1).Replace('\','/') } | Where-Object { $_ -ne 'd4r/package.json' })
|
||||
if (Compare-Object $shipped @($manifest.files.path)) { throw 'Manifest and shipped files differ.' }
|
||||
$results+=@{case='drag-in-layout'; passed=$true; targets=$targets.Count; files=$shipped.Count}
|
||||
|
||||
# 2. A code object for another GPU in a target's input is rejected.
|
||||
$prefix=Join-Path $OutputDirectory 'inputs/mixed/game'
|
||||
New-Inputs $prefix { param($root,$arch) if ($arch -eq 'gfx1101') { Write-CodeObject (Join-Path $root 'd4r/native/kernel3.hsaco') 65 } }
|
||||
$rejected=$false
|
||||
try { Invoke-Package $prefix (Join-Path $OutputDirectory 'release-mixed') } catch { $rejected=$_.Exception.Message -match 'does not target gfx1101' }
|
||||
if (!$rejected) { throw 'A gfx1100 code object in the gfx1101 input was not rejected.' }
|
||||
$results+=@{case='mixed-target-rejected'; passed=$true}
|
||||
|
||||
# 3. Shared runtime files must be identical across targets.
|
||||
$prefix=Join-Path $OutputDirectory 'inputs/runtime/game'
|
||||
New-Inputs $prefix { param($root,$arch) if ($arch -eq 'gfx1200') { Set-Content -LiteralPath (Join-Path $root 'd4r/zluda/nvcuda.dll') 'other zluda' -Encoding ASCII } }
|
||||
$rejected=$false
|
||||
try { Invoke-Package $prefix (Join-Path $OutputDirectory 'release-runtime') } catch { $rejected=$_.Exception.Message -match 'Shared runtime differs' }
|
||||
if (!$rejected) { throw 'A differing shared runtime was not rejected.' }
|
||||
$results+=@{case='shared-runtime-mismatch-rejected'; passed=$true}
|
||||
|
||||
$results | ConvertTo-Json | Set-Content -LiteralPath (Join-Path $OutputDirectory 'summary.json') -Encoding UTF8
|
||||
Write-Host "PASS WINDOWS_RELEASE_PACKAGE cases=$($results.Count) Report: $OutputDirectory"
|
||||
Reference in new issue
Block a user