Advance native Windows RR integration, kernel tooling and local packaging

Implement native NGX feature-13 RR through a LUID-matched D3D12/Vulkan
shared-memory and timeline-fence bridge. Add owned parameter snapshots,
GPU resource lifetime handling, inherited/enhanced barriers, optional
guides, sampled input formats and depth-plane support with stencil
preservation. Separate RR initialization from the SR CUDA runtime and
expose explicit backend/model selection through player configuration.

Add synthetic bridge, snapshot and NGX lifecycle harnesses covering
camera/history/reset, parameter mutation, delayed submission, early
release, capability gating and unsupported-input rejection.

Add exact gfx11 D/E model generation, verified caches, versioned local
deployment with configuration backups, and isolated portable model
tools with pinned Python, NumPy and glslang dependencies.

Extend Windows K benchmarking and private native-cache selection.
Fix LLVM 22 emitter/helper compatibility and preserve exact-output
validation for local output-kernel optimization.

Add native FSR RR provider diagnostics, local development package
refresh tooling, installer/checker updates, FidelityFX headers and
Windows parity documentation.

Keep NVIDIA binaries, derived models and private optimized kernels out
of distributable packages. Native RR evidence remains synthetic;
game validation, FSR RR dispatch, installer integration and Linux
performance parity remain incomplete.
This commit is contained in:
ayo committed 2026-10-16 12:53:26 -04:00
1 parent 3345fffcd3
commit 247fe1092d
60 files changed
+7168 -66

No files matched your search

+11 -5
View File
@@ -4,12 +4,17 @@ param([ValidateSet('enc0','enc1','enc2','enc3','enc4','dec5','dec4','dec3','dec2
[ValidateSet('baseline','load','store','both')][string]$NonTemporal='baseline',
[ValidateSet(0,1,2,4)][int]$PosTiles=0, [switch]$ShareValues, [switch]$PrivateValues,
[switch]$PackedAccumulator,
[ValidateSet('gfx1100','gfx1101','gfx1102','gfx1103','gfx1150','gfx1151','gfx1152','gfx1153','gfx1154','gfx1200','gfx1201')]
[string]$GpuArch='gfx1201',
[string]$HipRoot, [string]$OutputDirectory)
$ErrorActionPreference='Stop'
$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$HipRoot) { $HipRoot=Join-Path $repo '.tools/therock-10.2.0a20260929/_rocm_sdk_core' }
if ($ShareValues -and $PrivateValues) { throw 'Choose shared or private V storage.' }
if (!$OutputDirectory) { $OutputDirectory=Join-Path $repo "build/native-k-experiment-$Layer-$Mode-$NonTemporal-pos$PosTiles-share$([int][bool]$ShareValues)-private$([int][bool]$PrivateValues)-packed$([int][bool]$PackedAccumulator)" }
if ($GpuArch -notmatch '^gfx12' -and ($PosTiles -or $ShareValues -or $PrivateValues -or $PackedAccumulator)) {
throw 'Token tiling and accumulator/storage experiments require gfx12.'
}
if (!$OutputDirectory) { $OutputDirectory=Join-Path $repo "build/native-k-experiment-$GpuArch-$Layer-$Mode-$NonTemporal-pos$PosTiles-share$([int][bool]$ShareValues)-private$([int][bool]$PrivateValues)-packed$([int][bool]$PackedAccumulator)" }
$OutputDirectory=[IO.Path]::GetFullPath($OutputDirectory)
foreach ($baseline in @('build/native-k-gfx1201','build/windows-rdna4-therock','dist/windows-rdna4-command-list')) {
if ($OutputDirectory.StartsWith([IO.Path]::GetFullPath((Join-Path $repo $baseline)), [StringComparison]::OrdinalIgnoreCase)) {
@@ -40,22 +45,23 @@ if ($ShareValues) {
}
if ($PackedAccumulator) { $flags+='-DD4R_K_PACKED_ACC' }
if ($PrivateValues) { $flags+='-DD4R_K_PRIVATE_V' }
if ($GpuArch -match '^gfx11') { $flags+='-DD4R_WINDOWS_GFX11_LANE_EXCHANGE' }
New-Item -ItemType Directory -Force $OutputDirectory | Out-Null
$object=Join-Path $OutputDirectory "$name.hsaco"
$arguments=@('-x','hip','-std=c++17','--offload-arch=gfx1201','--offload-device-only',
$arguments=@('-x','hip','-std=c++17',"--offload-arch=$GpuArch",'--offload-device-only',
'--no-gpu-bundle-output','-mno-wavefrontsize64','-nogpuinc','-nogpulib','-O3',
'-DD4R_DEVICE_ONLY_MINIMAL','-DD4R_K_FP16_BASELINE')+$flags+@($source,'-o',$object)
$ErrorActionPreference='Continue'
& $compiler @arguments > (Join-Path $OutputDirectory "$name.build.stdout.log") 2> (Join-Path $OutputDirectory "$name.build.stderr.log")
$ErrorActionPreference='Stop'
if ($LASTEXITCODE) { throw "Experimental K compile failed: $Layer" }
& (Join-Path (Split-Path $compiler) 'llvm-objdump.exe') --disassemble --mcpu=gfx1201 $object `
& (Join-Path (Split-Path $compiler) 'llvm-objdump.exe') --disassemble "--mcpu=$GpuArch" $object `
> (Join-Path $OutputDirectory "$name.isa.txt")
if ($LASTEXITCODE) { throw 'Native object ISA extraction failed.' }
& (Join-Path (Split-Path $compiler) 'llvm-readobj.exe') --notes $object `
> (Join-Path $OutputDirectory "$name.metadata.txt")
if ($LASTEXITCODE) { throw 'Native object metadata extraction failed.' }
@{layer=$Layer; architecture='gfx1201'; experimental=$true; numericalValidation='pending';
@{layer=$Layer; architecture=$GpuArch; experimental=$true; numericalValidation='pending';
mode=$Mode; nonTemporal=$NonTemporal; tokenTilesPerWave=$PosTiles; shareValues=[bool]$ShareValues;
privateValues=[bool]$PrivateValues;
packedAccumulator=[bool]$PackedAccumulator;
@@ -64,5 +70,5 @@ if ($LASTEXITCODE) { throw 'Native object metadata extraction failed.' }
compilerVersion=(& $compiler --version | Out-String).Trim();
sha256=(Get-FileHash -LiteralPath $object -Algorithm SHA256).Hash} |
ConvertTo-Json -Depth 4 | Set-Content -LiteralPath (Join-Path $OutputDirectory "$name.build-info.json") -Encoding UTF8
Write-Host "Compiled gfx1201 K experiment: $Layer mode=$Mode nonTemporal=$NonTemporal posTiles=$PosTiles shareValues=$([bool]$ShareValues). Validate before installing."
Write-Host "Compiled $GpuArch K experiment: $Layer mode=$Mode nonTemporal=$NonTemporal posTiles=$PosTiles shareValues=$([bool]$ShareValues). Validate before installing."
# No override manifest or game installation is produced by this script.
+18 -4
View File
@@ -3,7 +3,8 @@ param(
[Parameter(Mandatory=$true)][string]$DlssdDll,
[ValidateSet('D','E')][string]$Preset='D',
[string]$OutputDirectory,
[string]$GitBash='C:\Program Files\Git\bin\bash.exe'
[string]$GitBash='C:\Program Files\Git\bin\bash.exe',
[switch]$ReuseCache
)
$ErrorActionPreference='Stop'
$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
@@ -18,7 +19,7 @@ $buildRoot=[IO.Path]::GetFullPath((Join-Path $repo 'build'))
if(!$OutputDirectory.StartsWith($buildRoot+'\',[StringComparison]::OrdinalIgnoreCase)){
throw "RR model output must stay under the ignored build directory: $OutputDirectory"
}
if(Test-Path -LiteralPath $OutputDirectory){throw "Use a new RR model output directory: $OutputDirectory"}
if((Test-Path -LiteralPath $OutputDirectory) -and !$ReuseCache){throw "Use a new RR model output directory or -ReuseCache: $OutputDirectory"}
$glslang=Join-Path $repo '.tools/glslang-16.6.0/bin'
$pythonHome=Split-Path (Get-Command python.exe -ErrorAction Stop).Source
$pythonShim=Join-Path $repo '.tools/rr-build-bin'
@@ -35,6 +36,8 @@ $unixOut=(& $cygpath -u $OutputDirectory).Trim()
if(!$unixRepo -or !$unixDll -or !$unixOut){throw 'Git Bash path conversion failed.'}
$oldPath=$env:PATH
$oldPythonPath=$env:PYTHONPATH
$oldGfx11=$env:D4R_RR_GFX11
$oldRelaxed=$env:D4R_RR_RELAXED
$env:PATH="$pythonShim;$pythonHome;$glslang;$(Split-Path $GitBash -Parent);$oldPath"
$env:PYTHONPATH=$pythonVendor
$env:D4R_RR_GFX11='1'
@@ -43,7 +46,16 @@ $log=Join-Path $buildRoot ("native-rr-$($Preset.ToLower())-windows-build.log")
try{
& $python3 -c 'import numpy; print("numpy", numpy.__version__)'
if($LASTEXITCODE){throw 'Pinned NumPy could not load in the Windows RR build environment.'}
$command="cd '$unixRepo' && D4R_RR_GFX11=1 D4R_RR_RELAXED=0 bash engine/rr/build_native_model.sh --dll '$unixDll' '$Preset' '$unixOut'"
$cacheArguments=@('--model',$OutputDirectory,'--dll',$DlssdDll,'--preset',$Preset,
'--glslang',(Join-Path $glslang 'glslangValidator.exe'),'--bash',$GitBash)
$cacheTool=Join-Path $PSScriptRoot 'rr-model-cache.py'
if(Test-Path -LiteralPath $OutputDirectory){
& $python3 $cacheTool check @cacheArguments
if($LASTEXITCODE){throw 'RR model cache is absent, stale or changed. Use a new output directory.'}
return
}
function Quote-Bash([string]$Value){return "'"+$Value.Replace("'","'\''")+"'"}
$command="cd $(Quote-Bash $unixRepo) && D4R_RR_GFX11=1 D4R_RR_RELAXED=0 bash engine/rr/build_native_model.sh --dll $(Quote-Bash $unixDll) '$Preset' $(Quote-Bash $unixOut)"
$previousPreference=$ErrorActionPreference
try{
$ErrorActionPreference='Continue'
@@ -54,6 +66,8 @@ try{
foreach($required in @('rr.txt','model.json','enc0_m.spv','dec0_m.spv','hkpn.spv','enc0.args','hkpn.args')){
if(!(Test-Path -LiteralPath (Join-Path $OutputDirectory $required))){throw "RR build incomplete; missing $required"}
}
& $python3 $cacheTool write @cacheArguments
if($LASTEXITCODE){throw 'RR build completed but cache manifest could not be written.'}
Write-Host "Built local preset $Preset native RR model: $OutputDirectory"
Write-Host "DLL SHA256: $hash. Build log: $log"
}finally{$env:PATH=$oldPath;$env:PYTHONPATH=$oldPythonPath}
}finally{$env:PATH=$oldPath;$env:PYTHONPATH=$oldPythonPath;$env:D4R_RR_GFX11=$oldGfx11;$env:D4R_RR_RELAXED=$oldRelaxed}
+28 -5
View File
@@ -1,14 +1,26 @@
[CmdletBinding()]
param([string]$SourceRoot, [string]$HipRoot = 'C:\Program Files\AMD\ROCm\7.2', [string]$WorkRoot)
param([string]$SourceRoot, [string]$HipRoot = 'C:\Program Files\AMD\ROCm\7.2', [string]$WorkRoot, [string]$LlvmBuildRoot)
$ErrorActionPreference = 'Stop'
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$SourceRoot) { $SourceRoot = Join-Path $repo 'external/ZLUDA' }
if (!$WorkRoot) { $WorkRoot = Join-Path $repo 'build/zluda-helpers-windows' }
$toolchain = Join-Path $repo '.tools/llvm-mingw-20260922-ucrt-x86_64'
$compiler = Join-Path $HipRoot 'bin/clang++.exe'
$dis = Join-Path $HipRoot 'bin/llvm-dis.exe'
$assembler = Join-Path $HipRoot 'bin/llvm-as.exe'
$ocml = Join-Path $HipRoot 'amdgcn/bitcode/ocml.bc'
function Find-HipHelperTool([string]$Name) {
foreach ($folder in @('lib/llvm/bin','bin')) {
$candidate=Join-Path $HipRoot "$folder/$Name.exe"
if(Test-Path -LiteralPath $candidate){return $candidate}
}
throw "HIP helper tool missing: $Name under $HipRoot"
}
$compiler = Find-HipHelperTool 'clang++'
$dis = Find-HipHelperTool 'llvm-dis'
$assembler = Find-HipHelperTool 'llvm-as'
if(!$LlvmBuildRoot){$LlvmBuildRoot=Join-Path $repo 'build/zluda-llvm-windows-gnu'}
$pinnedAssembler=Join-Path $LlvmBuildRoot 'bin/llvm-as.exe'
if(!(Test-Path -LiteralPath $pinnedAssembler)){throw 'Build the pinned LLVM llvm-as target before the PTX helpers.'}
$assembler=$pinnedAssembler
$ocml = Join-Path $HipRoot 'lib/llvm/amdgcn/bitcode/ocml.bc'
if(!(Test-Path -LiteralPath $ocml)){$ocml=Join-Path $HipRoot 'amdgcn/bitcode/ocml.bc'}
foreach ($file in @($compiler,$dis,$assembler,$ocml)) {
if (!(Test-Path $file)) { throw "HIP helper dependency missing: $file" }
}
@@ -58,13 +70,24 @@ foreach ($variant in $variants) {
if ($LASTEXITCODE) { throw "Disassemble failed: $raw" }
$clean = [Collections.Generic.List[string]]::new()
foreach ($line in [IO.File]::ReadLines($ir)) {
# Directly linked helpers do not need a ThinLTO index, which may retain
# references to the stripped HIP/LLVM globals.
if ($line -match '^\^\d+\s*=') { continue }
if ($line -match '@llvm.used|wchar_size|llvm.module.flags|__hip_cuid') { continue }
$line = $line -replace 'optnone','' -replace 'define hidden','define linkonce_odr'
$line = $line -replace '"target-cpu"="gfx1030"','' -replace '"target-features"="[^"]+"',''
$clean.Add($line)
}
[IO.File]::WriteAllLines($ir,$clean,[Text.UTF8Encoding]::new($false))
if($assembler -eq $pinnedAssembler){
& python (Join-Path $repo 'tools/windows/llvm22_ir.py') $ir $ir
if($LASTEXITCODE){throw 'LLVM 22 helper IR compatibility conversion failed.'}
}
$previousPath=$env:PATH
$env:PATH="$(Join-Path $toolchain 'bin');$previousPath"
try {
& $assembler $ir -o $output
if ($LASTEXITCODE) { throw "Assemble failed: $ir" }
} finally {$env:PATH=$previousPath}
Write-Host "Built $output ($((Get-Item $output).Length) bytes)"
}
+1 -1
View File
@@ -31,7 +31,7 @@ try {
$ErrorActionPreference = 'Stop'
if ($LASTEXITCODE) { throw "LLVM configure failed ($LASTEXITCODE)" }
$ErrorActionPreference = 'Continue'
& $cmake --build $BuildRoot --parallel $Jobs --target llvm-config llvm-libraries lldCommon lldELF `
& $cmake --build $BuildRoot --parallel $Jobs --target llvm-config llvm-libraries lldCommon lldELF llvm-as `
2>&1 | Tee-Object (Join-Path $BuildRoot 'build.log')
$ErrorActionPreference = 'Stop'
if ($LASTEXITCODE) { throw "LLVM build failed ($LASTEXITCODE)" }
+26 -13
View File
@@ -1,10 +1,10 @@
[CmdletBinding()]
param([string]$SourceRoot, [string]$LlvmBuildRoot, [string]$InstallRoot, [switch]$FetchOnly, [switch]$CacheTestsOnly, [switch]$CompilerTestsOnly, [int]$Jobs = 4)
param([string]$SourceRoot, [string]$LlvmBuildRoot, [string]$InstallRoot, [switch]$FetchOnly, [switch]$CacheTestsOnly, [switch]$CompilerTestsOnly, [switch]$EmitterOnly, [int]$Jobs = 4)
$ErrorActionPreference = 'Stop'
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$SourceRoot) { $SourceRoot = Join-Path $repo 'external/ZLUDA' }
if (!$LlvmBuildRoot) { $LlvmBuildRoot = Join-Path $repo 'build/zluda-llvm-windows-gnu' }
if (!$InstallRoot) { $InstallRoot = Join-Path $repo 'dist/zluda-windows-final' }
if (!$InstallRoot) { $InstallRoot = Join-Path $repo $(if ($EmitterOnly) { 'dist/zluda-windows-emitter' } else { 'dist/zluda-windows-final' }) }
$rust = Join-Path $repo '.tools/rust-1.98.1-gnu'
$toolchain = Join-Path $repo '.tools/llvm-mingw-20260922-ucrt-x86_64'
$target = Join-Path $repo 'build/zluda-rust-windows-gnu'
@@ -60,28 +60,41 @@ try {
foreach ($variant in @('','_constrained','_w64','_constrained_w64')) {
if (!(Test-Path "ptx/lib/zluda_ptx_impl$variant.bc")) { throw 'Run build-zluda-helpers.ps1 first.' }
}
$ErrorActionPreference = 'Continue'
& $cargo build --locked --release --target x86_64-pc-windows-gnu -p zluda -p nvapi -p zluda_trace `
2>&1 | Tee-Object (Join-Path $target 'build.log')
$ErrorActionPreference = 'Stop'
if ($LASTEXITCODE) { throw "ZLUDA build failed ($LASTEXITCODE)" }
if (!$EmitterOnly) {
$ErrorActionPreference = 'Continue'
& $cargo build --locked --release --target x86_64-pc-windows-gnu -p zluda -p nvapi -p zluda_trace `
2>&1 | Tee-Object (Join-Path $target 'build.log')
$ErrorActionPreference = 'Stop'
if ($LASTEXITCODE) { throw "ZLUDA build failed ($LASTEXITCODE)" }
}
$ErrorActionPreference = 'Continue'
& $cargo build --locked --release --target x86_64-pc-windows-gnu -p ptx --example d4r_emit `
2>&1 | Tee-Object (Join-Path $target 'emit-build.log')
$ErrorActionPreference = 'Stop'
if ($LASTEXITCODE) { throw "d4r_emit build failed ($LASTEXITCODE)" }
$release = Join-Path $target 'x86_64-pc-windows-gnu/release'
Copy-Item -LiteralPath (Join-Path $release 'nvcuda.dll') -Destination $InstallRoot -Force
Copy-Item -LiteralPath (Join-Path $release 'nvapi64.dll') -Destination $InstallRoot -Force
if (!$EmitterOnly) {
Copy-Item -LiteralPath (Join-Path $release 'nvcuda.dll') -Destination $InstallRoot -Force
Copy-Item -LiteralPath (Join-Path $release 'nvapi64.dll') -Destination $InstallRoot -Force
}
# The C++ dependencies select libc++ dynamically even when Rust requests
# static GNU support libraries. Keep these portable runtime DLLs local.
foreach ($runtime in @('libc++.dll', 'libunwind.dll')) {
Copy-Item -LiteralPath (Join-Path $toolchain "bin/$runtime") -Destination $InstallRoot -Force
}
New-Item -ItemType Directory -Force (Join-Path $InstallRoot 'trace') | Out-Null
Copy-Item -LiteralPath (Join-Path $release 'zluda_trace.dll') -Destination (Join-Path $InstallRoot 'trace/nvcuda.dll') -Force
if (!$EmitterOnly) {
New-Item -ItemType Directory -Force (Join-Path $InstallRoot 'trace') | Out-Null
Copy-Item -LiteralPath (Join-Path $release 'zluda_trace.dll') -Destination (Join-Path $InstallRoot 'trace/nvcuda.dll') -Force
}
Copy-Item -LiteralPath (Join-Path $release 'examples/d4r_emit.exe') -Destination $InstallRoot -Force
@{base='ee2f25a180099fa42f36b2346732e1f2470a03ad'; target='x86_64-pc-windows-gnu';
if(Test-Path -LiteralPath (Join-Path $LlvmBuildRoot 'bin/llvm-as.exe')){
Copy-Item -LiteralPath (Join-Path $LlvmBuildRoot 'bin/llvm-as.exe') -Destination $InstallRoot -Force
}
@{base='ee2f25a180099fa42f36b2346732e1f2470a03ad'; target='x86_64-pc-windows-gnu'; emitterOnly=[bool]$EmitterOnly;
emitterSha256=(Get-FileHash -LiteralPath (Join-Path $InstallRoot 'd4r_emit.exe') -Algorithm SHA256).Hash;
assemblerSha256=$(if(Test-Path -LiteralPath (Join-Path $InstallRoot 'llvm-as.exe')){
(Get-FileHash -LiteralPath (Join-Path $InstallRoot 'llvm-as.exe') -Algorithm SHA256).Hash
}else{$null});
sourceCommit=(& git rev-parse HEAD); workingTreeDirty=[bool](& git status --porcelain);
rust='1.98.1'; llvm=(& (Join-Path $LlvmBuildRoot 'bin/llvm-config.exe') --version);
llvmSource=$(if (Test-Path (Join-Path $LlvmBuildRoot 'd4r-llvm-build-info.json')) {
@@ -89,7 +102,7 @@ try {
} else { $null });
files=@(Get-ChildItem -LiteralPath $InstallRoot -Filter '*.dll' | Get-FileHash -Algorithm SHA256)} |
ConvertTo-Json -Depth 5 | Set-Content -LiteralPath (Join-Path $InstallRoot 'build-info.json') -Encoding UTF8
Write-Host "Native Windows d4r ZLUDA runtime: $InstallRoot"
Write-Host "Native Windows d4r ZLUDA $(if ($EmitterOnly) { 'offline emitter' } else { 'runtime' }): $InstallRoot"
} finally {
Pop-Location
foreach ($name in $previous.Keys) { [Environment]::SetEnvironmentVariable($name,$previous[$name],'Process') }
+34 -3
View File
@@ -158,7 +158,8 @@ else {
Ok "GPU $($device.name) ($a): build present, $native native kernels"
if (!$arch) { $arch = $a }
}
if ($a -ne 'gfx1201') { Note "only the RX 9070 XT (gfx1201) has been tested on real hardware; $a is compile-tested" }
if ($a -eq 'gfx1101') { Note 'RX 7700 XT has passed native Windows synthetic checks and limited game-frame tests; broad game validation remains incomplete' }
elseif ($a -ne 'gfx1201') { Note "$a is compile-tested; no native Windows hardware validation is recorded for this target" }
}
}
if (@($inventory.devices | Where-Object { $_.wavefrontSize -eq 32 }).Count -gt 1) { Note 'several GPUs found; d4r uses the one the game renders on' }
@@ -197,7 +198,7 @@ $iniPath = Join-Path $d4r 'd4r.ini'
$model = 'K'
if (Test-Path -LiteralPath $iniPath) {
$section = ''; $iniProblems = 0
$known = @{ 'dlss.model' = 1; 'dlss.showwatermark' = 1; 'interop.asyncinterop' = 1; 'debug.validateoutput' = 1; 'debug.log' = 1; 'paths.cachedir' = 1; 'kernels.nativefp8' = 1 }
$known = @{ 'dlss.model' = 1; 'dlss.showwatermark' = 1; 'interop.asyncinterop' = 1; 'debug.validateoutput' = 1; 'debug.log' = 1; 'paths.cachedir' = 1; 'paths.nativedir' = 1; 'kernels.nativefp8' = 1; 'rayreconstruction.backend' = 1; 'rayreconstruction.modeldir' = 1 }
$boolean = @('dlss.showwatermark', 'interop.asyncinterop', 'debug.validateoutput', 'kernels.nativefp8')
foreach ($raw in (Read-TextFile $iniPath).TrimStart([char]0xFEFF) -split "`n") {
$line = $raw.Trim()
@@ -212,11 +213,41 @@ if (Test-Path -LiteralPath $iniPath) {
elseif ($name -eq 'dlss.model') {
if (@('', 'auto', 'k', 'dlss4', '11') -contains $v) { $model = 'K' }
elseif (@('m', 'dlss4.5', '13') -contains $v) { $model = 'M' }
else { Note "d4r.ini: [DLSS] Model '$value' is not available on Windows (use K or M); K will be used"; $iniProblems++ }
elseif (@('e', '5') -contains $v) { $model = 'E' }
elseif (@('l', '12') -contains $v) { $model = 'L' }
else { Note "d4r.ini: [DLSS] Model '$value' is not available on Windows (use E, K, L or M); K will be used"; $iniProblems++ }
}
elseif ($boolean -contains $name) {
if (@('', 'auto', '1', 'true', 'yes', 'on', '0', 'false', 'no', 'off') -notcontains $v) { Note "d4r.ini: [$section] $key must be true or false, not '$value'; the default will be used"; $iniProblems++ }
}
elseif ($name -eq 'rayreconstruction.backend') {
if ($v -notin @('', 'auto', 'off', 'native', 'fsr')) { Note 'd4r.ini: [RayReconstruction] Backend must be off, native or fsr; off will be used'; $iniProblems++ }
elseif ($v -eq 'fsr') { Note 'Native Windows FSR RR is unavailable; RR requests will be rejected' }
}
elseif ($name -eq 'paths.nativedir' -and $v -notin @('', 'auto')) {
$privateNative=if([IO.Path]::IsPathRooted($value)){$value}else{Join-Path $d4r $value}
if($arch -and (Test-Path -LiteralPath (Join-Path $privateNative $arch))){$privateNative=Join-Path $privateNative $arch}
$privateObjects=@(Get-ChildItem -LiteralPath $privateNative -Filter '*.hsaco' -ErrorAction SilentlyContinue)
if(!$privateObjects.Count -or !(Test-Path -LiteralPath (Join-Path $privateNative 'd4r-kernels.txt'))){
Bad '[Paths] NativeDir must contain the complete native kernel set and d4r-kernels.txt';$iniProblems++
}else{
foreach($requiredNative in @(Get-ChildItem -LiteralPath (Join-Path $d4r "native\$arch") -Filter '*.hsaco' -ErrorAction SilentlyContinue)){
if(!(Test-Path -LiteralPath (Join-Path $privateNative $requiredNative.Name))){
Bad "NativeDir is incomplete; missing $($requiredNative.Name)";$iniProblems++
}
}
$privateTarget=@($registry | Where-Object architecture -eq $arch) | Select-Object -First 1
foreach($object in $privateObjects){
$stream=[IO.File]::OpenRead($object.FullName)
try{$header=New-Object byte[] 64;$read=$stream.Read($header,0,64)}finally{$stream.Dispose()}
if($privateTarget -and ($read -ne 64 -or $header[0] -ne 127 -or $header[1] -ne 69 -or
$header[2] -ne 76 -or $header[3] -ne 70 -or $header[48] -ne $privateTarget.elfMachine)){
Bad "NativeDir $($object.Name) is not built for $arch";$iniProblems++
}
}
if(!$iniProblems){Ok "private native kernel directory: $privateNative"}
}
}
elseif ($name -eq 'debug.log' -and @('', 'auto', 'normal', 'verbose') -notcontains $v) { Note "d4r.ini: [Debug] Log must be normal or verbose, not '$value'; normal will be used"; $iniProblems++ }
}
if (!$iniProblems) { Ok "d4r.ini is valid (model $model)" }
+19 -8
View File
@@ -1,6 +1,6 @@
# 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
# Builds the Windows drag-in release: extract it into the game folder and run
# install.bat for the pinned local NVIDIA dependencies. No game launcher is
# required. Inputs are the per-target game packages that
# package-windows-game.ps1 produces (the same inputs as the quick test).
[CmdletBinding()]
param(
@@ -8,17 +8,27 @@ param(
[Parameter(Mandatory=$true)][string]$LoaderDll,
[Parameter(Mandatory=$true)][string]$PackageRoot,
[string[]]$Architectures, # default: every target in gpu-targets.json; a subset makes a smaller release
[string]$ArchivePath
[string]$ArchivePath,
[switch]$LocalDevelopment
)
$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($LocalDevelopment){
$buildRoot=[IO.Path]::GetFullPath((Join-Path $repo 'build'))+'\'
foreach($candidate in @($PackageRoot,$ArchivePath) | Where-Object { $_ }){
if(!([IO.Path]::GetFullPath($candidate)).StartsWith($buildRoot,[StringComparison]::OrdinalIgnoreCase)){
throw 'Local development packages and ZIPs must stay under ignored build/.'
}
}
}
if (Test-Path -LiteralPath $PackageRoot) { throw 'Use a new output directory to avoid mixing releases.' }
$git=Get-Command git -ErrorAction SilentlyContinue
$workingTreeDirty=(!$git -or [bool](& git -C $repo status --porcelain))
$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.' }
if ($ArchivePath -and !$LocalDevelopment -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) {
@@ -35,7 +45,7 @@ if (!$selected.Count -or ($Architectures -and $selected.Count -ne @($Architectur
foreach ($gpu in $selected) {
$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 ($metadata.architecture -ne $arch -or ($metadata.d4rWorkingTreeDirty -and !$LocalDevelopment)) { 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
@@ -83,11 +93,12 @@ $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')) }) {
if (Get-ChildItem -LiteralPath $PackageRoot -Recurse -File | Where-Object { $_.Name -in @('nvngx_dlss.dll','nvngx_dlssd.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;
$manifest=[ordered]@{schema=1; kind='windows-drag-in'; localDevelopment=[bool]$LocalDevelopment;
packageWorkingTreeDirty=[bool]$workingTreeDirty; 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
@@ -0,0 +1,57 @@
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)][string]$DlssDll,
[Parameter(Mandatory=$true)][string]$NativeDirectory,
[Parameter(Mandatory=$true)][string]$OutputDirectory,
[string]$HipRoot,
[string]$EmitterRoot,
[string]$GpuArch='gfx1101',
[string]$Kernel='hiluma_engine_output_depthreg_mvhi_ldr_max_v2_rel'
)
$ErrorActionPreference='Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
[void](Get-D4RGpuTargetInfo $GpuArch)
$DlssDll=(Get-Item -LiteralPath $DlssDll).FullName
$NativeDirectory=(Get-Item -LiteralPath $NativeDirectory).FullName
$OutputDirectory=[IO.Path]::GetFullPath($OutputDirectory)
$buildRoot=[IO.Path]::GetFullPath((Join-Path $repo 'build'))+'\'
if(!$OutputDirectory.StartsWith($buildRoot,[StringComparison]::OrdinalIgnoreCase)){
throw 'Private generated kernels must stay under ignored build/.'
}
if(Test-Path -LiteralPath $OutputDirectory){throw 'Use a new private cache directory.'}
$expected='3975567b8943c53acce397f2b72380092f84f162d00b0d2c7d08a1025c563983'
if((Get-FileHash -LiteralPath $DlssDll).Hash.ToLowerInvariant() -ne $expected){throw 'Expected pinned DLSS SR 310.9.1.'}
if(!$HipRoot){$HipRoot=Join-Path $repo '.tools/therock-10.2.0a20260929/_rocm_sdk_core'}
if(!$EmitterRoot){$EmitterRoot=Join-Path $repo 'dist/zluda-windows-emitter'}
$objects=@(Get-ChildItem -LiteralPath $NativeDirectory -Filter '*.hsaco' -File)
if($objects.Count -ne 16){throw 'NativeDirectory must contain the baseline 11 K and 5 M objects.'}
foreach($family in @('k','m')){
foreach($source in Get-ChildItem -LiteralPath (Join-Path $repo "kernels/$family") -Filter '*.hip' -File){
if(!(Test-Path -LiteralPath (Join-Path $NativeDirectory ($source.BaseName+'.hsaco')))){
throw "Baseline native directory is incomplete: $($source.BaseName)"
}
}
}
foreach($object in $objects){Assert-D4RCodeObjectTarget $object.FullName $GpuArch}
& (Join-Path $PSScriptRoot 'build-native-texture.ps1') -DlssDll $DlssDll -Kernel $Kernel `
-HipRoot $HipRoot -ZludaRoot $EmitterRoot -GpuArch $GpuArch -OutputDirectory (Join-Path $OutputDirectory 'texture')
if($LASTEXITCODE){throw 'Private texture build failed.'}
$native=Join-Path $OutputDirectory 'native'
New-Item -ItemType Directory -Path $native | Out-Null
foreach($object in $objects){Copy-Item -LiteralPath $object.FullName -Destination $native}
foreach($marker in @('d4r-native-fp8.txt')){
if(Test-Path -LiteralPath (Join-Path $NativeDirectory $marker)){
Copy-Item -LiteralPath (Join-Path $NativeDirectory $marker) -Destination $native
}
}
Copy-Item -LiteralPath (Join-Path $OutputDirectory "texture/$Kernel.hsaco") -Destination $native
& python (Join-Path $repo 'kernels/tools/kernel_manifest.py') $native $DlssDll
if($LASTEXITCODE){throw 'Private native manifest generation failed.'}
@{schema=1; architecture=$GpuArch; privateNvidiaDerivedCode=$true; nativeDirectory=$native;
dlssSha256=$expected; kernel=$Kernel; validation='built only; validate complete frames before game use';
files=@(Get-ChildItem -LiteralPath $native -File | ForEach-Object {
@{name=$_.Name; sha256=(Get-FileHash -LiteralPath $_.FullName).Hash}
})} | ConvertTo-Json -Depth 5 | Set-Content -LiteralPath (Join-Path $OutputDirectory 'cache.json') -Encoding UTF8
Write-Host 'Private cache built; no game or existing configuration changed.'
Write-Host "After validation, set [Paths] NativeDir = $native"
+72
View File
@@ -0,0 +1,72 @@
"""Stamp or verify local RR build artifacts against sources, tools and DLL identity."""
import argparse
import hashlib
import json
from pathlib import Path
import sys
def sha(path):
return hashlib.sha256(path.read_bytes()).hexdigest()
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('action', choices=('write', 'check'))
parser.add_argument('--model', type=Path, required=True)
parser.add_argument('--dll', type=Path, required=True)
parser.add_argument('--preset', choices=('D', 'E'), required=True)
parser.add_argument('--glslang', type=Path, required=True)
parser.add_argument('--bash', type=Path, required=True)
args = parser.parse_args()
repo = Path(__file__).resolve().parents[2]
model = args.model.resolve()
if not model.is_relative_to((repo / 'build').resolve()):
parser.error('model cache must stay under ignored build/')
import numpy
sources = {}
for directory in ('engine', 'vulkan', 'kernels/tools', 'scripts/windows'):
for path in sorted((repo / directory).rglob('*')):
if path.is_file() and path.suffix in ('.py', '.ps1', '.sh', '.comp', '.glsl', '.h', '.inc', '.txt'):
sources[path.relative_to(repo).as_posix()] = sha(path)
identity = dict(schema=1, preset=args.preset, architecture='gfx1101', arithmetic='exact-gfx11',
numpyVersion=numpy.__version__, sources=sources,
tools={name: sha(path) for name, path in (
('dll', args.dll), ('glslang', args.glslang),
('bash', args.bash), ('python', Path(sys.executable)))})
stamp = model / 'windows-rr-cache.json'
products = {path.name: sha(path) for path in sorted(model.iterdir())
if path.is_file() and path.name not in (stamp.name, stamp.name + '.tmp')}
for name in ('rr.txt', 'model.json', 'enc0_m.spv', 'dec0_m.spv', 'hkpn.spv', 'enc0.args', 'hkpn.args'):
if name not in products:
raise RuntimeError(f'incomplete model: {name}')
manifest = (model / 'rr.txt').read_text().splitlines()
if (not manifest or manifest[0] != 'D4RR0001' or
f'preset {4 if args.preset == "D" else 5}' not in manifest or
'arithmetic gfx11' not in manifest):
raise RuntimeError('RR manifest preset/arithmetic does not match requested cache identity')
stages = [line.split() for line in manifest if line.startswith('stage ')]
expected_stages = {'enc0', 'enc1', 'enc2', 'enc3', 'enc4', 'enc5',
'dec4', 'dec3', 'dec2', 'dec1', 'dec0', 'hkpn'}
if len(stages) != 12 or {fields[1] for fields in stages} != expected_stages:
raise RuntimeError('RR stage list is incomplete or duplicated')
for fields in stages:
for name in (fields[2], fields[4]):
if name != '-' and name not in products:
raise RuntimeError(f'RR stage artifact missing or outside model directory: {name}')
if args.action == 'check':
cached = json.loads(stamp.read_text())
if cached.get('identity') != identity:
raise RuntimeError('RR cache identity changed; use a new output directory to rebuild')
if cached.get('products') != products:
raise RuntimeError('RR cache artifacts changed; use a new output directory to rebuild')
print(f'RR_CACHE_HIT preset={args.preset} artifacts={len(products)} model={model}')
else:
temporary = stamp.with_name(stamp.name + '.tmp')
temporary.write_text(json.dumps(dict(identity=identity, products=products), indent=2) + '\n')
temporary.replace(stamp)
print(f'RR_CACHE_WRITTEN preset={args.preset} artifacts={len(products)} model={model}')
if __name__ == '__main__':
main()
+54
View File
@@ -0,0 +1,54 @@
#!/usr/bin/env python3
"""Generate deterministic RR replay inputs. This is a dispatch smoke, not a quality reference."""
import argparse
import json
import math
from pathlib import Path
import struct
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('output', type=Path)
parser.add_argument('--width', type=int, default=64)
parser.add_argument('--height', type=int, default=64)
parser.add_argument('--frames', type=int, default=3)
parser.add_argument('--output-width', type=int)
parser.add_argument('--output-height', type=int)
args = parser.parse_args()
if not (32 <= args.width <= 1024 and 32 <= args.height <= 1024 and 1 <= args.frames <= 32):
parser.error('width/height must be 32..1024; frames must be 1..32')
if bool(args.output_width) != bool(args.output_height):
parser.error('supply both output dimensions')
ow, oh = args.output_width or args.width * 2, args.output_height or args.height * 2
if not (1 <= ow <= 2560 and 1 <= oh <= 1440):
parser.error('output must fit 2560x1440')
args.output.mkdir(parents=True, exist_ok=False)
identity = '1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1'
lines = [f'size {args.width} {args.height} {ow} {oh}']
for frame in range(args.frames):
data = {name: bytearray() for name in ('color', 'motion', 'depth', 'normals', 'roughness', 'diffuse', 'specular')}
for y in range(args.height):
for x in range(args.width):
u, v = x / (args.width - 1), y / (args.height - 1)
noise = math.sin(x * 1.7 + y * 2.3 + frame) * 0.025
data['color'] += struct.pack('<4e', 0.1 + u + noise, 0.1 + v + noise, 0.2 + u * v, 1)
data['motion'] += struct.pack('<2e', 0, 0)
data['depth'] += struct.pack('<f', 1 + v)
data['normals'] += struct.pack('<4e', 0, 0, 1, 1)
data['roughness'] += struct.pack('<4e', 0.5, 0.5, 0.5, 0.5)
data['diffuse'] += bytes((128, 160, 192, 255))
data['specular'] += bytes((10, 10, 10, 255))
for name, blob in data.items():
(args.output / f'{frame}-{name}.bin').write_bytes(blob)
lines.append(f'frame {frame} 0 0 1 1 1 {int(frame == 0)} 0 {identity} {identity}')
(args.output / 'frames.txt').write_text('\n'.join(lines) + '\n', encoding='ascii')
(args.output / 'synthetic.json').write_text(json.dumps({
'kind': 'synthetic-dispatch-only', 'render': [args.width, args.height],
'output': [ow, oh], 'frames': args.frames,
'quality_reference': False,
}, indent=2) + '\n', encoding='ascii')
if __name__ == '__main__':
main()
+27
View File
@@ -0,0 +1,27 @@
[CmdletBinding()]
param()
$ErrorActionPreference='Stop'
$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
$directory=Join-Path $repo '.tools/fsr-rr-1.2'
$dll=Join-Path $directory 'amd_fidelityfx_denoiser_dx12.dll'
$expected='48f1e5888ba6a0a3d59a98b9751e37c392b0f7b8c223d0082d5c1f40642879d3'
$url='https://raw.githubusercontent.com/GPUOpen-LibrariesAndSDKs/FidelityFX-SDK/v2.3.0/Kits/FidelityFX/signedbin/amd_fidelityfx_denoiser_dx12.dll'
New-Item -ItemType Directory -Path $directory -Force | Out-Null
if(Test-Path -LiteralPath $dll){
if((Get-FileHash -LiteralPath $dll -Algorithm SHA256).Hash.ToLowerInvariant() -ne $expected){
throw "Existing denoiser hash mismatch; refusing to replace $dll"
}
}else{
$temporary=Join-Path $directory ([Guid]::NewGuid().ToString('N')+'.download')
try{
Invoke-WebRequest -Uri $url -OutFile $temporary -UseBasicParsing
if((Get-FileHash -LiteralPath $temporary -Algorithm SHA256).Hash.ToLowerInvariant() -ne $expected){
throw 'AMD denoiser download hash mismatch.'
}
Move-Item -LiteralPath $temporary -Destination $dll
}finally{
if(Test-Path -LiteralPath $temporary){Remove-Item -LiteralPath $temporary}
}
}
Write-Host "Pinned AMD denoiser ready: $dll"
Write-Host 'Provider availability and execution still require test-fsr-rr.ps1.'
+20 -3
View File
@@ -57,7 +57,7 @@ function Expect([string]$case,$run,[int]$exit,[string[]]$patterns) {
$game=New-Install 'healthy'; $inv=Write-Inventory 'a' 'gfx1101'
Expect 'healthy-install' (Run-Check $game $inv) 0 @('ok\s+d4r\\dlss\\nvngx_dlss\.dll \(nvngx_dlss\.dll 310\.9\.1, tested on Windows\)','ok\s+d4r\\ngx\\_nvngx\.dll',
'ok\s+GPU AMD Radeon RX 7700 XT \(gfx1101\): build present, 16 native kernels','ok\s+all 17 GPU code objects are built for gfx1101',
'ok\s+no vkd3d/Wine d3d12\.dll','ok\s+d4r\.ini is valid \(model K\)','compile-tested','Everything d4r needs is in place')
'ok\s+no vkd3d/Wine d3d12\.dll','ok\s+d4r\.ini is valid \(model K\)','RX 7700 XT has passed native Windows synthetic checks','Everything d4r needs is in place')
# 2. NVIDIA DLL problems, each with the fix.
$game=New-Install 'dll-missing'; Remove-Item -LiteralPath (Join-Path $game 'd4r/dlss/nvngx_dlss.dll')
@@ -78,8 +78,8 @@ $game=New-Install 'opti-path'; (Get-Content -LiteralPath (Join-Path $game 'OptiS
Expect 'optiscaler-ini-path' (Run-Check $game $inv) 1 @('MISSING\s+OptiScaler\.ini NvngxPath = nowhere does not hold _nvngx\.dll')
# 4. d4r.ini mistakes are notes with what will happen instead.
$game=New-Install 'ini'; Set-Content -LiteralPath (Join-Path $game 'd4r/d4r.ini') "[DLSS]`nModel = E`nShowWatermark = sometimes`n[Latency]`nFrameAge = 1`n[Debug]`nLog = loud`n" -Encoding ASCII
Expect 'ini-mistakes' (Run-Check $game $inv) 0 @("note\s+d4r\.ini: \[DLSS\] Model 'E' is not available on Windows",'must be true or false, not ''sometimes''','\[Latency\] FrameAge is not a Windows setting','Log must be normal or verbose')
$game=New-Install 'ini'; Set-Content -LiteralPath (Join-Path $game 'd4r/d4r.ini') "[DLSS]`nModel = Z`nShowWatermark = sometimes`n[Latency]`nFrameAge = 1`n[Debug]`nLog = loud`n" -Encoding ASCII
Expect 'ini-mistakes' (Run-Check $game $inv) 0 @("note\s+d4r\.ini: \[DLSS\] Model 'Z' is not available on Windows",'must be true or false, not ''sometimes''','\[Latency\] FrameAge is not a Windows setting','Log must be normal or verbose')
# 5. GPU cases.
$game=New-Install 'gpu-no-build'; Remove-Item -LiteralPath (Join-Path $game 'd4r/_nvngx_gfx1103.dll')
@@ -119,5 +119,22 @@ $exitEmpty=$LASTEXITCODE; $ErrorActionPreference='Stop'
if ($exitEmpty -ne 1 -or $text -notmatch 'no d4r folder here') { throw "A folder without d4r must be reported.`n$text" }
$results+=@{case='no-d4r-folder'; passed=$true}
foreach($preset in @('E','L')){
$game=New-Install "ini-$preset"
Set-Content -LiteralPath (Join-Path $game 'd4r/d4r.ini') "[DLSS]`nModel=$preset`n" -Encoding ASCII
Expect "ini-$preset" (Run-Check $game $inv) 0 @("d4r.ini is valid \(model $preset\)")
}
$game=New-Install 'private-native'
$private=Join-Path $game 'd4r/private-native'
New-Item -ItemType Directory -Path $private | Out-Null
Copy-Item (Join-Path $game 'd4r/native/gfx1101/*') $private
Set-Content -LiteralPath (Join-Path $game 'd4r/d4r.ini') "[Paths]`nNativeDir=private-native`n" -Encoding ASCII
Expect 'private-native-valid' (Run-Check $game $inv) 0 @('ok\s+private native kernel directory')
$object=Get-ChildItem -LiteralPath $private -Filter '*.hsaco' | Select-Object -First 1
$header=[IO.File]::ReadAllBytes($object.FullName);$header[48]=0;[IO.File]::WriteAllBytes($object.FullName,$header)
Expect 'private-native-target-rejected' (Run-Check $game $inv) 1 @('NativeDir .* is not built for gfx1101')
Remove-Item -LiteralPath $object.FullName
Expect 'private-native-incomplete-rejected' (Run-Check $game $inv) 1 @('NativeDir is incomplete')
$results | ConvertTo-Json -Depth 4 | Set-Content -LiteralPath (Join-Path $OutputDirectory 'summary.json') -Encoding UTF8
Write-Host "PASS D4R_CHECK cases=$($results.Count) Report: $OutputDirectory"
+45
View File
@@ -0,0 +1,45 @@
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)][string]$Probe,
[Parameter(Mandatory=$true)][string]$DenoiserDll,
[Parameter(Mandatory=$true)][string]$OutputDirectory,
[switch]$QueryOnly,
[ValidateRange(1,600)][int]$TimeoutSeconds=120
)
$ErrorActionPreference='Stop'
$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
$Probe=(Get-Item -LiteralPath $Probe).FullName
$DenoiserDll=(Get-Item -LiteralPath $DenoiserDll).FullName
$expected='48f1e5888ba6a0a3d59a98b9751e37c392b0f7b8c223d0082d5c1f40642879d3'
if((Get-FileHash -LiteralPath $DenoiserDll -Algorithm SHA256).Hash.ToLowerInvariant() -ne $expected){
throw 'Expected unmodified AMD SDK 2.3 denoiser 1.2.0.2740.'
}
$OutputDirectory=[IO.Path]::GetFullPath($OutputDirectory)
$buildRoot=[IO.Path]::GetFullPath((Join-Path $repo 'build'))
if(!$OutputDirectory.StartsWith($buildRoot+'\',[StringComparison]::OrdinalIgnoreCase)){
throw 'Probe output must stay under the ignored build directory.'
}
if(Test-Path -LiteralPath $OutputDirectory){throw 'Use a new probe output directory.'}
New-Item -ItemType Directory -Path $OutputDirectory | Out-Null
# Start-Process joins arguments into one command line. Reject embedded quotes;
# quote absolute file paths so spaces in the workspace are supported.
foreach($path in @($DenoiserDll,$OutputDirectory)){
if($path.Contains('"')){throw 'Embedded quotes are not supported in probe paths.'}
}
$arguments='"'+$DenoiserDll+'" "'+$OutputDirectory+'" --size 64x64 --frames 48'
if($QueryOnly){$arguments+=' --query-only'}
$process=Start-Process -FilePath $Probe -ArgumentList $arguments -WindowStyle Hidden -PassThru `
-RedirectStandardOutput (Join-Path $OutputDirectory 'stdout.log') `
-RedirectStandardError (Join-Path $OutputDirectory 'stderr.log')
try{
$deadline=[DateTime]::UtcNow.AddSeconds($TimeoutSeconds)
while(!$process.WaitForExit(1000)){
if([DateTime]::UtcNow -ge $deadline){
Stop-Process -Id $process.Id -ErrorAction SilentlyContinue
throw "FSR RR probe timed out after $TimeoutSeconds seconds; exact probe process stopped."
}
}
$process.WaitForExit()
Get-Content -LiteralPath (Join-Path $OutputDirectory 'stdout.log')
if($process.ExitCode -ne 0){throw "FSR RR probe failed ($($process.ExitCode)); see $OutputDirectory"}
}finally{$process.Dispose()}
+53
View File
@@ -0,0 +1,53 @@
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)][string]$Probe,
[Parameter(Mandatory=$true)][string]$ModelDirectory,
[Parameter(Mandatory=$true)][string]$InputDirectory,
[Parameter(Mandatory=$true)][string]$ReferenceDirectory,
[Parameter(Mandatory=$true)][string]$OutputDirectory
)
$ErrorActionPreference='Stop'
$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
foreach($name in @('Probe','ModelDirectory','InputDirectory','ReferenceDirectory')){
Set-Variable -Name $name -Value ((Get-Item -LiteralPath (Get-Variable -Name $name -ValueOnly)).FullName)
}
$OutputDirectory=[IO.Path]::GetFullPath($OutputDirectory)
if(!$OutputDirectory.StartsWith([IO.Path]::GetFullPath((Join-Path $repo 'build'))+'\',[StringComparison]::OrdinalIgnoreCase)){
throw 'RR bridge outputs must stay under ignored build/.'
}
if(Test-Path -LiteralPath $OutputDirectory){throw 'Use a fresh RR bridge output directory.'}
New-Item -ItemType Directory -Path $OutputDirectory | Out-Null
$frames=@(Get-Content -LiteralPath (Join-Path $InputDirectory 'frames.txt') | Where-Object {$_ -match '^frame '}).Count
if(!$frames -or $frames -gt 32){throw 'Need 1..32 RR fixture frames.'}
$arguments=@('--rr-model',$ModelDirectory,'--rr-inputs',$InputDirectory,'--rr-reference',$ReferenceDirectory,
'--rr-output',(Join-Path $OutputDirectory 'frames'))
foreach($value in $arguments){if($value.Contains('"')){throw 'Embedded quotes are not supported in probe paths.'}}
$quoted=($arguments | ForEach-Object {'"'+$_+'"'}) -join ' '
$process=Start-Process -FilePath $Probe -ArgumentList $quoted -WindowStyle Hidden -PassThru `
-RedirectStandardOutput (Join-Path $OutputDirectory 'stdout.log') `
-RedirectStandardError (Join-Path $OutputDirectory 'stderr.log')
try{
$deadline=[DateTime]::UtcNow.AddSeconds(180)
while(!$process.WaitForExit(1000)){
if([DateTime]::UtcNow -ge $deadline){Stop-Process -Id $process.Id;throw 'Exact RR bridge process stopped at 180-second limit.'}
}
$process.WaitForExit()
$text=Get-Content -LiteralPath (Join-Path $OutputDirectory 'stdout.log') -Raw
Get-Content -LiteralPath (Join-Path $OutputDirectory 'stdout.log')
$records=[regex]::Matches($text,'(?m)^RR_BRIDGED_FRAME .*finite=1 nonuniform=1 standalone_exact=1 ')
if($process.ExitCode -ne 0 -or $records.Count -ne $frames -or $text -notmatch 'PASS RR_BRIDGED_INFERENCE'){
Get-Content -LiteralPath (Join-Path $OutputDirectory 'stderr.log')
throw "RR bridged inference failed ($($process.ExitCode)); see $OutputDirectory"
}
$outputs=@(Get-ChildItem -LiteralPath (Join-Path $OutputDirectory 'frames') -Filter '*-out.bin')
if($outputs.Count -ne $frames){throw 'Incomplete RR output file set.'}
foreach($output in $outputs){
if((Get-FileHash -LiteralPath $output.FullName).Hash -ne (Get-FileHash -LiteralPath (Join-Path $ReferenceDirectory $output.Name)).Hash){
throw 'Independent bridged/reference output hash comparison failed.'
}
}
@{passed=$true;frames=$frames;guides=7;standaloneExact=$true;gpuFenceHandoff=$true;
gameAccessed=$false;qualityReference=$false;d3d12Textures=$true;probeSha256=(Get-FileHash -LiteralPath $Probe).Hash;
model=$ModelDirectory;inputs=$InputDirectory;reference=$ReferenceDirectory} |
ConvertTo-Json -Depth 4 | Set-Content -LiteralPath (Join-Path $OutputDirectory 'summary.json') -Encoding UTF8
}finally{$process.Dispose()}
+47
View File
@@ -0,0 +1,47 @@
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)][string]$Probe,
[Parameter(Mandatory=$true)][string]$OutputDirectory
)
$ErrorActionPreference='Stop'
$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
$Probe=(Get-Item -LiteralPath $Probe).FullName
$OutputDirectory=[IO.Path]::GetFullPath($OutputDirectory)
if(!$OutputDirectory.StartsWith([IO.Path]::GetFullPath((Join-Path $repo 'build'))+'\',[StringComparison]::OrdinalIgnoreCase)){
throw 'RR interop probe reports must stay under ignored build/.'
}
if(Test-Path -LiteralPath $OutputDirectory){throw 'Use a new output directory.'}
New-Item -ItemType Directory -Path $OutputDirectory | Out-Null
$cases=@(
@{name='smoke';bytes=1048576;iterations=8},
@{name='render-colour-1712x960-rgba16f-padded';bytes=13271040;iterations=3;width=1712;height=960},
@{name='output-colour-2560x1440-rgba16f';bytes=29491200;iterations=3;width=2560;height=1440}
)
$results=@()
foreach($case in $cases){
$stdout=Join-Path $OutputDirectory "$($case.name).stdout.log"
$stderr=Join-Path $OutputDirectory "$($case.name).stderr.log"
$arguments=@('--bytes',"$($case.bytes)",'--iterations',"$($case.iterations)")
if($case.width){$arguments+=@('--image-width',"$($case.width)",'--image-height',"$($case.height)")}
$process=Start-Process -FilePath $Probe -ArgumentList $arguments `
-WindowStyle Hidden -PassThru -RedirectStandardOutput $stdout -RedirectStandardError $stderr
try{
if(!$process.WaitForExit(30000)){
Stop-Process -Id $process.Id -ErrorAction SilentlyContinue
throw "Exact RR interop probe stopped after 30 seconds: $($case.name)"
}
$process.WaitForExit()
$text=Get-Content -LiteralPath $stdout -Raw
$records=[regex]::Matches($text,'(?m)^RR_INTEROP_ITERATION .* exact=1 ')
if($process.ExitCode -ne 0 -or $records.Count -ne $case.iterations -or
$text -notmatch 'PASS RR_INTEROP_TRANSFER .*gpu_fence_handoff=1 .*inference_executed=0'){
throw "RR interop case failed ($($process.ExitCode)): $($case.name); see $OutputDirectory"
}
if($case.width -and $text -notmatch 'canonical_image=1'){throw 'Canonical image path was not exercised.'}
$results+=@{name=$case.name;bytes=$case.bytes;iterations=$case.iterations;exactBothDirections=$true;canonicalImage=[bool]$case.width}
Write-Host "PASS RR_INTEROP $($case.name): $($case.iterations) iterations, $($case.bytes) bytes"
}finally{$process.Dispose()}
}
@{passed=$true;probeSha256=(Get-FileHash -LiteralPath $Probe).Hash;cases=$results;
gpuFenceHandoff=$true;inferenceExecuted=$false;gameAccessed=$false} |
ConvertTo-Json -Depth 5 | Set-Content -LiteralPath (Join-Path $OutputDirectory 'summary.json') -Encoding UTF8
@@ -107,5 +107,36 @@ try { Invoke-Package $prefix (Join-Path $OutputDirectory 'release-runtime') } ca
if (!$rejected) { throw 'A differing shared runtime was not rejected.' }
$results+=@{case='shared-runtime-mismatch-rejected'; passed=$true}
# Local ZIPs may include uncommitted inputs, but remain under ignored build/ and
# preserve all target/hash/runtime checks. This fixture is never a usable game ZIP.
$prefix=Join-Path $OutputDirectory 'inputs/development/game'
New-Inputs $prefix
foreach($target in $targets){
$metadataPath="$prefix-$($target.architecture)/package.json"
$metadata=Get-Content -LiteralPath $metadataPath -Raw | ConvertFrom-Json
$metadata.d4rWorkingTreeDirty=$true
$metadata | ConvertTo-Json -Depth 8 | Set-Content -LiteralPath $metadataPath -Encoding UTF8
}
$developmentRoot=Join-Path $repo ('build/release-development-fixture-'+[Guid]::NewGuid().ToString('N'))
$zip=Join-Path $developmentRoot 'fixture.zip'
& (Join-Path $PSScriptRoot 'package-windows-release.ps1') -GamePackagePrefix $prefix -LoaderDll $loader `
-PackageRoot (Join-Path $developmentRoot 'package') -ArchivePath $zip -LocalDevelopment | Out-Null
$metadata=Get-Content -LiteralPath (Join-Path $developmentRoot 'package/d4r/package.json') -Raw | ConvertFrom-Json
if(!$metadata.localDevelopment){throw 'Local ZIP lacks development marker.'}
$archive=[IO.Compression.ZipFile]::OpenRead($zip)
try{
foreach($required in @('install.bat','install-dlss.ps1','d4r/d4r.ini')){
if(!$archive.GetEntry($required)){throw "Local ZIP lacks $required"}
}
}finally{$archive.Dispose()}
$results+=@{case='local-development-zip'; passed=$true}
$rejected=$false
try{
& (Join-Path $PSScriptRoot 'package-windows-release.ps1') -GamePackagePrefix $prefix -LoaderDll $loader `
-PackageRoot (Join-Path $repo 'dist/rejected-local-fixture') -LocalDevelopment | Out-Null
}catch{$rejected=$_.Exception.Message -match 'must stay under ignored build/'}
if(!$rejected){throw 'Local package escaped build/.'}
$results+=@{case='local-development-path-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"