diff --git a/docs/windows-game.md b/docs/windows-game.md index bc7b4f2..46c5f39 100644 --- a/docs/windows-game.md +++ b/docs/windows-game.md @@ -128,4 +128,5 @@ uses a previous-frame fallback. OptiScaler source modifications are GPL-3.0 and exported under `source-patches/optiscaler`. ZLUDA source modifications are exported under -`source-patches/zluda`. Dependency license texts and build hashes are included. +`source-patches/zluda`; the LLVM gfx1154 backport is under +`source-patches/zluda-llvm`. Dependency license texts and build hashes are included. diff --git a/docs/windows-gpu-support.md b/docs/windows-gpu-support.md index b9b30d4..11a080e 100644 --- a/docs/windows-gpu-support.md +++ b/docs/windows-gpu-support.md @@ -99,6 +99,29 @@ Use `-GpuArchitectures gfx1100,gfx1101,gfx1102,gfx1200,gfx1201` for a subset. Per-target logs and `matrix-build.json` distinguish compilation from execution. The supplied DLL generates manifests locally and is never copied into archives. +Rebuild LLVM/ZLUDA when updating from an older package: the old LLVM 22 backend +does not recognize gfx1154 even though Clang 24 compiles native objects for it. +`build-zluda-llvm.ps1` now applies the source backport in `patches/zluda-llvm` +automatically; relink with `build-zluda-windows.ps1` afterward. Compiler base +and patch hashes are recorded in the ZLUDA build metadata and included in game +packages. The expected patched LLVM submodule appears modified in its parent +checkout; its complete source delta is exported, not a binary target override. + +For a compilation gate requiring neither a GPU nor NVIDIA DLLs, run: + +```powershell +.\scripts\windows\test-zluda-target-compilation.ps1 -ZludaRoot "$PWD\dist\zluda-windows-final" +``` + +All 33 public PTX compilations pass for the eleven targets: Driver API pattern, +FP16 MMA strict reference and explicit WMMA modes, with correct ELF targets +and wave32. The gfx12 strict F16 reference intentionally retains its existing +double-precision helper; the separate WMMA mode checks code generation only. +It does not enable relaxed arithmetic in game packages or validate numerical +results on other GPUs. The original gfx1154 compiler abort is preserved locally +in `build/llvm-gfx1154/before.log`; the regression results are in +`test-results/windows-gpu-coverage/zluda-offline`. + ## Fork adaptation Reviewed [realdody's branch](https://github.com/realdody/d4r/tree/windows-rdna3) diff --git a/docs/windows-rdna4-port.md b/docs/windows-rdna4-port.md index a315ec3..074a4e5 100644 --- a/docs/windows-rdna4-port.md +++ b/docs/windows-rdna4-port.md @@ -52,6 +52,22 @@ Results: `test-results/windows-gpu-coverage`; build logs and the compile-only matrix report: `build/windows-gpu-coverage`. No physical multi-GPU, APU or other-target validation is claimed. K performance remains open. +The final translator gate exposed a separate dependency gap: pinned LLVM 22 +rejects `gfx1154` and aborts (`0xC0000409`) on a public PTX pattern. A minimal +source backport of official LLVM `7a0829e41228` adds the processor's real +11.5.4 features, parser and ELF identity. It is exported under +`patches/zluda-llvm`, applied idempotently by the LLVM builder and included with +its base/hash in package metadata. LLVM and ZLUDA are rebuilt; all 33 offline +pattern/F16-reference/WMMA compilations pass across the eleven targets without +GPU execution. The existing strict gfx12 F16 reference lowering remains intact. +The rebuilt ZLUDA passes 20/20 RX 9070 XT CTest gates. Its twelve further K +4K burst/recreation frames are finite and all six async RGB images are exact; +three sync RGB images also exactly match the previous compiler's captures. +Four further M 4K frames are finite and match all four previous-compiler RGB +images exactly. Both require native transformer hits, zero CPU frame copies +and frame age 0. Results: `k-new-zluda`, `m-new-zluda` and compiler comparison +logs under `test-results/windows-gpu-coverage`. Other GPUs remain unverified. + **Current milestone: K performance remains open.** The latest unprofiled 4K Silent Hill 2 scene capture records 65.250 FPS. Functional K/M and the reproducible archive do not close this gate. Prioritize measured K kernel cost @@ -1219,7 +1235,10 @@ Pinned additional build dependencies: rust-std and rust-mingw archives and installs only under `.tools`. * ZLUDA LLVM submodule `ff4dc1f7c9e1c64d4d69e40f4ed30c2280a96dfd`, `llvm-config` reports `22.0.0git`. AMDGPU/LLVM/LLD are built with LLVM-MinGW - `20260922`; no Linux build host or runtime is used. + `20260922`; no Linux build host or runtime is used. The Windows builder adds + `patches/zluda-llvm/0001-backport-gfx1154.patch`, adapted from official LLVM + `7a0829e41228513299c5108685b0bc127463c6a1`. Rebuild and relink ZLUDA when + updating; native Clang 24 target support alone does not cover translated PTX. * HiGHS submodule `364c83a51e44ba6c27def9c8fc1a49b1daf5ad5c`. * The LLVM IR helper producer is stable HIP 7.2/LLVM 21. The final target is selected by the translator from HIP `gfx1201`; generic helper generation diff --git a/patches/zluda-llvm/0001-backport-gfx1154.patch b/patches/zluda-llvm/0001-backport-gfx1154.patch new file mode 100644 index 0000000..9f0df18 --- /dev/null +++ b/patches/zluda-llvm/0001-backport-gfx1154.patch @@ -0,0 +1,128 @@ +diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h +index e619b186d..dd3e9d92b 100644 +--- a/llvm/include/llvm/BinaryFormat/ELF.h ++++ b/llvm/include/llvm/BinaryFormat/ELF.h +@@ -856,7 +856,7 @@ enum : unsigned { + EF_AMDGPU_MACH_AMDGCN_GFX11_GENERIC = 0x054, + EF_AMDGPU_MACH_AMDGCN_GFX1152 = 0x055, + EF_AMDGPU_MACH_AMDGCN_RESERVED_0X56 = 0x056, +- EF_AMDGPU_MACH_AMDGCN_RESERVED_0X57 = 0x057, ++ EF_AMDGPU_MACH_AMDGCN_GFX1154 = 0x057, + EF_AMDGPU_MACH_AMDGCN_GFX1153 = 0x058, + EF_AMDGPU_MACH_AMDGCN_GFX12_GENERIC = 0x059, + EF_AMDGPU_MACH_AMDGCN_GFX1251 = 0x05a, +diff --git a/llvm/include/llvm/TargetParser/TargetParser.h b/llvm/include/llvm/TargetParser/TargetParser.h +index aad985926..c0aaa465b 100644 +--- a/llvm/include/llvm/TargetParser/TargetParser.h ++++ b/llvm/include/llvm/TargetParser/TargetParser.h +@@ -109,6 +109,7 @@ enum GPUKind : uint32_t { + GK_GFX1151, + GK_GFX1152, + GK_GFX1153, ++ GK_GFX1154, + + GK_GFX1200, + GK_GFX1201, +diff --git a/llvm/lib/Object/ELFObjectFile.cpp b/llvm/lib/Object/ELFObjectFile.cpp +index f9fda2346..70ddaae22 100644 +--- a/llvm/lib/Object/ELFObjectFile.cpp ++++ b/llvm/lib/Object/ELFObjectFile.cpp +@@ -591,6 +591,8 @@ StringRef ELFObjectFileBase::getAMDGPUCPUName() const { + return "gfx1152"; + case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1153: + return "gfx1153"; ++ case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1154: ++ return "gfx1154"; + + // AMDGCN GFX12. + case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1200: +diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp +index d9cce1eb7..7936876f4 100644 +--- a/llvm/lib/ObjectYAML/ELFYAML.cpp ++++ b/llvm/lib/ObjectYAML/ELFYAML.cpp +@@ -632,6 +632,7 @@ void ScalarBitSetTraits::bitset(IO &IO, + BCaseMask(EF_AMDGPU_MACH_AMDGCN_GFX1151, EF_AMDGPU_MACH); + BCaseMask(EF_AMDGPU_MACH_AMDGCN_GFX1152, EF_AMDGPU_MACH); + BCaseMask(EF_AMDGPU_MACH_AMDGCN_GFX1153, EF_AMDGPU_MACH); ++ BCaseMask(EF_AMDGPU_MACH_AMDGCN_GFX1154, EF_AMDGPU_MACH); + BCaseMask(EF_AMDGPU_MACH_AMDGCN_GFX1200, EF_AMDGPU_MACH); + BCaseMask(EF_AMDGPU_MACH_AMDGCN_GFX1201, EF_AMDGPU_MACH); + BCaseMask(EF_AMDGPU_MACH_AMDGCN_GFX1250, EF_AMDGPU_MACH); +diff --git a/llvm/lib/Target/AMDGPU/GCNProcessors.td b/llvm/lib/Target/AMDGPU/GCNProcessors.td +index c6fb31f9c..5d21894a3 100644 +--- a/llvm/lib/Target/AMDGPU/GCNProcessors.td ++++ b/llvm/lib/Target/AMDGPU/GCNProcessors.td +@@ -304,7 +304,12 @@ def : ProcessorModel<"gfx1153", GFX11SpeedModel, + FeatureISAVersion11_5_3.Features + >; + +-// [gfx1100, gfx1101, gfx1102, gfx1103, gfx1150, gfx1151, gfx1152, gfx1153] ++// Backported from LLVM 7a0829e41228: actual gfx1154 features and identity. ++def : ProcessorModel<"gfx1154", GFX11SpeedModel, ++ FeatureISAVersion11_5_Common.Features ++>; ++ ++// [gfx1100, gfx1101, gfx1102, gfx1103, gfx1150, gfx1151, gfx1152, gfx1153, gfx1154] + def : ProcessorModel<"gfx11-generic", GFX11SpeedModel, + FeatureISAVersion11_Generic.Features + >; +diff --git a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.cpp b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.cpp +index 5a0857322..c506fc308 100644 +--- a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.cpp ++++ b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.cpp +@@ -114,6 +114,7 @@ StringRef AMDGPUTargetStreamer::getArchNameFromElfMach(unsigned ElfMach) { + case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1151: AK = GK_GFX1151; break; + case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1152: AK = GK_GFX1152; break; + case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1153: AK = GK_GFX1153; break; ++ case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1154: AK = GK_GFX1154; break; + case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1200: AK = GK_GFX1200; break; + case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1201: AK = GK_GFX1201; break; + case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1250: AK = GK_GFX1250; break; +@@ -201,6 +202,7 @@ unsigned AMDGPUTargetStreamer::getElfMach(StringRef GPU) { + case GK_GFX1151: return ELF::EF_AMDGPU_MACH_AMDGCN_GFX1151; + case GK_GFX1152: return ELF::EF_AMDGPU_MACH_AMDGCN_GFX1152; + case GK_GFX1153: return ELF::EF_AMDGPU_MACH_AMDGCN_GFX1153; ++ case GK_GFX1154: return ELF::EF_AMDGPU_MACH_AMDGCN_GFX1154; + case GK_GFX1200: return ELF::EF_AMDGPU_MACH_AMDGCN_GFX1200; + case GK_GFX1201: return ELF::EF_AMDGPU_MACH_AMDGCN_GFX1201; + case GK_GFX1250: return ELF::EF_AMDGPU_MACH_AMDGCN_GFX1250; +diff --git a/llvm/lib/TargetParser/TargetParser.cpp b/llvm/lib/TargetParser/TargetParser.cpp +index 34b09b14b..39acbb942 100644 +--- a/llvm/lib/TargetParser/TargetParser.cpp ++++ b/llvm/lib/TargetParser/TargetParser.cpp +@@ -172,6 +172,7 @@ constexpr GPUInfo AMDGCNGPUs[] = { + {{"gfx1151"}, {"gfx1151"}, GK_GFX1151, FEATURE_FAST_FMA_F32|FEATURE_FAST_DENORMAL_F32|FEATURE_WAVE32|FEATURE_WGP}, + {{"gfx1152"}, {"gfx1152"}, GK_GFX1152, FEATURE_FAST_FMA_F32|FEATURE_FAST_DENORMAL_F32|FEATURE_WAVE32|FEATURE_WGP}, + {{"gfx1153"}, {"gfx1153"}, GK_GFX1153, FEATURE_FAST_FMA_F32|FEATURE_FAST_DENORMAL_F32|FEATURE_WAVE32|FEATURE_WGP}, ++ {{"gfx1154"}, {"gfx1154"}, GK_GFX1154, FEATURE_FAST_FMA_F32|FEATURE_FAST_DENORMAL_F32|FEATURE_WAVE32|FEATURE_WGP}, + {{"gfx1200"}, {"gfx1200"}, GK_GFX1200, FEATURE_FAST_FMA_F32|FEATURE_FAST_DENORMAL_F32|FEATURE_WAVE32|FEATURE_WGP}, + {{"gfx1201"}, {"gfx1201"}, GK_GFX1201, FEATURE_FAST_FMA_F32|FEATURE_FAST_DENORMAL_F32|FEATURE_WAVE32|FEATURE_WGP}, + {{"gfx1250"}, {"gfx1250"}, GK_GFX1250, FEATURE_FAST_FMA_F32|FEATURE_FAST_DENORMAL_F32|FEATURE_WAVE32}, +@@ -328,6 +329,7 @@ AMDGPU::IsaVersion AMDGPU::getIsaVersion(StringRef GPU) { + case GK_GFX1151: return {11, 5, 1}; + case GK_GFX1152: return {11, 5, 2}; + case GK_GFX1153: return {11, 5, 3}; ++ case GK_GFX1154: return {11, 5, 4}; + case GK_GFX1200: return {12, 0, 0}; + case GK_GFX1201: return {12, 0, 1}; + case GK_GFX1250: return {12, 5, 0}; +@@ -475,6 +477,7 @@ static void fillAMDGCNFeatureMap(StringRef GPU, const Triple &T, + Features["atomic-fmin-fmax-global-f32"] = true; + break; + case GK_GFX1153: ++ case GK_GFX1154: + case GK_GFX1152: + case GK_GFX1151: + case GK_GFX1150: +diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp +index ab9331690..0ade2d412 100644 +--- a/llvm/tools/llvm-readobj/ELFDumper.cpp ++++ b/llvm/tools/llvm-readobj/ELFDumper.cpp +@@ -1655,6 +1655,7 @@ const EnumEntry ElfHeaderMipsFlags[] = { + ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1151, "gfx1151"), \ + ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1152, "gfx1152"), \ + ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1153, "gfx1153"), \ ++ ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1154, "gfx1154"), \ + ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1200, "gfx1200"), \ + ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1201, "gfx1201"), \ + ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1250, "gfx1250"), \ diff --git a/patches/zluda-llvm/README.md b/patches/zluda-llvm/README.md new file mode 100644 index 0000000..1b01662 --- /dev/null +++ b/patches/zluda-llvm/README.md @@ -0,0 +1,24 @@ +# LLVM source patches for the Windows compiler + +Base: ZLUDA's LLVM submodule `ff4dc1f7c9e1c64d4d69e40f4ed30c2280a96dfd` +(LLVM 22). `build-zluda-llvm.ps1` applies these patches idempotently before +building. ZLUDA's parent source patches remain in `patches/zluda`. + +`0001-backport-gfx1154.patch` adapts official LLVM +[`7a0829e41228`](https://github.com/llvm/llvm-project/commit/7a0829e41228513299c5108685b0bc127463c6a1) +to the older parser/ELF structures. It adds actual gfx1154 processor features, +ISA 11.5.4, parser identity and ELF machine 0x57. It does not map gfx1154 onto +another CPU, patch binary headers or alter existing processors' features. +LLVM's gfx1154 uses `FeatureISAVersion11_5_Common` and the GFX11 speed model. +LLVM code remains Apache-2.0 WITH LLVM-exception (see the dependency license). + +The prior offline compiler aborts on a public PTX pattern for gfx1154 with +unrecognized-processor diagnostics and exit `0xC0000409`. After rebuilding +LLVM, rebuild/relink ZLUDA and its offline emitter; changing native Clang +objects alone cannot fix the translated PTX path. Run +`scripts/windows/test-zluda-target-compilation.ps1` to compile the public +Driver API pattern and FP16 MMA fixtures (strict/reference and WMMA modes) +for every target without GPU work. All 33 compilations pass with correct ELF +targets and wave32. Strict gfx12 F16 reference retains its prior FP64 helper; +WMMA mode here is a compilation check, not a default arithmetic change. +This checks code generation and ELF identity, not hardware execution/numerics. diff --git a/scripts/windows/build-zluda-llvm.ps1 b/scripts/windows/build-zluda-llvm.ps1 index 345a46a..f7f9121 100644 --- a/scripts/windows/build-zluda-llvm.ps1 +++ b/scripts/windows/build-zluda-llvm.ps1 @@ -12,6 +12,7 @@ if (!(Test-Path (Join-Path $SourceRoot 'ext/llvm-project/llvm/CMakeLists.txt'))) throw 'Run git submodule update --init --depth 1 ext/llvm-project in the ZLUDA checkout.' } New-Item -ItemType Directory -Force $BuildRoot | Out-Null +& (Join-Path $PSScriptRoot 'prepare-zluda-llvm-source.ps1') -LlvmSourceRoot (Join-Path $SourceRoot 'ext/llvm-project') $oldPath = $env:PATH try { $env:PATH = "$(Join-Path $toolchain 'bin');$oldPath" @@ -36,5 +37,9 @@ try { if ($LASTEXITCODE) { throw "LLVM build failed ($LASTEXITCODE)" } & (Join-Path $BuildRoot 'bin/llvm-config.exe') --version if ($LASTEXITCODE) { throw 'llvm-config verification failed' } + @{sourceBase=(& git -C (Join-Path $SourceRoot 'ext/llvm-project') rev-parse HEAD).Trim(); fullSourceDeltaVerified=$true; + sourcePatches=@(Get-ChildItem (Join-Path $repo 'patches/zluda-llvm') -Filter *.patch | ForEach-Object { + @{name=$_.Name; sha256=(Get-FileHash -LiteralPath $_.FullName).Hash}})} | + ConvertTo-Json -Depth 5 | Set-Content (Join-Path $BuildRoot 'd4r-llvm-build-info.json') -Encoding UTF8 Write-Host "Native Windows LLVM: $BuildRoot" } finally { $env:PATH = $oldPath } diff --git a/scripts/windows/build-zluda-windows.ps1 b/scripts/windows/build-zluda-windows.ps1 index 34770fb..7485339 100644 --- a/scripts/windows/build-zluda-windows.ps1 +++ b/scripts/windows/build-zluda-windows.ps1 @@ -84,6 +84,9 @@ try { @{base='ee2f25a180099fa42f36b2346732e1f2470a03ad'; target='x86_64-pc-windows-gnu'; 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')) { + Get-Content (Join-Path $LlvmBuildRoot 'd4r-llvm-build-info.json') -Raw | ConvertFrom-Json + } 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" diff --git a/scripts/windows/package-windows-game.ps1 b/scripts/windows/package-windows-game.ps1 index 98b2aac..c0667d8 100644 --- a/scripts/windows/package-windows-game.ps1 +++ b/scripts/windows/package-windows-game.ps1 @@ -94,6 +94,7 @@ Stage (Join-Path $HipRoot 'share/doc/amd_comgr/LICENSE.txt') 'licenses/amd_comgr 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) } +foreach ($patch in Get-ChildItem -LiteralPath (Join-Path $repo 'patches/zluda-llvm') -Filter '*.patch') { Stage $patch.FullName ('source-patches/zluda-llvm/' + $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 diff --git a/scripts/windows/prepare-zluda-llvm-source.ps1 b/scripts/windows/prepare-zluda-llvm-source.ps1 new file mode 100644 index 0000000..8fc7fb7 --- /dev/null +++ b/scripts/windows/prepare-zluda-llvm-source.ps1 @@ -0,0 +1,34 @@ +[CmdletBinding()] +param([Parameter(Mandatory=$true)][string]$LlvmSourceRoot) +$ErrorActionPreference='Stop' +$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..')) +$expected='ff4dc1f7c9e1c64d4d69e40f4ed30c2280a96dfd' +$actual=(& git -C $LlvmSourceRoot rev-parse HEAD).Trim() +if ($LASTEXITCODE -or $actual -ne $expected) { throw "Expected audited ZLUDA LLVM source $expected, found $actual; review the patch against this revision." } +$patches=@(Get-ChildItem (Join-Path $repo 'patches/zluda-llvm') -Filter *.patch | Sort-Object Name) +foreach ($patch in $patches) { + $oldPreference=$ErrorActionPreference + try { + $ErrorActionPreference='Continue' + & git -C $LlvmSourceRoot apply --reverse --check $patch.FullName 2>$null + $applied=($LASTEXITCODE -eq 0) + } finally { $ErrorActionPreference=$oldPreference } + if (!$applied) { + & git -C $LlvmSourceRoot apply --check $patch.FullName + if ($LASTEXITCODE) { throw "LLVM source patch conflicts: $($patch.Name)" } + & git -C $LlvmSourceRoot apply $patch.FullName + if ($LASTEXITCODE) { throw "LLVM source patch failed: $($patch.Name)" } + } + Write-Host "LLVM source patch present: $($patch.Name)" +} +# The pinned backport is the entire intended LLVM delta. +if ($patches.Count -ne 1) { throw 'Review combined LLVM source provenance before adding more patches.' } +$audit=Join-Path $repo ('build/llvm-source-audit-'+[Guid]::NewGuid().ToString('N')+'.patch') +New-Item -ItemType Directory -Force (Split-Path $audit) | Out-Null +try { + & git -C $LlvmSourceRoot diff --binary --output=$audit + if ($LASTEXITCODE) { throw 'Cannot audit LLVM source diff.' } + $actualDiff=[IO.File]::ReadAllText($audit).Replace("`r`n","`n").TrimEnd() + $expectedDiff=[IO.File]::ReadAllText($patches[0].FullName).Replace("`r`n","`n").TrimEnd() + if ($actualDiff -cne $expectedDiff) { throw 'LLVM source contains changes outside the exported audited patch.' } +} finally { if (Test-Path -LiteralPath $audit) { Remove-Item -LiteralPath $audit } } diff --git a/scripts/windows/test-zluda-target-compilation.ps1 b/scripts/windows/test-zluda-target-compilation.ps1 new file mode 100644 index 0000000..ee5b441 --- /dev/null +++ b/scripts/windows/test-zluda-target-compilation.ps1 @@ -0,0 +1,67 @@ +[CmdletBinding()] +param([string]$ZludaRoot, [string[]]$GpuArchitectures, [string]$OutputDirectory) +$ErrorActionPreference='Stop' +. (Join-Path $PSScriptRoot 'gpu-target.ps1') +$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..')) +if (!$ZludaRoot) { $ZludaRoot=Join-Path $repo 'dist/zluda-windows-final' } +if (!$OutputDirectory) { $OutputDirectory=Join-Path $repo 'test-results/zluda-target-compilation' } +if (!$GpuArchitectures) { $GpuArchitectures=@(Get-D4RGpuTargets | ForEach-Object { $_.architecture }) } +foreach ($arch in $GpuArchitectures) { [void](Get-D4RGpuTargetInfo $arch) } +$emitter=Join-Path $ZludaRoot 'd4r_emit.exe' +if (!(Test-Path -LiteralPath $emitter)) { throw "Rebuild ZLUDA and its offline emitter: $emitter" } +New-Item -ItemType Directory -Force $OutputDirectory | Out-Null +$settings=@{PATH="$ZludaRoot;$env:PATH"; D4R_ZLUDA_WMMA='1'; D4R_ZLUDA_WMMA_FP8='1'; + D4R_ZLUDA_WMMA_F16_REFERENCE='1'; D4R_ZLUDA_WMMA_FP8_NATIVE='0'; D4R_ZLUDA_WMMA_LAYOUT=$null; + D4R_ZLUDA_WAVE64=$null; D4R_ZLUDA_FAST_MATH=$null; D4R_ZLUDA_IGNORE_DENORMAL=$null; + D4R_ZLUDA_WMMA_F32ACC=$null; D4R_ZLUDA_EXTRA_BC=$null; D4R_ZLUDA_WGP=$null} +$old=@{}; $rows=[Collections.Generic.List[object]]::new() +try { + foreach ($key in $settings.Keys) { + $old[$key]=[Environment]::GetEnvironmentVariable($key,'Process') + if ($null -eq $settings[$key]) { Remove-Item -LiteralPath "Env:$key" -ErrorAction SilentlyContinue } + else { [Environment]::SetEnvironmentVariable($key,$settings[$key],'Process') } + } + foreach ($fixture in @(@{name='pattern'; source='cuda_driver_probe.cpp'; reference='1'}, + @{name='f16-mma-reference'; source='cuda_mma_probe.cpp'; reference='1'}, + @{name='f16-mma-wmma'; source='cuda_mma_probe.cpp'; reference='0'})) { + $env:D4R_ZLUDA_WMMA_F16_REFERENCE=$fixture.reference + # Reuse the public synthetic PTX exercised by the hardware diagnostics. + # Reading source does not execute a probe or load HIP/NVIDIA libraries. + $match=[regex]::Match((Get-Content (Join-Path $repo ('tools/windows/'+$fixture.source)) -Raw),'(?s)R"PTX\((.*?)\)PTX"') + if (!$match.Success) { throw 'Public PTX fixture not found.' } + $ptx=Join-Path $OutputDirectory ($fixture.name+'.ptx') + $match.Groups[1].Value | Set-Content -LiteralPath $ptx -Encoding ASCII + foreach ($arch in $GpuArchitectures) { + $output=Join-Path $OutputDirectory ($arch+'/'+$fixture.name) + New-Item -ItemType Directory -Force $output | Out-Null + $log=Join-Path $output 'compile.log' + $oldPreference=$ErrorActionPreference + try { $ErrorActionPreference='Continue'; & $emitter $ptx $output $arch *> $log; $code=$LASTEXITCODE } + finally { $ErrorActionPreference=$oldPreference } + if ($code) { throw "Offline ZLUDA compilation failed: $arch $($fixture.name), exit=$code; see $log" } + Assert-D4RCodeObjectTarget (Join-Path $output 'module.hsaco') $arch + $text=Get-Content -LiteralPath $log -Raw + if ($text -match 'not a recognized processor|ignoring processor|unsupported processor') { throw "Target rejected by compiler: $log" } + $asm=Get-Content (Join-Path $output 'asm.s') -Raw + if ($asm -notmatch '\.amdhsa_wavefront_size32\s+1') { throw "Missing wave32 code generation: $output" } + $hasWmma=($asm -match 'v_wmma_') + if (($fixture.name -eq 'f16-mma-wmma' -or ($fixture.name -eq 'f16-mma-reference' -and $arch.StartsWith('gfx11'))) -and !$hasWmma) { + throw "WMMA lowering missing: $output" + } + # gfx12 strict F16 accumulation intentionally uses the existing + # double-precision reference helper. Do not label it native WMMA. + if ($fixture.name -eq 'f16-mma-reference' -and $arch.StartsWith('gfx12') -and + ($hasWmma -or $asm -notmatch 'v_fma_f64')) { throw "Strict gfx12 reference lowering changed: $output" } + $rows.Add(@{architecture=$arch; fixture=$fixture.name; compiled=$true; elfTargetCorrect=$true; + nativeWmma=$hasWmma; hardwareExecuted=$false}) + Write-Host "PASS ZLUDA_OFFLINE target=$arch fixture=$($fixture.name) wave=32 hardware_executed=0" + } + } + @{passed=$true; fixtures=@($rows); emitterSha256=(Get-FileHash -LiteralPath $emitter).Hash; gpuWorkExecuted=$false} | + ConvertTo-Json -Depth 6 | Set-Content (Join-Path $OutputDirectory 'summary.json') -Encoding UTF8 +} finally { + foreach ($key in $old.Keys) { + if ($null -eq $old[$key]) { Remove-Item -LiteralPath "Env:$key" -ErrorAction SilentlyContinue } + else { [Environment]::SetEnvironmentVariable($key,$old[$key],'Process') } + } +}