Files
d4r/scripts/windows/package-windows-game.ps1
T
xdfnx-devandrealdody 3fa963fd1b Enable experimental native Windows RDNA3 and RDNA4 targets
Share explicit target metadata across build/runtime/package guards, preserve native gfx11 WMMA with a Windows LDS lane exchange, select HIP devices by D3D12 LUID, and reject wrong-target/vkd3d installations before changing game files. Review all issue #10 logs and document compile-only coverage plus RX9070XT regressions.

Co-authored-by: realdody <[email protected]>
2026-10-02 17:10:42 +03:00

136 lines
9.3 KiB
PowerShell

[CmdletBinding()]
param(
[string]$PackageRoot, [string]$DiagnosticRoot, [string]$OptiScalerRoot,
[string]$ZludaRoot, [string]$HipRoot, [string]$KernelKRoot, [string]$KernelMRoot,
[string]$GpuArch,
[string]$ArchivePath
)
$ErrorActionPreference = 'Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
$defaults = @{PackageRoot='dist/windows-rdna4-game'; DiagnosticRoot='dist/windows-rdna4-command-list';
OptiScalerRoot='dist/optiscaler-windows-d4r'; ZludaRoot='dist/zluda-windows-final';
HipRoot='.tools/therock-10.2.0a20260929/_rocm_sdk_core'}
foreach ($name in $defaults.Keys) {
if (!(Get-Variable -Name $name -ValueOnly)) { Set-Variable -Name $name -Value (Join-Path $repo $defaults[$name]) }
}
$GpuArch=Get-D4RGpuTarget $DiagnosticRoot $GpuArch
if ($GpuArch -ne 'gfx1201' -and !$PSBoundParameters.ContainsKey('PackageRoot')) { $PackageRoot += "-$GpuArch" }
if (!$KernelKRoot) { $KernelKRoot=Join-Path $repo "build/native-k-$GpuArch" }
if (!$KernelMRoot) { $KernelMRoot=Join-Path $repo "build/native-m-$GpuArch" }
foreach ($directory in @($KernelKRoot,$KernelMRoot)) {
$info=Join-Path $directory 'build-info.json'
if ((Test-Path -LiteralPath $info) -and (Get-Content -LiteralPath $info -Raw | ConvertFrom-Json).architecture -ne $GpuArch) {
throw "Native kernel directory does not target ${GpuArch}: $directory"
}
}
$PackageRoot = [IO.Path]::GetFullPath($PackageRoot)
if (Test-Path -LiteralPath (Join-Path $PackageRoot 'gpu-target.json')) {
[void](Get-D4RGpuTarget $PackageRoot $GpuArch)
}
$sourceCommit=(& git -C $repo rev-parse HEAD).Trim()
$sourceDirty=[bool](& git -C $repo status --porcelain)
if ($ArchivePath -and $sourceDirty) { throw 'Commit source changes before creating the distributable archive.' }
New-Item -ItemType Directory -Force $PackageRoot | Out-Null
$stagedFiles = [Collections.Generic.List[string]]::new()
function Stage([string]$source, [string]$relative) {
if (!(Test-Path -LiteralPath $source -PathType Leaf)) { throw "Required file missing: $source" }
if ($source.EndsWith('.hsaco')) { Assert-D4RCodeObjectTarget $source $GpuArch }
$destination = Join-Path $PackageRoot $relative
New-Item -ItemType Directory -Force (Split-Path $destination) | Out-Null
Copy-Item -LiteralPath $source -Destination $destination -Force
$stagedFiles.Add($relative)
}
Stage (Join-Path $OptiScalerRoot 'OptiScaler.dll') 'OptiScaler.dll'
Stage (Join-Path $DiagnosticRoot 'bin/d4r_nvngx.dll') 'd4r/_nvngx.dll'
Stage (Join-Path $DiagnosticRoot "bin/pixel_convert_${GpuArch}.hsaco") "d4r/pixel_convert_${GpuArch}.hsaco"
Stage (Join-Path $DiagnosticRoot 'nvapi-compat/nvapi64.dll') 'd4r/nvapi/nvapi64.dll'
Stage (Join-Path $DiagnosticRoot 'bin/d4r_debug_launcher.exe') 'd4r/d4r_debug_launcher.exe'
Stage (Join-Path $DiagnosticRoot 'bin/d4r_gpu_inventory.exe') 'd4r/d4r_gpu_inventory.exe'
foreach ($file in @('nvcuda.dll','nvapi64.dll','libc++.dll','libunwind.dll')) { Stage (Join-Path $ZludaRoot $file) "d4r/zluda/$file" }
foreach ($file in @('amdhip64_7.dll','amd_comgr.dll','hiprtc0717.dll','hiprtc-builtins0717.dll','rocm_kpack.dll','AMD.ROCM.Comgr.MANIFEST','.hipVersion')) {
Stage (Join-Path $HipRoot "bin/$file") "d4r/hip/bin/$file"
}
$entries = @{}
foreach ($directory in @($KernelKRoot, $KernelMRoot)) {
foreach ($line in Get-Content -LiteralPath (Join-Path $directory 'd4r-kernels.txt')) {
if (!$line.Trim() -or $line.StartsWith('#')) { continue }
if ($line -notmatch '^([A-Za-z0-9_]+) ([0-9a-f]{16})$') { throw "Invalid native manifest entry: $line" }
if ($entries.ContainsKey($Matches[1])) { throw "Duplicate native kernel: $($Matches[1])" }
$entries[$Matches[1]] = $line
Stage (Join-Path $directory ($Matches[1] + '.hsaco')) ('d4r/native/' + $Matches[1] + '.hsaco')
}
}
if ($entries.Count -ne 16) { throw "Expected 11 K and 5 M native objects; found $($entries.Count)" }
@("# Audited DLSS 310.9.1: K + M $GpuArch native kernels", '# Generated by package-windows-game.ps1') + @($entries.Values | Sort-Object) |
Set-Content -LiteralPath (Join-Path $PackageRoot 'd4r/native/d4r-kernels.txt') -Encoding ASCII
$stagedFiles.Add('d4r/native/d4r-kernels.txt')
Stage (Join-Path $repo 'scripts/windows/windows-game.ps1') 'windows-game.ps1'
Stage (Join-Path $repo 'scripts/windows/gpu-target.ps1') 'gpu-target.ps1'
Stage (Join-Path $repo 'scripts/windows/gpu-preflight.ps1') 'gpu-preflight.ps1'
Stage (Join-Path $repo 'tools/windows/gpu-targets.json') 'gpu-targets.json'
if (Test-Path -LiteralPath (Join-Path $DiagnosticRoot 'gpu-target.json')) {
Stage (Join-Path $DiagnosticRoot 'gpu-target.json') 'gpu-target.json'
} else {
# Builds predating target metadata were gfx1201 only. The resolver rejects
# any attempt to label such a build gfx1200.
@{schema=1; architecture=$GpuArch; wavefrontSize=32; validation='Legacy gfx1201 build; run the GPU diagnostics.'} |
ConvertTo-Json | Set-Content -LiteralPath (Join-Path $PackageRoot 'gpu-target.json') -Encoding UTF8
$stagedFiles.Add('gpu-target.json')
}
Stage (Join-Path $repo 'scripts/windows/capture-game-window.ps1') 'capture-game-window.ps1'
Stage (Join-Path $repo 'scripts/windows/send-game-key.ps1') 'send-game-key.ps1'
Stage (Join-Path $repo 'docs/windows-game.md') 'README.md'
Stage (Join-Path $repo 'docs/windows-performance.md') 'windows-performance.md'
Stage (Join-Path $repo 'docs/windows-gpu-support.md') 'windows-gpu-support.md'
Stage (Join-Path $repo 'docs/windows-rdna4-port.md') 'windows-rdna4-port.md'
Stage (Join-Path $repo 'LICENSE') 'licenses/d4r.txt'
Stage (Join-Path $OptiScalerRoot 'GPL-3.0.txt') 'licenses/OptiScaler.txt'
Stage (Join-Path $repo 'external/ZLUDA/LICENSE-MIT') 'licenses/ZLUDA-MIT.txt'
Stage (Join-Path $repo 'external/ZLUDA/LICENSE-APACHE') 'licenses/ZLUDA-APACHE.txt'
Stage (Join-Path $repo 'external/ZLUDA/ext/llvm-project/LICENSE.TXT') 'licenses/LLVM.txt'
Stage (Join-Path $repo 'external/MinHook/LICENSE.txt') 'licenses/MinHook.txt'
Stage (Join-Path $HipRoot 'share/doc/amd_comgr/LICENSE.txt') 'licenses/amd_comgr.txt'
Stage (Join-Path $repo 'external/clr/LICENSE.md') 'licenses/HIP-CLR.txt'
foreach ($patch in Get-ChildItem -LiteralPath (Join-Path $repo 'patches/optiscaler') -Filter '*.patch') { Stage $patch.FullName ('source-patches/optiscaler/' + $patch.Name) }
foreach ($patch in Get-ChildItem -LiteralPath (Join-Path $repo 'patches/zluda') -Filter '*.patch') { Stage $patch.FullName ('source-patches/zluda/' + $patch.Name) }
$sourceArchive=Join-Path $repo 'build/d4r-windows-rdna4-source.zip'
New-Item -ItemType Directory -Force (Split-Path $sourceArchive) | Out-Null
& git -C $repo archive --format=zip --output $sourceArchive $sourceCommit
if ($LASTEXITCODE) { throw 'Cannot archive the committed d4r source.' }
Stage $sourceArchive 'source/d4r-windows-rdna4-source.zip'
$metadata = [ordered]@{
architecture=$GpuArch; hardwareValidation=$(if ($GpuArch -eq 'gfx1201') { 'RX9070XT tested; other SKUs unverified' } else { 'compile-only; hardware unverified' }); nativeKernels=16; dlssSha256='3975567b8943c53acce397f2b72380092f84f162d00b0d2c7d08a1025c563983';
d4rCommit=$sourceCommit;
d4rWorkingTreeDirty=$sourceDirty;
optiScaler=(Get-Content -LiteralPath (Join-Path $OptiScalerRoot 'build-info.json') -Raw | ConvertFrom-Json);
zludaBuild=(Get-Content -LiteralPath (Join-Path $ZludaRoot 'build-info.json') -Raw | ConvertFrom-Json);
hipRuntime='TheRock 10.2.0a20260929 / HIP 7.17.26386';
files=@($stagedFiles | ForEach-Object { Get-Item -LiteralPath (Join-Path $PackageRoot $_) } | ForEach-Object {
@{path=$_.FullName.Substring($PackageRoot.Length+1); sha256=(Get-FileHash -LiteralPath $_.FullName -Algorithm SHA256).Hash; version=$_.VersionInfo.FileVersion}
})
}
$metadata | ConvertTo-Json -Depth 10 | Set-Content -LiteralPath (Join-Path $PackageRoot 'package.json') -Encoding UTF8
if (Get-ChildItem -LiteralPath $PackageRoot -Recurse -File | Where-Object { $_.Name -eq 'nvngx_dlss.dll' -or ($_.Name -eq '_nvngx.dll' -and $_.DirectoryName -ne (Join-Path $PackageRoot 'd4r')) }) {
throw 'Proprietary NVIDIA binaries must not be in the package.'
}
Write-Host "Windows game development package: $PackageRoot (NVIDIA DLLs excluded)"
if ($ArchivePath) {
$ArchivePath=[IO.Path]::GetFullPath($ArchivePath)
if ($ArchivePath.StartsWith($PackageRoot+'\',[StringComparison]::OrdinalIgnoreCase)) { throw 'Place the ZIP outside the package directory.' }
Add-Type -AssemblyName System.IO.Compression,System.IO.Compression.FileSystem
New-Item -ItemType Directory -Force (Split-Path $ArchivePath) | Out-Null
$stream=[IO.File]::Open($ArchivePath,[IO.FileMode]::Create,[IO.FileAccess]::ReadWrite,[IO.FileShare]::None)
$archive=$null
try {
$archive=[IO.Compression.ZipArchive]::new($stream,[IO.Compression.ZipArchiveMode]::Create)
# Never archive caches, results, private texture outputs or a local DLL
# merely because it happens to be somewhere under PackageRoot.
foreach ($relative in @($stagedFiles)+@('package.json')) {
[void][IO.Compression.ZipFileExtensions]::CreateEntryFromFile($archive,
(Join-Path $PackageRoot $relative),$relative.Replace('\','/'),[IO.Compression.CompressionLevel]::Optimal)
}
} finally { if ($archive) { $archive.Dispose() }; $stream.Dispose() }
Write-Host "Public package archive: $ArchivePath"
}