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:
1 parent
3345fffcd3
commit
247fe1092d
60 files changed
+7168
-66
No files matched your search
@@ -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.
|
||||
@@ -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}
|
||||
@@ -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)"
|
||||
}
|
||||
@@ -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)" }
|
||||
|
||||
@@ -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') }
|
||||
|
||||
@@ -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)" }
|
||||
|
||||
@@ -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"
|
||||
@@ -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()
|
||||
@@ -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()
|
||||
@@ -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.'
|
||||
@@ -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"
|
||||
@@ -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()}
|
||||
@@ -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()}
|
||||
@@ -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"
|
||||
Reference in new issue
Block a user