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]>
This commit is contained in:
1 parent
98de8e3a3e
commit
3fa963fd1b
32 files changed
+494
-162
No files matched your search
+30
-8
@@ -15,15 +15,36 @@ endif()
|
|||||||
find_program(D4R_HIP_CLANG NAMES clang++.exe PATHS "${D4R_HIP_ROOT}/bin" "${D4R_HIP_ROOT}/lib/llvm/bin" NO_DEFAULT_PATH REQUIRED)
|
find_program(D4R_HIP_CLANG NAMES clang++.exe PATHS "${D4R_HIP_ROOT}/bin" "${D4R_HIP_ROOT}/lib/llvm/bin" NO_DEFAULT_PATH REQUIRED)
|
||||||
# Architecture parameterization adapted from realdody/d4r ae530b0.
|
# Architecture parameterization adapted from realdody/d4r ae530b0.
|
||||||
# Keep explicit subtargets: no gfx11 substitution or untested future gfx12 ISA.
|
# Keep explicit subtargets: no gfx11 substitution or untested future gfx12 ISA.
|
||||||
|
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/tools/windows/gpu-targets.json" d4r_target_json)
|
||||||
|
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS tools/windows/gpu-targets.json)
|
||||||
|
string(JSON d4r_target_count LENGTH "${d4r_target_json}" targets)
|
||||||
|
math(EXPR d4r_target_last "${d4r_target_count} - 1")
|
||||||
|
set(d4r_supported_targets)
|
||||||
|
set(d4r_target_cpp_entries "")
|
||||||
|
foreach(index RANGE ${d4r_target_last})
|
||||||
|
foreach(field architecture elfMachine isaMajor family)
|
||||||
|
string(JSON target_${field} GET "${d4r_target_json}" targets ${index} ${field})
|
||||||
|
endforeach()
|
||||||
|
list(APPEND d4r_supported_targets "${target_architecture}")
|
||||||
|
string(APPEND d4r_target_cpp_entries " GpuTarget{\"${target_architecture}\", ${target_elfMachine}, ${target_isaMajor}, \"${target_family}\"},\n")
|
||||||
|
endforeach()
|
||||||
|
configure_file(tools/windows/gpu_targets.generated.h.in gpu_targets.generated.h @ONLY)
|
||||||
|
include_directories("${CMAKE_CURRENT_BINARY_DIR}")
|
||||||
set(D4R_GPU_ARCH "gfx1201" CACHE STRING "Native Windows package GPU target")
|
set(D4R_GPU_ARCH "gfx1201" CACHE STRING "Native Windows package GPU target")
|
||||||
set_property(CACHE D4R_GPU_ARCH PROPERTY STRINGS gfx1201 gfx1200)
|
set_property(CACHE D4R_GPU_ARCH PROPERTY STRINGS ${d4r_supported_targets})
|
||||||
set(d4r_supported_targets gfx1200 gfx1201)
|
|
||||||
if(NOT D4R_GPU_ARCH IN_LIST d4r_supported_targets)
|
if(NOT D4R_GPU_ARCH IN_LIST d4r_supported_targets)
|
||||||
message(FATAL_ERROR "D4R_GPU_ARCH must be gfx1200 or gfx1201")
|
message(FATAL_ERROR "D4R_GPU_ARCH must be one of: ${d4r_supported_targets}")
|
||||||
endif()
|
endif()
|
||||||
add_compile_definitions(D4R_TARGET_ARCH="${D4R_GPU_ARCH}")
|
add_compile_definitions(D4R_TARGET_ARCH="${D4R_GPU_ARCH}")
|
||||||
configure_file(tools/windows/gpu-target.json.in gpu-target.json @ONLY)
|
configure_file(tools/windows/gpu-target.json.in gpu-target.json @ONLY)
|
||||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/gpu-target.json" DESTINATION .)
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/gpu-target.json" DESTINATION .)
|
||||||
|
install(FILES tools/windows/gpu-targets.json DESTINATION .)
|
||||||
|
set(d4r_device_flags)
|
||||||
|
if(D4R_GPU_ARCH MATCHES "^gfx11")
|
||||||
|
# Windows-only workaround informed by realdody/d4r 1897b4a. Keep the real
|
||||||
|
# gfx11 layout; do not route RDNA3 through gfx12 fragments.
|
||||||
|
list(APPEND d4r_device_flags -DD4R_WINDOWS_GFX11_LANE_EXCHANGE)
|
||||||
|
endif()
|
||||||
set(probe_object "${CMAKE_CURRENT_BINARY_DIR}/probe_${D4R_GPU_ARCH}.hsaco")
|
set(probe_object "${CMAKE_CURRENT_BINARY_DIR}/probe_${D4R_GPU_ARCH}.hsaco")
|
||||||
add_custom_command(OUTPUT "${probe_object}"
|
add_custom_command(OUTPUT "${probe_object}"
|
||||||
COMMAND "${D4R_HIP_CLANG}" -x hip --offload-arch=${D4R_GPU_ARCH}
|
COMMAND "${D4R_HIP_CLANG}" -x hip --offload-arch=${D4R_GPU_ARCH}
|
||||||
@@ -44,10 +65,10 @@ set(wmma_object "${CMAKE_CURRENT_BINARY_DIR}/wmma_${D4R_GPU_ARCH}.hsaco")
|
|||||||
add_custom_command(OUTPUT "${wmma_object}"
|
add_custom_command(OUTPUT "${wmma_object}"
|
||||||
COMMAND "${D4R_HIP_CLANG}" -x hip --offload-arch=${D4R_GPU_ARCH}
|
COMMAND "${D4R_HIP_CLANG}" -x hip --offload-arch=${D4R_GPU_ARCH}
|
||||||
--offload-device-only --no-gpu-bundle-output -mno-wavefrontsize64
|
--offload-device-only --no-gpu-bundle-output -mno-wavefrontsize64
|
||||||
-nogpuinc -nogpulib -O2 "${CMAKE_CURRENT_SOURCE_DIR}/tools/windows/wmma_gfx1201.hip"
|
-nogpuinc -nogpulib -O2 ${d4r_device_flags} "${CMAKE_CURRENT_SOURCE_DIR}/tools/windows/wmma_gfx1201.hip"
|
||||||
-o "${wmma_object}"
|
-o "${wmma_object}"
|
||||||
DEPENDS tools/windows/wmma_gfx1201.hip kernels/common/wmma_backend.h
|
DEPENDS tools/windows/wmma_gfx1201.hip kernels/common/wmma_backend.h
|
||||||
kernels/common/wmma_layout.h VERBATIM)
|
kernels/common/wmma_layout.h kernels/common/wave32_exchange.h VERBATIM)
|
||||||
add_custom_target(d4r_wmma_code_object ALL DEPENDS "${wmma_object}")
|
add_custom_target(d4r_wmma_code_object ALL DEPENDS "${wmma_object}")
|
||||||
# K/M objects stay in experimental/, outside the ZLUDA native override
|
# K/M objects stay in experimental/, outside the ZLUDA native override
|
||||||
# directory, until each layer and then the complete network pass replay.
|
# directory, until each layer and then the complete network pass replay.
|
||||||
@@ -78,9 +99,9 @@ foreach(family k m)
|
|||||||
add_custom_command(OUTPUT "${native_object}"
|
add_custom_command(OUTPUT "${native_object}"
|
||||||
COMMAND "${D4R_HIP_CLANG}" -x hip -std=c++17 --offload-arch=${D4R_GPU_ARCH}
|
COMMAND "${D4R_HIP_CLANG}" -x hip -std=c++17 --offload-arch=${D4R_GPU_ARCH}
|
||||||
--offload-device-only --no-gpu-bundle-output -mno-wavefrontsize64
|
--offload-device-only --no-gpu-bundle-output -mno-wavefrontsize64
|
||||||
-nogpuinc -nogpulib -O3 -DD4R_DEVICE_ONLY_MINIMAL ${native_flags}
|
-nogpuinc -nogpulib -O3 -DD4R_DEVICE_ONLY_MINIMAL ${d4r_device_flags} ${native_flags}
|
||||||
"${source}" -o "${native_object}"
|
"${source}" -o "${native_object}"
|
||||||
DEPENDS "${source}" ${native_headers} kernels/common/wmma_layout.h
|
DEPENDS "${source}" ${native_headers} kernels/common/wmma_layout.h kernels/common/wave32_exchange.h
|
||||||
kernels/common/hip_device_minimal.h VERBATIM)
|
kernels/common/hip_device_minimal.h VERBATIM)
|
||||||
list(APPEND native_objects "${native_object}")
|
list(APPEND native_objects "${native_object}")
|
||||||
install(FILES "${native_object}" DESTINATION "experimental/${family}")
|
install(FILES "${native_object}" DESTINATION "experimental/${family}")
|
||||||
@@ -89,7 +110,7 @@ endforeach()
|
|||||||
add_custom_target(d4r_native_compile ALL DEPENDS ${native_objects})
|
add_custom_target(d4r_native_compile ALL DEPENDS ${native_objects})
|
||||||
# Retain the old manual build target for existing scripts.
|
# Retain the old manual build target for existing scripts.
|
||||||
add_custom_target(d4r_native_gfx1201_compile DEPENDS d4r_native_compile)
|
add_custom_target(d4r_native_gfx1201_compile DEPENDS d4r_native_compile)
|
||||||
foreach(probe hip_gfx1201_probe gfx12_wmma_probe k_module_probe native_replay_probe cuda_driver_probe cuda_mma_probe cuda_image_probe d3d12_command_probe d3d12_pixel_probe d3d12_hip_interop_probe hip_stream_lifecycle_probe ngx_cuda_init_probe d3d12_dlss_probe)
|
foreach(probe gpu_inventory hip_gfx1201_probe gfx12_wmma_probe k_module_probe native_replay_probe cuda_driver_probe cuda_mma_probe cuda_image_probe d3d12_command_probe d3d12_pixel_probe d3d12_hip_interop_probe hip_stream_lifecycle_probe ngx_cuda_init_probe d3d12_dlss_probe)
|
||||||
add_executable(d4r_${probe} tools/windows/${probe}.cpp)
|
add_executable(d4r_${probe} tools/windows/${probe}.cpp)
|
||||||
target_compile_definitions(d4r_${probe} PRIVATE WIN32_LEAN_AND_MEAN NOMINMAX __HIP_PLATFORM_AMD__)
|
target_compile_definitions(d4r_${probe} PRIVATE WIN32_LEAN_AND_MEAN NOMINMAX __HIP_PLATFORM_AMD__)
|
||||||
target_include_directories(d4r_${probe} PRIVATE "${D4R_HIP_ROOT}/include")
|
target_include_directories(d4r_${probe} PRIVATE "${D4R_HIP_ROOT}/include")
|
||||||
@@ -200,6 +221,7 @@ install(FILES "${pixel_object}" DESTINATION bin)
|
|||||||
install(FILES "${wmma_object}" DESTINATION bin)
|
install(FILES "${wmma_object}" DESTINATION bin)
|
||||||
install(FILES scripts/windows/test-windows-rdna4.ps1 DESTINATION .)
|
install(FILES scripts/windows/test-windows-rdna4.ps1 DESTINATION .)
|
||||||
install(FILES scripts/windows/gpu-target.ps1 DESTINATION .)
|
install(FILES scripts/windows/gpu-target.ps1 DESTINATION .)
|
||||||
|
install(FILES scripts/windows/gpu-preflight.ps1 DESTINATION .)
|
||||||
install(FILES scripts/windows/test-gpu-target-contract.ps1 DESTINATION .)
|
install(FILES scripts/windows/test-gpu-target-contract.ps1 DESTINATION .)
|
||||||
install(FILES scripts/windows/test-k-replay.ps1 DESTINATION .)
|
install(FILES scripts/windows/test-k-replay.ps1 DESTINATION .)
|
||||||
install(FILES scripts/windows/test-k-captures.ps1 DESTINATION .)
|
install(FILES scripts/windows/test-k-captures.ps1 DESTINATION .)
|
||||||
|
|||||||
+13
-5
@@ -1,21 +1,29 @@
|
|||||||
# Native Windows RDNA4 game development package
|
# Native Windows RDNA3 / RDNA4 game development package
|
||||||
|
|
||||||
Validated hardware: Windows 11 x64 / Radeon RX 9070 XT / gfx1201. Native K and
|
Validated hardware: Windows 11 x64 / Radeon RX 9070 XT / gfx1201. Native K and
|
||||||
M transformer kernels pass standalone D3D12 + OptiScaler checks. Silent Hill 2
|
M transformer kernels pass standalone D3D12 + OptiScaler checks. Silent Hill 2
|
||||||
K now renders real menu frames and M renders a saved gameplay level with
|
K now renders real menu frames and M renders a saved gameplay level with
|
||||||
GPU NaN/Inf checks. Both K and M pass 3840x2160 output on this machine.
|
GPU NaN/Inf checks. Both K and M pass 3840x2160 output on this machine.
|
||||||
The user reports 49-51 FPS for K in the measured scene after the command-hook
|
Performance measurements and their controls are recorded in
|
||||||
fix and locally built output-store optimization. This is a local
|
[windows-performance.md](windows-performance.md). This is a
|
||||||
development package; no NVIDIA proprietary DLL is included.
|
development package; no NVIDIA proprietary DLL is included.
|
||||||
|
|
||||||
Builds also accept gfx1200 (for example RX 9060/9060 XT). This target is
|
Experimental builds also accept gfx1100..gfx1103 (RDNA3), gfx1150..gfx1154
|
||||||
**compile-tested only**; no physical gfx1200 validation has been performed.
|
(RDNA3.5) and gfx1200 (for example RX 9060/9060 XT). These targets are
|
||||||
|
**compile-tested only**; no physical validation here has been performed.
|
||||||
RX 9070 and other gfx1201 cards also remain untested. Use a package built for
|
RX 9070 and other gfx1201 cards also remain untested. Use a package built for
|
||||||
the GPU's actual HIP architecture: its `gpu-target.json`, host shim and ELF
|
the GPU's actual HIP architecture: its `gpu-target.json`, host shim and ELF
|
||||||
code objects must agree. Installation/runtime reject mixed targets. See
|
code objects must agree. Installation/runtime reject mixed targets. See
|
||||||
[windows-gpu-support.md](windows-gpu-support.md) for separate-target build
|
[windows-gpu-support.md](windows-gpu-support.md) for separate-target build
|
||||||
commands, the fork review and the first hardware diagnostic gate.
|
commands, the fork review and the first hardware diagnostic gate.
|
||||||
|
|
||||||
|
Before changing game files, the runner inventories HIP devices without
|
||||||
|
executing kernels. It rejects another architecture's package and a local
|
||||||
|
D3D12 proxy identifying itself as vkd3d/Wine, producing one diagnostic ZIP.
|
||||||
|
RX 9060 XT needs gfx1200: the old gfx1201-only package fails before DLSS
|
||||||
|
initialization on it. Use native D3D12. On an untested GPU, start with
|
||||||
|
synchronous K and output/exception diagnostics.
|
||||||
|
|
||||||
Build the shim/diagnostics, corrected ZLUDA, K/M native objects and patched
|
Build the shim/diagnostics, corrected ZLUDA, K/M native objects and patched
|
||||||
OptiScaler using the scripts in `scripts/windows`, then run:
|
OptiScaler using the scripts in `scripts/windows`, then run:
|
||||||
|
|
||||||
|
|||||||
+112
-101
@@ -1,40 +1,80 @@
|
|||||||
# Windows GPU targets
|
# Experimental Windows RDNA3 / RDNA4 coverage
|
||||||
|
|
||||||
The native Windows build accepts **gfx1200** and **gfx1201**. It builds a
|
The shim, diagnostics, native K/M kernels and game installer accept the
|
||||||
separate shim, diagnostics and code objects for each target. The default stays
|
targets below, with one package per actual ISA. **Only RX 9070 XT has physical
|
||||||
gfx1201. GPU selection uses HIP's real `gcnArchName`, followed by D3D12/HIP
|
validation here.** All other targets are experimental and compile-tested;
|
||||||
adapter LUID matching; it does not depend on a marketing name or overridden
|
working DLSS, interop and performance on them remain unverified.
|
||||||
DXGI vendor ID.
|
|
||||||
|
|
||||||
| Target | Examples in LLVM's processor table | This project's validation |
|
| Family | Target | Examples / scope |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| gfx1201 | RX 9070, RX 9070 XT | RX 9070 XT: hardware, K/M and game tests. Other cards untested. |
|
| RDNA3 | gfx1100 | RX 7900 family; same-target workstation GPUs |
|
||||||
| gfx1200 | RX 9060, RX 9060 XT | Host/device compilation and software tests only. No physical gfx1200 available. |
|
| RDNA3 | gfx1101 | RX 7700 / 7700 XT / 7800 XT; same-target mobile/workstation GPUs |
|
||||||
|
| RDNA3 | gfx1102 | RX 7600 / 7600 XT; same-target mobile/workstation GPUs |
|
||||||
|
| RDNA3 | gfx1103 | RDNA3 integrated graphics |
|
||||||
|
| RDNA3.5 | gfx1150, gfx1151, gfx1152, gfx1153, gfx1154 | Corresponding integrated graphics targets |
|
||||||
|
| RDNA4 | gfx1200 | RX 9060 / 9060 XT; same-target GPUs |
|
||||||
|
| RDNA4 | gfx1201 | RX 9070 / 9070 XT / 9070 GRE; same-target GPUs |
|
||||||
|
|
||||||
Sources: [LLVM AMDGPU processors](https://llvm.org/docs/AMDGPUUsage.html#processors)
|
Names and IDs follow [LLVM processors](https://llvm.org/docs/AMDGPUUsage.html#processors)
|
||||||
and [AMD's Windows compatibility matrix](https://rocm.docs.amd.com/projects/radeon-ryzen/en/latest/docs/compatibility/compatibilityrad/windows/windows_compatibility.html).
|
and [ELF ABI](https://llvm.org/docs/AMDGPUUsage.html#amdgpu-elf-header-e-flags).
|
||||||
AMD's matrix is dependency information, not evidence that d4r's K/M or external
|
`tools/windows/gpu-targets.json` supplies CMake-generated C++, PowerShell and
|
||||||
memory path works on an untested card. Other RDNA4 SKUs are eligible only when
|
the private texture builder. Selection uses HIP's real `gcnArchName` and the
|
||||||
HIP reports one of these exact targets and exposes the required Windows APIs.
|
D3D12 adapter LUID, including systems with several GPUs sharing a target.
|
||||||
Device-specific drivers, performance and memory capacity still need testing.
|
Marketing names do not control eligibility.
|
||||||
gfx1250/gfx1251 are a separate ISA group and are not enabled by this change.
|
|
||||||
|
|
||||||
Do not rename a gfx1201 package to gfx1200. `gpu-target.json`, the compiled
|
All listed RDNA3/RDNA3.5/RDNA4 targets with existing gfx11/gfx12 WMMA contracts
|
||||||
host target and each ELF code-object target must agree. Runtime selection
|
are included. TBD RDNA4m gfx1170..gfx1172 and gfx12.5 gfx1250/gfx1251 are
|
||||||
rejects another architecture before launching kernels. Staging, packaging and
|
different ISA groups and excluded. Unknown future targets need explicit review.
|
||||||
installation inspect the documented AMDGPU ELF machine ID and reject mixed
|
Check [AMD's Windows matrix](https://rocm.docs.amd.com/projects/radeon-ryzen/en/latest/docs/compatibility/compatibilityrad/windows/windows_compatibility.html)
|
||||||
objects. They never rewrite a binary target or set `HSA_OVERRIDE_GFX_VERSION`.
|
for driver/runtime eligibility. Compiler support cannot supply missing Windows
|
||||||
Legacy packages without target metadata remain gfx1201 only.
|
driver support or external-memory APIs, especially on APUs.
|
||||||
|
|
||||||
## Build and package
|
## Installation and diagnostics
|
||||||
|
|
||||||
Prepare the pinned dependencies as described in `windows-rdna4-port.md`.
|
Use the actual target's archive: **gfx1200 for RX 9060 XT**, for example.
|
||||||
Select a target explicitly; this example creates the experimental gfx1200
|
Metadata, host target and every ELF target must agree. Runtime/scripts reject
|
||||||
package. Use gfx1201 for a 9070/9070 XT. Keep separate output directories when
|
mixed targets and never rename targets, rewrite ELF IDs or set
|
||||||
building both targets.
|
`HSA_OVERRIDE_GFX_VERSION`. Legacy metadata-free packages remain gfx1201 only.
|
||||||
|
|
||||||
|
Before changing game files, `windows-game.ps1` now runs a read-only HIP
|
||||||
|
inventory and checks the target and wave32. Inventory allocates no GPU buffers
|
||||||
|
and runs no kernels; success is discovery, not validation. Failure prints one
|
||||||
|
ZIP containing stdout/stderr, exit code, runtime/DLL and driver details. A local
|
||||||
|
`d3d12.dll` identifying itself as vkd3d/Wine is rejected before install. Restore
|
||||||
|
the game's native D3D12 installation; the script never loads or removes that
|
||||||
|
proxy itself. Begin synchronously on an untested GPU:
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
$arch = 'gfx1200'
|
.\windows-game.ps1 -GameExe "D:\Games\Example\Game.exe" -NgxCore "C:\LocalDLLs\_nvngx.dll" -DlssDll "C:\LocalDLLs\nvngx_dlss.dll" -Preset 11 -ValidateOutput -CaptureExceptions
|
||||||
|
```
|
||||||
|
|
||||||
|
The local DLLs must match the documented NGX version and DLSS 310.9.1 SHA256
|
||||||
|
in `package.json`. NVIDIA DLLs are never distributed. Retain the printed ZIP
|
||||||
|
on failure. Async K and performance are subsequent gates; gfx1201-specific
|
||||||
|
FP8, arithmetic and tuning experiments remain separate.
|
||||||
|
|
||||||
|
## Issue #10 review, 2026-10-02
|
||||||
|
|
||||||
|
Reviewed [comment 5952822115](https://github.com/countervolts/d4r/issues/10#issuecomment-5952822115),
|
||||||
|
including all 32 attached text logs from eight attempts. HIP discovers
|
||||||
|
**RX 9060 XT / gfx1200** successfully. Every attempt fails with the old shim's
|
||||||
|
**"No selected gfx1201 device"** rejection; OptiScaler reports `support=false`
|
||||||
|
/ `BAD00002`. None reaches `D4R_RUNTIME` initialization or native transformer
|
||||||
|
execution. These logs do not demonstrate a K/M kernel crash. Use the gfx1200
|
||||||
|
package instead of overriding architecture. Three attempts also load
|
||||||
|
vkd3d-proton 3.1.0 from a local D3D12 proxy, outside this Windows backend.
|
||||||
|
|
||||||
|
The new packages/preflight address the identified failures. They do not prove
|
||||||
|
those games work on RX 9060 XT; a new native-D3D12 run on that GPU is required.
|
||||||
|
Raw community logs and personal directory paths stay local.
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
Prepare dependencies following `windows-rdna4-port.md`. Default: gfx1201.
|
||||||
|
Select another target explicitly and keep separate directories:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
$arch = 'gfx1101' # for example RX 7800 XT
|
||||||
$diag = "$PWD\dist\windows-$arch-diagnostics"
|
$diag = "$PWD\dist\windows-$arch-diagnostics"
|
||||||
.\scripts\windows\build-windows-rdna4.ps1 -RuntimeProfile therock -GpuArch $arch -ZludaRoot "$PWD\dist\zluda-windows-final" -BuildDirectory "$PWD\build\windows-$arch" -InstallDirectory $diag
|
.\scripts\windows\build-windows-rdna4.ps1 -RuntimeProfile therock -GpuArch $arch -ZludaRoot "$PWD\dist\zluda-windows-final" -BuildDirectory "$PWD\build\windows-$arch" -InstallDirectory $diag
|
||||||
.\scripts\windows\stage-native-k.ps1 -DlssDll "$PWD\nvngx_dlss.dll" -PackageRoot $diag
|
.\scripts\windows\stage-native-k.ps1 -DlssDll "$PWD\nvngx_dlss.dll" -PackageRoot $diag
|
||||||
@@ -42,89 +82,60 @@ $diag = "$PWD\dist\windows-$arch-diagnostics"
|
|||||||
.\scripts\windows\package-windows-game.ps1 -DiagnosticRoot $diag -GpuArch $arch -PackageRoot "$PWD\dist\windows-$arch-game" -ArchivePath "$PWD\dist\windows-$arch-game.zip"
|
.\scripts\windows\package-windows-game.ps1 -DiagnosticRoot $diag -GpuArch $arch -PackageRoot "$PWD\dist\windows-$arch-game" -ArchivePath "$PWD\dist\windows-$arch-game.zip"
|
||||||
```
|
```
|
||||||
|
|
||||||
ZLUDA, HIP and OptiScaler must already be built/prepared. The package contains
|
Rebuild diagnostics for the new inventory executable. The package keeps strict
|
||||||
the strict K FP16 and M FP16-equivalent baseline; native FP8 stays disabled.
|
K FP16 and M FP16-equivalent baselines; native M FP8 remains disabled. CMake:
|
||||||
The architecture does not change arithmetic or the existing WMMA layout.
|
`-DD4R_GPU_ARCH=gfx1101`. Some source/executable names retain gfx1201/gfx12 for
|
||||||
Private NVIDIA-derived texture overrides remain optional local experiments;
|
compatibility; actual targets follow the selected architecture.
|
||||||
their builder accepts `-GpuArch`, and their validation must match the target
|
|
||||||
package before installation. Existing gfx1201 performance measurements are
|
|
||||||
not measurements of gfx1200.
|
|
||||||
The separate experimental FP8/F16 arithmetic and tuning recipes remain
|
|
||||||
gfx1201-specific; this change enables the conservative production baseline
|
|
||||||
on both build targets.
|
|
||||||
|
|
||||||
Equivalent CMake selection is `-DD4R_GPU_ARCH=gfx1200`. Unknown targets fail
|
One command compiles all eleven targets without GPU workloads:
|
||||||
configuration. Some diagnostic executable names and source filenames retain
|
|
||||||
`gfx1201` for compatibility; the logged architecture and compiled code objects
|
|
||||||
use the selected target.
|
|
||||||
|
|
||||||
## First hardware gate on another card
|
|
||||||
|
|
||||||
From the repository root, with the matching diagnostic package above and the
|
|
||||||
pinned dependencies, run this single command:
|
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
.\scripts\windows\test-windows-rdna4.ps1 -RuntimeProfile therock -PackageRoot "$PWD\dist\windows-gfx1200-diagnostics" -ZludaRoot "$PWD\dist\zluda-windows-final"
|
.\scripts\windows\build-windows-gpu-matrix.ps1 -ZludaRoot "$PWD\dist\zluda-windows-final"
|
||||||
```
|
```
|
||||||
|
|
||||||
Success requires exit 0, all selected tests passed in `summary.json`, the
|
Add `-PackageGames -DlssDll "$PWD\nvngx_dlss.dll" -ArchiveDirectory "$PWD\dist\windows-gpu-archives"`
|
||||||
correct actual GPU/target in stdout, exact HIP/PTX/WMMA/pixel-format checks and
|
to stage/archive all packages after committing source and preparing OptiScaler.
|
||||||
stable interop lifetime. On failure, retain the single printed diagnostic ZIP;
|
Use `-GpuArchitectures gfx1100,gfx1101,gfx1102,gfx1200,gfx1201` for a subset.
|
||||||
it includes stdout/stderr, exit code, runtime/driver inventory and DLL identity.
|
Per-target logs and `matrix-build.json` distinguish compilation from execution.
|
||||||
No NVIDIA DLL is required for this first gate. Full K/M reference, temporal,
|
The supplied DLL generates manifests locally and is never copied into archives.
|
||||||
standalone DLSS and game validation are subsequent gates on that hardware;
|
|
||||||
passing the first gate alone does not close them.
|
|
||||||
|
|
||||||
Without that GPU, run `ctest --test-dir build/windows-gfx1200 -L software
|
## Fork adaptation
|
||||||
--output-on-failure`. These CPU/WARP checks do not execute gfx1200 kernels.
|
|
||||||
|
|
||||||
## Fork review
|
Reviewed [realdody's branch](https://github.com/realdody/d4r/tree/windows-rdna3)
|
||||||
|
at `ae530b0f53ed5c0bb87558dd7c20f619e014e4fd` and the newer
|
||||||
|
[`1897b4a` correction](https://github.com/realdody/d4r/commit/1897b4afa79832bd879234cfb37e7c1468db5cde).
|
||||||
|
Earlier MSVC binary16 and generated `BOOL` fixes remain. The earlier forced
|
||||||
|
gfx12 fragment layout is not used.
|
||||||
|
|
||||||
Reviewed [realdody's windows-rdna3 branch](https://github.com/realdody/d4r/tree/windows-rdna3)
|
The newer fork reports Windows gfx1101 `permlanex16` returning its own lane,
|
||||||
at `ae530b0f53ed5c0bb87558dd7c20f619e014e4fd`, on 2026-10-02. Adapted:
|
duplicating even K values into odd slots. This port adapts that finding into
|
||||||
|
`kernels/common/wave32_exchange.h`: a Windows/gfx11-only per-wave LDS exchange,
|
||||||
|
with native gfx11 layout, generic x/y/z indexing, 2 KiB scratch (512 threads
|
||||||
|
maximum), volatile accesses and wave fences/barriers protecting scratch reuse.
|
||||||
|
It covers K/M fragment conversions and other K half-wave exchanges. gfx12 and
|
||||||
|
Linux keep the original instruction path. The raw gfx11 probe uses its actual
|
||||||
|
intrinsic/layout, without a forced gfx12 shim.
|
||||||
|
|
||||||
- Per-target build configuration and actual-target diagnostics, narrowed here
|
The fork reports RX 7800 XT enc1/enc2 identity/nonzero/reference checks. Those
|
||||||
to the two documented RDNA4 subtargets, with package/ELF guards added.
|
are **the author's results**, not validation of this adaptation or full K/M
|
||||||
- MSVC binary16 conversion in the synthetic CUDA MMA reference. An exhaustive
|
here. LDS exchange, full network, translated CUDA, accuracy, interop and speed
|
||||||
CPU test covers 63,490 finite/infinity encodings and 31,743 rounding
|
still need physical gfx11 testing. Credit: realdody <dodobozicek@gmail.com>.
|
||||||
boundaries; LLVM also checks it against native `_Float16` conversion.
|
|
||||||
- `WINBOOL` to `BOOL` normalization in generated D3D12 hooks, so the generated
|
|
||||||
header works with the Microsoft SDK as well as MinGW headers.
|
|
||||||
|
|
||||||
The fork's RDNA3 implementation forces `D4R_WMMA_LAYOUT=12` for gfx11. That
|
## Results and next hardware gate
|
||||||
kernel-layout change, the raw gfx11 probe and the expanded gfx11 runtime
|
|
||||||
allowlist are not imported. Its reported RX 7800 XT/K result has not been
|
|
||||||
independently reproduced here; its M/translated-path limitations still require
|
|
||||||
separate checks. This change does not advertise native Windows RDNA3 readiness.
|
|
||||||
The existing upstream Linux/RDNA3 implementation is unchanged. Credit for
|
|
||||||
the adapted portability fixes: realdody <dodobozicek@gmail.com>.
|
|
||||||
|
|
||||||
## Local results, 2026-10-02
|
All eleven targets compile the complete MinGW host build and 19 device objects
|
||||||
|
with TheRock `10.2.0a20260929`, HIP `7.17.26386`, Clang 24. Software target
|
||||||
|
contracts inspect actual ELF objects without other-target GPU launches.
|
||||||
|
RX 9070 XT passes all 20 CTest gates after these changes. K/M full-frame and
|
||||||
|
package checks are recorded in `windows-rdna4-port.md`. Local logs are in
|
||||||
|
`build/windows-gpu-coverage` and `test-results/windows-gpu-coverage`.
|
||||||
|
|
||||||
- Both targets: complete MinGW host build and 19 device code objects using
|
The first hardware gate on another GPU needs no NVIDIA DLL:
|
||||||
TheRock `10.2.0a20260929`, HIP `7.17.26386`, Clang 24. The runtime, driver,
|
|
||||||
patched ZLUDA and OptiScaler versions are unchanged from the validated port.
|
|
||||||
- gfx1201/RX 9070 XT: 20/20 CTest gates, including 16 physical-GPU gates.
|
|
||||||
- gfx1200: 4/4 software gates; no gfx1200 kernel execution.
|
|
||||||
- MSVC v143 `14.44.35207`: binary16 CPU test passes; CUDA MMA probe and D3D12
|
|
||||||
hook translation units compile. This is not a complete MSVC build claim.
|
|
||||||
- K: 12 finite 4K frames at 2259x1271 input, burst and feature recreation;
|
|
||||||
all six async RGB images exactly match their synchronous controls.
|
|
||||||
- M: eight finite 4K control/candidate frames at the same input dimensions;
|
|
||||||
all four new-build RGB images exactly match the prior validated build.
|
|
||||||
Both presets log every required native layer, zero CPU image copies and
|
|
||||||
current-frame output.
|
|
||||||
- Original gfx1201 objects remain byte-identical on disk. In fresh builds,
|
|
||||||
`.text` and `.rodata*` match the prior gfx1201 objects for all 19 kernels;
|
|
||||||
fresh ELF files have different overall hashes. gfx1200 and gfx1201 have
|
|
||||||
distinct correct ELF targets. Matching instruction sections are compile
|
|
||||||
evidence, not a substitute for testing gfx1200 hardware.
|
|
||||||
- A gfx1200 HIP probe on the physical gfx1201 fails cleanly with exit 4 before
|
|
||||||
any GPU allocation/kernel execution. This tests refusal, not gfx1200 support.
|
|
||||||
- Both target packages pass install/restore checks in isolated workspace
|
|
||||||
fixtures; no game is launched. Only manifest-listed runtime files install.
|
|
||||||
Packaging rejects a mismatched destination or native kernel directory before
|
|
||||||
writing files. Every packaged code object has the expected ELF target.
|
|
||||||
|
|
||||||
Logs are local in `test-results/rdna4-targets-*` and
|
```powershell
|
||||||
`test-results/rdna4-target-objects.json`; they contain no public NVIDIA DLLs.
|
.\scripts\windows\test-windows-rdna4.ps1 -RuntimeProfile therock -PackageRoot "$PWD\dist\windows-gfx1101-diagnostics" -ZludaRoot "$PWD\dist\zluda-windows-final"
|
||||||
|
```
|
||||||
|
|
||||||
|
Success requires exit 0, correct actual target, exact HIP/PTX/WMMA/pixel checks
|
||||||
|
and stable interop lifetime. Failure prints one ZIP. Full K/M reference,
|
||||||
|
temporal, DLSS and game validation remain subsequent gates.
|
||||||
+34
-10
@@ -1,6 +1,7 @@
|
|||||||
# Windows / RDNA4 port
|
# Windows / RDNA4 port
|
||||||
|
|
||||||
Branch: `windows-rdna4`. Native Windows build targets: **gfx1200 / gfx1201**.
|
Branch: `windows-rdna4`. Experimental Windows build targets: **gfx1100..gfx1103,
|
||||||
|
gfx1150..gfx1154, gfx1200 / gfx1201**.
|
||||||
Validated physical hardware: Windows 11 x64, RX 9070 XT, **gfx1201**.
|
Validated physical hardware: Windows 11 x64, RX 9070 XT, **gfx1201**.
|
||||||
Priority: correct K, correct M, native Windows, same-frame output, then speed.
|
Priority: correct K, correct M, native Windows, same-frame output, then speed.
|
||||||
Upstream integration: [PR #11](https://github.com/countervolts/d4r/pull/11)
|
Upstream integration: [PR #11](https://github.com/countervolts/d4r/pull/11)
|
||||||
@@ -18,15 +19,38 @@ explicit limits; the validated package keeps conservative arithmetic.
|
|||||||
|
|
||||||
## Milestone and gates
|
## Milestone and gates
|
||||||
|
|
||||||
2026-10-02 target coverage: gfx1200 and gfx1201 now have separate host/device
|
2026-10-02 coverage: all eleven listed RDNA3 / RDNA3.5 / RDNA4 targets compile
|
||||||
builds and guarded packages. Both compile; gfx1201 passes 20 CTest gates on
|
with separate host/device objects and guarded packages. Only RX 9070 XT has
|
||||||
RX 9070 XT, and gfx1200 passes four software-only gates. No physical gfx1200
|
physical validation here; no other-target GPU workloads are executed. The
|
||||||
test is available. K's new host build passes twelve finite 4K burst/recreation
|
newest realdody correction informs a Windows-only gfx11 LDS half-wave exchange
|
||||||
frames with all six async RGB images exact. M's four new-build 4K RGB images
|
preserving native gfx11 WMMA layout. gfx12 and Linux keep their original
|
||||||
exactly match the previous build. The fork audit, adopted MSVC fixes,
|
instruction path. A shared registry drives build, runtime, ELF checks and
|
||||||
per-target commands, validation limits and first hardware gate are maintained
|
scripts. HIP selection matches the D3D12 LUID before selecting an ordinal,
|
||||||
in [windows-gpu-support.md](windows-gpu-support.md). RDNA3 runtime/layout changes
|
including same-target multi-GPU systems.
|
||||||
from the reviewed fork are not imported. K performance remains open.
|
|
||||||
|
Issue #10 comment 5952822115 contains 32 logs / eight attempts: all discover
|
||||||
|
RX 9060 XT / gfx1200 but reject the old gfx1201 package before NGX runtime
|
||||||
|
initialization. Three also load a vkd3d-proton D3D12 proxy. The installer now
|
||||||
|
catches these conditions before changing game files and prints one diagnostic
|
||||||
|
ZIP. The next community gate is the gfx1200 package on native D3D12; those logs
|
||||||
|
do not establish a native K/M crash. Coverage, sources, fork credit, commands
|
||||||
|
and hardware limits are in [windows-gpu-support.md](windows-gpu-support.md).
|
||||||
|
|
||||||
|
The rebuilt gfx1201 passes 20/20 CTest gates on RX 9070 XT. K completes twelve
|
||||||
|
finite 4K burst/recreation frames at 2259x1271 input, with all six async RGB
|
||||||
|
images exactly matching sync. M completes eight finite control/candidate 4K
|
||||||
|
frames, with all four candidate RGB images matching the prior build exactly.
|
||||||
|
Both log every required native layer, zero CPU frame copies and frame age 0.
|
||||||
|
All 209 compiled objects have the correct ELF target. For all nineteen gfx1201
|
||||||
|
objects, instruction/constant sections match the previous validated build.
|
||||||
|
|
||||||
|
All eleven game directories stage strict K/M baselines without NVIDIA DLLs.
|
||||||
|
An isolated gfx1201 install/restore fixture preserves original bytes; wrong
|
||||||
|
gfx1200-on-gfx1201 and dummy vkd3d-proxy fixtures refuse before game changes
|
||||||
|
and produce one diagnostic ZIP each. The real game installation is untouched.
|
||||||
|
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.
|
||||||
|
|
||||||
**Current milestone: K performance remains open.** The latest unprofiled 4K
|
**Current milestone: K performance remains open.** The latest unprofiled 4K
|
||||||
Silent Hill 2 scene capture records 65.250 FPS. Functional K/M and the
|
Silent Hill 2 scene capture records 65.250 FPS. Functional K/M and the
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// Windows gfx11 portability workaround informed by realdody/d4r 1897b4a.
|
||||||
|
// The reported permlanex16 failure duplicates the even K value into the odd
|
||||||
|
// slot. Retain the native gfx11 layout and exchange through per-wave LDS.
|
||||||
|
// Other platforms and gfx12 keep their original instruction sequence.
|
||||||
|
__attribute__((device, always_inline)) static inline uint32_t d4r_wave32_other_half(uint32_t value)
|
||||||
|
{
|
||||||
|
#if defined(D4R_WINDOWS_GFX11_LANE_EXCHANGE) && defined(__GFX11__)
|
||||||
|
__attribute__((shared)) volatile uint32_t scratch[512];
|
||||||
|
const uint32_t tid = __builtin_amdgcn_workitem_id_x() + __builtin_amdgcn_workgroup_size_x() *
|
||||||
|
(__builtin_amdgcn_workitem_id_y() + __builtin_amdgcn_workgroup_size_y() * __builtin_amdgcn_workitem_id_z());
|
||||||
|
// All native K/M launch bounds are <=512. Do not silently corrupt LDS if
|
||||||
|
// this helper is later reused by a larger workgroup.
|
||||||
|
if (tid >= 512) __builtin_trap();
|
||||||
|
scratch[tid] = value;
|
||||||
|
__builtin_amdgcn_fence(__ATOMIC_RELEASE, "wavefront");
|
||||||
|
__builtin_amdgcn_wave_barrier();
|
||||||
|
__builtin_amdgcn_fence(__ATOMIC_ACQUIRE, "wavefront");
|
||||||
|
const uint32_t result = scratch[tid ^ 16u];
|
||||||
|
// Protect scratch reuse by the next exchange in this wave. No block-wide
|
||||||
|
// rendezvous: different waves can reach GEMMs in a different order.
|
||||||
|
__builtin_amdgcn_fence(__ATOMIC_RELEASE, "wavefront");
|
||||||
|
__builtin_amdgcn_wave_barrier();
|
||||||
|
__builtin_amdgcn_fence(__ATOMIC_ACQUIRE, "wavefront");
|
||||||
|
return result;
|
||||||
|
#else
|
||||||
|
return __builtin_amdgcn_permlanex16(value, value, 0x76543210u, 0xfedcba98u, false, false);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include "wave32_exchange.h"
|
||||||
|
|
||||||
// d4r's gfx11 interface: each lane supplies 16 FP16 K operands. The 8 FP32
|
// d4r's gfx11 interface: each lane supplies 16 FP16 K operands. The 8 FP32
|
||||||
// outputs have logical row 2*i + lane/16 and logical column lane%16.
|
// outputs have logical row 2*i + lane/16 and logical column lane%16.
|
||||||
@@ -13,8 +14,7 @@ using d4r_wmma_f8 = float __attribute__((ext_vector_type(8)));
|
|||||||
__attribute__((device, always_inline)) static inline float d4r_wmma_other_half(float value)
|
__attribute__((device, always_inline)) static inline float d4r_wmma_other_half(float value)
|
||||||
{
|
{
|
||||||
const uint32_t bits = __builtin_bit_cast(uint32_t, value);
|
const uint32_t bits = __builtin_bit_cast(uint32_t, value);
|
||||||
const uint32_t swapped = __builtin_amdgcn_permlanex16(
|
const uint32_t swapped = d4r_wave32_other_half(bits);
|
||||||
bits, bits, 0x76543210u, 0xfedcba98u, false, false);
|
|
||||||
return __builtin_bit_cast(float, swapped);
|
return __builtin_bit_cast(float, swapped);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ d4r_wmma_legacy_layout(d4r_wmma_h16 a, d4r_wmma_h16 b, d4r_wmma_f8 c)
|
|||||||
result[i] = (row >> 3) == group ? d12[new_index] : remote_d[new_index];
|
result[i] = (row >> 3) == group ? d12[new_index] : remote_d[new_index];
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
#elif defined(__gfx1100__) || defined(__gfx1101__) || defined(__gfx1102__) || defined(__gfx1103__)
|
#elif defined(__GFX11__)
|
||||||
return __builtin_amdgcn_wmma_f32_16x16x16_f16_w32(a, b, c);
|
return __builtin_amdgcn_wmma_f32_16x16x16_f16_w32(a, b, c);
|
||||||
#else
|
#else
|
||||||
#error "d4r WMMA backend requires a validated gfx11 or gfx12 target"
|
#error "d4r WMMA backend requires a validated gfx11 or gfx12 target"
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
// Only clang builtins are used (the texture tails compile with -nogpuinc -nogpulib).
|
// Only clang builtins are used (the texture tails compile with -nogpuinc -nogpulib).
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include "wave32_exchange.h"
|
||||||
|
|
||||||
#ifndef D4R_WMMA_LAYOUT
|
#ifndef D4R_WMMA_LAYOUT
|
||||||
#if defined(__GFX12__)
|
#if defined(__GFX12__)
|
||||||
@@ -56,7 +57,7 @@ WM_FN uint32_t wm_half()
|
|||||||
// value of the lane with the same index in the other half of the wave
|
// value of the lane with the same index in the other half of the wave
|
||||||
WM_FN uint32_t wm_other_half(uint32_t v)
|
WM_FN uint32_t wm_other_half(uint32_t v)
|
||||||
{
|
{
|
||||||
return __builtin_amdgcn_permlanex16(v, v, 0x76543210u, 0xfedcba98u, false, false);
|
return d4r_wave32_other_half(v);
|
||||||
}
|
}
|
||||||
WM_FN float wm_other_half_f(float v)
|
WM_FN float wm_other_half_f(float v)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ __device__ __forceinline__ acc8v splat8(float v)
|
|||||||
|
|
||||||
__device__ __forceinline__ uint32_t other_half(uint32_t v)
|
__device__ __forceinline__ uint32_t other_half(uint32_t v)
|
||||||
{
|
{
|
||||||
return __builtin_amdgcn_permlanex16(v, v, 0x76543210u, 0xfedcba98u, false, false);
|
return wm_other_half(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
__device__ __forceinline__ uint32_t pack2(half_t lo, half_t hi)
|
__device__ __forceinline__ uint32_t pack2(half_t lo, half_t hi)
|
||||||
|
|||||||
@@ -5,10 +5,12 @@ param(
|
|||||||
[string]$HipRoot = 'C:\Program Files\AMD\ROCm\7.2',
|
[string]$HipRoot = 'C:\Program Files\AMD\ROCm\7.2',
|
||||||
[string]$ZludaRoot,
|
[string]$ZludaRoot,
|
||||||
[ValidateSet('cu','wgp')][string]$ShaderMode='cu',
|
[ValidateSet('cu','wgp')][string]$ShaderMode='cu',
|
||||||
[ValidateSet('gfx1200','gfx1201')][string]$GpuArch='gfx1201',
|
[string]$GpuArch='gfx1201',
|
||||||
[string]$OutputDirectory
|
[string]$OutputDirectory
|
||||||
)
|
)
|
||||||
$ErrorActionPreference='Stop'
|
$ErrorActionPreference='Stop'
|
||||||
|
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
|
||||||
|
[void](Get-D4RGpuTargetInfo $GpuArch)
|
||||||
$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
|
$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
|
||||||
if (!$ZludaRoot) { $ZludaRoot=Join-Path $repo 'dist/zluda-windows-final' }
|
if (!$ZludaRoot) { $ZludaRoot=Join-Path $repo 'dist/zluda-windows-final' }
|
||||||
if (!$OutputDirectory) { $OutputDirectory=Join-Path $repo "build/private-textures-$GpuArch" }
|
if (!$OutputDirectory) { $OutputDirectory=Join-Path $repo "build/private-textures-$GpuArch" }
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
[CmdletBinding()]
|
||||||
|
param(
|
||||||
|
[string[]]$GpuArchitectures,
|
||||||
|
[ValidateSet('stable','therock')][string]$RuntimeProfile='therock',
|
||||||
|
[string]$ZludaRoot, [string]$DlssDll,
|
||||||
|
[switch]$PackageGames,
|
||||||
|
[string]$BuildRoot, [string]$OutputRoot, [string]$ArchiveDirectory
|
||||||
|
)
|
||||||
|
$ErrorActionPreference='Stop'
|
||||||
|
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
|
||||||
|
$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
|
||||||
|
if (!$GpuArchitectures) { $GpuArchitectures=@(Get-D4RGpuTargets | ForEach-Object { $_.architecture }) }
|
||||||
|
foreach ($arch in $GpuArchitectures) { [void](Get-D4RGpuTargetInfo $arch) }
|
||||||
|
if (@($GpuArchitectures | Select-Object -Unique).Count -ne $GpuArchitectures.Count) { throw 'Duplicate GPU target.' }
|
||||||
|
if (!$BuildRoot) { $BuildRoot=Join-Path $repo 'build/windows-gpu-coverage' }
|
||||||
|
if (!$OutputRoot) { $OutputRoot=Join-Path $repo 'dist/windows-gpu-coverage' }
|
||||||
|
if (!$ZludaRoot) { $ZludaRoot=Join-Path $repo 'dist/zluda-windows-final' }
|
||||||
|
if ($ArchiveDirectory -and !$PackageGames) { throw 'ArchiveDirectory requires PackageGames.' }
|
||||||
|
if ($PackageGames -and (!$DlssDll -or ![IO.Path]::IsPathRooted($DlssDll) -or !(Test-Path -LiteralPath $DlssDll))) {
|
||||||
|
throw 'PackageGames requires an absolute path to your local nvngx_dlss.dll; it will not be redistributed.'
|
||||||
|
}
|
||||||
|
New-Item -ItemType Directory -Force $BuildRoot | Out-Null
|
||||||
|
if ($ArchiveDirectory) { New-Item -ItemType Directory -Force $ArchiveDirectory | Out-Null }
|
||||||
|
$results=[Collections.Generic.List[object]]::new()
|
||||||
|
foreach ($arch in $GpuArchitectures) {
|
||||||
|
$build="$BuildRoot-$arch"; $diag="$OutputRoot-$arch"
|
||||||
|
$log=Join-Path $BuildRoot "$arch-build.log"
|
||||||
|
Write-Host "Building $arch (compile/package only; no GPU workloads). Log: $log"
|
||||||
|
& (Join-Path $PSScriptRoot 'build-windows-rdna4.ps1') -RuntimeProfile $RuntimeProfile -GpuArch $arch `
|
||||||
|
-ZludaRoot $ZludaRoot -BuildDirectory $build -InstallDirectory $diag *> $log
|
||||||
|
$row=[ordered]@{architecture=$arch; compiled=$true; hardwareTestExecuted=$false; buildDirectory=$build; diagnosticRoot=$diag; log=$log}
|
||||||
|
if ($PackageGames) {
|
||||||
|
$k="$BuildRoot-native-k-$arch"; $m="$BuildRoot-native-m-$arch"; $game="$OutputRoot-game-$arch"
|
||||||
|
& (Join-Path $PSScriptRoot 'stage-native-k.ps1') -DlssDll $DlssDll -PackageRoot $diag -GpuArch $arch -OutputDirectory $k
|
||||||
|
& (Join-Path $PSScriptRoot 'stage-native-m.ps1') -DlssDll $DlssDll -PackageRoot $diag -GpuArch $arch -OutputDirectory $m
|
||||||
|
$packageArgs=@{DiagnosticRoot=$diag; GpuArch=$arch; PackageRoot=$game; ZludaRoot=$ZludaRoot; KernelKRoot=$k; KernelMRoot=$m}
|
||||||
|
if ($ArchiveDirectory) { $packageArgs.ArchivePath=Join-Path $ArchiveDirectory "d4r-windows-$arch.zip" }
|
||||||
|
& (Join-Path $PSScriptRoot 'package-windows-game.ps1') @packageArgs
|
||||||
|
$row.gamePackage=$game
|
||||||
|
}
|
||||||
|
$results.Add($row)
|
||||||
|
$results | ConvertTo-Json -Depth 5 | Set-Content (Join-Path $BuildRoot 'matrix-build.json') -Encoding UTF8
|
||||||
|
Write-Host "Compiled $arch; hardware validation remains separate."
|
||||||
|
}
|
||||||
@@ -2,13 +2,15 @@
|
|||||||
param(
|
param(
|
||||||
[string]$HipRoot = $env:HIP_PATH,
|
[string]$HipRoot = $env:HIP_PATH,
|
||||||
[ValidateSet('stable', 'therock')][string]$RuntimeProfile = 'stable',
|
[ValidateSet('stable', 'therock')][string]$RuntimeProfile = 'stable',
|
||||||
[ValidateSet('gfx1200','gfx1201')][string]$GpuArch = 'gfx1201',
|
[string]$GpuArch = 'gfx1201',
|
||||||
[string]$ZludaRoot,
|
[string]$ZludaRoot,
|
||||||
[string]$ToolchainRoot,
|
[string]$ToolchainRoot,
|
||||||
[string]$BuildDirectory,
|
[string]$BuildDirectory,
|
||||||
[string]$InstallDirectory
|
[string]$InstallDirectory
|
||||||
)
|
)
|
||||||
$ErrorActionPreference = 'Stop'
|
$ErrorActionPreference = 'Stop'
|
||||||
|
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
|
||||||
|
[void](Get-D4RGpuTargetInfo $GpuArch)
|
||||||
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
|
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
|
||||||
if ($RuntimeProfile -eq 'therock') {
|
if ($RuntimeProfile -eq 'therock') {
|
||||||
if (!$PSBoundParameters.ContainsKey('HipRoot')) { $HipRoot = Join-Path $repo '.tools/therock-10.2.0a20260929/_rocm_sdk_core' }
|
if (!$PSBoundParameters.ContainsKey('HipRoot')) { $HipRoot = Join-Path $repo '.tools/therock-10.2.0a20260929/_rocm_sdk_core' }
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
# Read-only inventory before touching game files. It allocates no GPU memory
|
||||||
|
# and executes no kernels; successful discovery is not hardware validation.
|
||||||
|
function Invoke-D4RGpuPreflight([string]$PackageRoot, [string]$GameDirectory, [string]$Target, [string]$OutputDirectory) {
|
||||||
|
New-Item -ItemType Directory -Force $OutputDirectory | Out-Null
|
||||||
|
$result=[ordered]@{passed=$false; target=$Target; gpuWorkExecuted=$false; failure=$null}
|
||||||
|
try {
|
||||||
|
$proxy=Join-Path $GameDirectory 'd3d12.dll'
|
||||||
|
if (Test-Path -LiteralPath $proxy) {
|
||||||
|
$item=Get-Item -LiteralPath $proxy
|
||||||
|
$result.localD3D12=@{path=$proxy; sha256=(Get-FileHash -LiteralPath $proxy).Hash; product=$item.VersionInfo.ProductName}
|
||||||
|
# Identify known Vulkan/Wine proxies by their own strings. Do not
|
||||||
|
# load, remove or replace a third-party game DLL.
|
||||||
|
if ($item.Length -le 64MB -and [Text.Encoding]::ASCII.GetString([IO.File]::ReadAllBytes($proxy)) -match '(?i)vkd3d|wined3d') {
|
||||||
|
throw 'Local d3d12.dll identifies as vkd3d/Wine. Restore the game native D3D12 installation before using this Windows backend.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$info=[Diagnostics.ProcessStartInfo]::new()
|
||||||
|
$info.FileName=Join-Path $PackageRoot 'd4r/d4r_gpu_inventory.exe'
|
||||||
|
$hip=Join-Path $PackageRoot 'd4r/hip'
|
||||||
|
foreach ($value in @($hip,$OutputDirectory)) { if ($value.Contains('"')) { throw 'Unsupported quote in inventory path.' } }
|
||||||
|
$info.Arguments='--hip-root "' + $hip + '" --output-dir "' + $OutputDirectory + '"'
|
||||||
|
$info.UseShellExecute=$false; $info.CreateNoWindow=$true
|
||||||
|
$info.EnvironmentVariables['D4R_DIAG_DIR']=$OutputDirectory
|
||||||
|
$info.RedirectStandardOutput=$true; $info.RedirectStandardError=$true
|
||||||
|
$process=[Diagnostics.Process]::new(); $process.StartInfo=$info
|
||||||
|
try {
|
||||||
|
if (!$process.Start()) { throw 'Cannot start GPU inventory.' }
|
||||||
|
$stdout=$process.StandardOutput.ReadToEndAsync(); $stderr=$process.StandardError.ReadToEndAsync()
|
||||||
|
$timedOut=!$process.WaitForExit(30000)
|
||||||
|
if ($timedOut) { $process.Kill(); $process.WaitForExit() }
|
||||||
|
$stdout.GetAwaiter().GetResult() | Set-Content (Join-Path $OutputDirectory 'gpu-inventory.stdout.log') -Encoding UTF8
|
||||||
|
$stderr.GetAwaiter().GetResult() | Set-Content (Join-Path $OutputDirectory 'gpu-inventory.stderr.log') -Encoding UTF8
|
||||||
|
$result.exitCode=$process.ExitCode
|
||||||
|
$result.exceptionOrExitHex='0x{0:X8}' -f [BitConverter]::ToUInt32([BitConverter]::GetBytes([int]$process.ExitCode),0)
|
||||||
|
if ($timedOut) { $result.timedOut=$true; throw 'HIP inventory timed out after 30 seconds.' }
|
||||||
|
if ($process.ExitCode) { throw "HIP inventory failed (exit $($process.ExitCode))." }
|
||||||
|
} finally { $process.Dispose() }
|
||||||
|
$inventory=Get-Content (Join-Path $OutputDirectory 'gpu-inventory.json') -Raw | ConvertFrom-Json
|
||||||
|
$result.inventory=$inventory
|
||||||
|
if ($inventory.compiledTarget -ne $Target) { throw "Inventory executable targets $($inventory.compiledTarget); package requires $Target." }
|
||||||
|
$matching=@($inventory.devices | Where-Object { $_.architecture -eq $Target -and $_.wavefrontSize -eq 32 })
|
||||||
|
if (!$matching.Count) {
|
||||||
|
$actual=@($inventory.devices | ForEach-Object { "$($_.architecture) ($($_.name))" }) -join ', '
|
||||||
|
throw "GPU target mismatch: detected $actual; package requires $Target. Use the package for the actual HIP architecture; do not rename code objects."
|
||||||
|
}
|
||||||
|
$result.passed=$true
|
||||||
|
Write-Host "D4R_PREFLIGHT target=$Target devices=$($matching.Count) gpu_work_executed=0"
|
||||||
|
} catch {
|
||||||
|
$result.failure=$_.Exception.Message
|
||||||
|
$result | ConvertTo-Json -Depth 8 | Set-Content (Join-Path $OutputDirectory 'preflight.json') -Encoding UTF8
|
||||||
|
try { Get-CimInstance Win32_VideoController | Select-Object Name,DriverVersion,DriverDate | ConvertTo-Json |
|
||||||
|
Set-Content (Join-Path $OutputDirectory 'driver.json') -Encoding UTF8 } catch {}
|
||||||
|
$bundle=$OutputDirectory+'.zip'
|
||||||
|
Compress-Archive -Path (Join-Path $OutputDirectory '*') -DestinationPath $bundle -Force
|
||||||
|
throw "$($result.failure) Diagnostic bundle: $bundle"
|
||||||
|
}
|
||||||
|
$result | ConvertTo-Json -Depth 8 | Set-Content (Join-Path $OutputDirectory 'preflight.json') -Encoding UTF8
|
||||||
|
}
|
||||||
@@ -1,19 +1,31 @@
|
|||||||
# Shared by the build, diagnostics, staging and game package scripts.
|
# Shared by the build, diagnostics, staging and game package scripts.
|
||||||
|
function Get-D4RGpuTargets {
|
||||||
|
$registry=Join-Path $PSScriptRoot 'gpu-targets.json'
|
||||||
|
if (!(Test-Path -LiteralPath $registry)) { $registry=Join-Path $PSScriptRoot '../../tools/windows/gpu-targets.json' }
|
||||||
|
$data=Get-Content -LiteralPath $registry -Raw | ConvertFrom-Json
|
||||||
|
if ($data.schema -ne 1) { throw 'Unsupported GPU target registry schema.' }
|
||||||
|
return $data.targets
|
||||||
|
}
|
||||||
|
function Get-D4RGpuTargetInfo([string]$Target) {
|
||||||
|
$info=@(Get-D4RGpuTargets | Where-Object { $_.architecture -eq $Target })
|
||||||
|
if ($info.Count -ne 1) { throw "Unsupported GPU target: $Target" }
|
||||||
|
return $info[0]
|
||||||
|
}
|
||||||
function Get-D4RGpuTarget([string]$Root, [string]$Requested) {
|
function Get-D4RGpuTarget([string]$Root, [string]$Requested) {
|
||||||
$configured=$null
|
$configured=$null
|
||||||
$targetFile=Join-Path $Root 'gpu-target.json'
|
$targetFile=Join-Path $Root 'gpu-target.json'
|
||||||
if (Test-Path -LiteralPath $targetFile) {
|
if (Test-Path -LiteralPath $targetFile) {
|
||||||
$configured=(Get-Content -LiteralPath $targetFile -Raw | ConvertFrom-Json).architecture
|
$configured=(Get-Content -LiteralPath $targetFile -Raw | ConvertFrom-Json).architecture
|
||||||
if ($configured -notin @('gfx1200','gfx1201')) { throw "Unsupported package GPU target: $configured" }
|
[void](Get-D4RGpuTargetInfo $configured)
|
||||||
}
|
}
|
||||||
$target=if ($Requested) { $Requested } elseif ($configured) { $configured } else { 'gfx1201' }
|
$target=if ($Requested) { $Requested } elseif ($configured) { $configured } else { 'gfx1201' }
|
||||||
if ($target -notin @('gfx1200','gfx1201')) { throw "Unsupported GPU target: $target" }
|
[void](Get-D4RGpuTargetInfo $target)
|
||||||
if (!$configured -and $target -ne 'gfx1201') { throw 'A gfx1200 build requires gpu-target.json; rebuild with -GpuArch gfx1200.' }
|
if (!$configured -and $target -ne 'gfx1201') { throw "A $target build requires gpu-target.json; rebuild with -GpuArch $target." }
|
||||||
if ($configured -and $target -ne $configured) { throw "Requested $target differs from package target $configured" }
|
if ($configured -and $target -ne $configured) { throw "Requested $target differs from package target $configured" }
|
||||||
return $target
|
return $target
|
||||||
}
|
}
|
||||||
function Assert-D4RCodeObjectTarget([string]$Path, [string]$Target) {
|
function Assert-D4RCodeObjectTarget([string]$Path, [string]$Target) {
|
||||||
if ($Target -notin @('gfx1200','gfx1201')) { throw "Unsupported GPU target: $Target" }
|
$info=Get-D4RGpuTargetInfo $Target
|
||||||
$reader=[IO.BinaryReader]::new([IO.File]::OpenRead($Path))
|
$reader=[IO.BinaryReader]::new([IO.File]::OpenRead($Path))
|
||||||
try { $header=$reader.ReadBytes(64) } finally { $reader.Dispose() }
|
try { $header=$reader.ReadBytes(64) } finally { $reader.Dispose() }
|
||||||
if ($header.Length -ne 64 -or $header[0] -ne 127 -or $header[1] -ne 69 -or $header[2] -ne 76 -or $header[3] -ne 70 -or
|
if ($header.Length -ne 64 -or $header[0] -ne 127 -or $header[1] -ne 69 -or $header[2] -ne 76 -or $header[3] -ne 70 -or
|
||||||
@@ -21,6 +33,6 @@ function Assert-D4RCodeObjectTarget([string]$Path, [string]$Target) {
|
|||||||
throw "Invalid AMDGPU ELF64 code object: $Path"
|
throw "Invalid AMDGPU ELF64 code object: $Path"
|
||||||
}
|
}
|
||||||
# LLVM AMDGPU e_flags machine IDs; inspect, never patch or spoof them.
|
# LLVM AMDGPU e_flags machine IDs; inspect, never patch or spoof them.
|
||||||
$expected=if ($Target -eq 'gfx1200') { 0x48 } else { 0x4e }
|
$expected=$info.elfMachine
|
||||||
if ($header[48] -ne $expected) { throw "Code object does not target ${Target}: $Path (ELF machine=$($header[48]))" }
|
if ($header[48] -ne $expected) { throw "Code object does not target ${Target}: $Path (ELF machine=$($header[48]))" }
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
param(
|
param(
|
||||||
[string]$PackageRoot, [string]$DiagnosticRoot, [string]$OptiScalerRoot,
|
[string]$PackageRoot, [string]$DiagnosticRoot, [string]$OptiScalerRoot,
|
||||||
[string]$ZludaRoot, [string]$HipRoot, [string]$KernelKRoot, [string]$KernelMRoot,
|
[string]$ZludaRoot, [string]$HipRoot, [string]$KernelKRoot, [string]$KernelMRoot,
|
||||||
[ValidateSet('gfx1200','gfx1201')][string]$GpuArch,
|
[string]$GpuArch,
|
||||||
[string]$ArchivePath
|
[string]$ArchivePath
|
||||||
)
|
)
|
||||||
$ErrorActionPreference = 'Stop'
|
$ErrorActionPreference = 'Stop'
|
||||||
@@ -15,7 +15,7 @@ foreach ($name in $defaults.Keys) {
|
|||||||
if (!(Get-Variable -Name $name -ValueOnly)) { Set-Variable -Name $name -Value (Join-Path $repo $defaults[$name]) }
|
if (!(Get-Variable -Name $name -ValueOnly)) { Set-Variable -Name $name -Value (Join-Path $repo $defaults[$name]) }
|
||||||
}
|
}
|
||||||
$GpuArch=Get-D4RGpuTarget $DiagnosticRoot $GpuArch
|
$GpuArch=Get-D4RGpuTarget $DiagnosticRoot $GpuArch
|
||||||
if ($GpuArch -eq 'gfx1200' -and !$PSBoundParameters.ContainsKey('PackageRoot')) { $PackageRoot += '-gfx1200' }
|
if ($GpuArch -ne 'gfx1201' -and !$PSBoundParameters.ContainsKey('PackageRoot')) { $PackageRoot += "-$GpuArch" }
|
||||||
if (!$KernelKRoot) { $KernelKRoot=Join-Path $repo "build/native-k-$GpuArch" }
|
if (!$KernelKRoot) { $KernelKRoot=Join-Path $repo "build/native-k-$GpuArch" }
|
||||||
if (!$KernelMRoot) { $KernelMRoot=Join-Path $repo "build/native-m-$GpuArch" }
|
if (!$KernelMRoot) { $KernelMRoot=Join-Path $repo "build/native-m-$GpuArch" }
|
||||||
foreach ($directory in @($KernelKRoot,$KernelMRoot)) {
|
foreach ($directory in @($KernelKRoot,$KernelMRoot)) {
|
||||||
@@ -46,6 +46,7 @@ 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 "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 '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_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 @('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')) {
|
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"
|
Stage (Join-Path $HipRoot "bin/$file") "d4r/hip/bin/$file"
|
||||||
@@ -66,6 +67,8 @@ if ($entries.Count -ne 16) { throw "Expected 11 K and 5 M native objects; found
|
|||||||
$stagedFiles.Add('d4r/native/d4r-kernels.txt')
|
$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/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-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')) {
|
if (Test-Path -LiteralPath (Join-Path $DiagnosticRoot 'gpu-target.json')) {
|
||||||
Stage (Join-Path $DiagnosticRoot 'gpu-target.json') 'gpu-target.json'
|
Stage (Join-Path $DiagnosticRoot 'gpu-target.json') 'gpu-target.json'
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
param([Parameter(Mandatory=$true)][string]$DlssDll, [string]$PackageRoot, [string]$OutputDirectory, [ValidateSet('gfx1200','gfx1201')][string]$GpuArch)
|
param([Parameter(Mandatory=$true)][string]$DlssDll, [string]$PackageRoot, [string]$OutputDirectory, [string]$GpuArch)
|
||||||
$ErrorActionPreference = 'Stop'
|
$ErrorActionPreference = 'Stop'
|
||||||
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
|
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
|
||||||
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
|
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
param([Parameter(Mandatory=$true)][string]$DlssDll, [string]$PackageRoot, [string]$OutputDirectory, [ValidateSet('gfx1200','gfx1201')][string]$GpuArch)
|
param([Parameter(Mandatory=$true)][string]$DlssDll, [string]$PackageRoot, [string]$OutputDirectory, [string]$GpuArch)
|
||||||
$ErrorActionPreference = 'Stop'
|
$ErrorActionPreference = 'Stop'
|
||||||
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
|
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
|
||||||
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
|
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ param(
|
|||||||
[ValidateSet('stable', 'therock')][string]$RuntimeProfile = 'stable',
|
[ValidateSet('stable', 'therock')][string]$RuntimeProfile = 'stable',
|
||||||
[string]$ZludaRoot,
|
[string]$ZludaRoot,
|
||||||
[string]$PackageRoot,
|
[string]$PackageRoot,
|
||||||
[ValidateSet('gfx1200','gfx1201')][string]$GpuArch,
|
[string]$GpuArch,
|
||||||
[string]$OutputDirectory,
|
[string]$OutputDirectory,
|
||||||
[string]$NgxCore = $env:D4R_NGX_CORE,
|
[string]$NgxCore = $env:D4R_NGX_CORE,
|
||||||
[string]$DlssDll = $env:D4R_DLSS_DLL,
|
[string]$DlssDll = $env:D4R_DLSS_DLL,
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ param(
|
|||||||
)
|
)
|
||||||
$ErrorActionPreference = 'Stop'
|
$ErrorActionPreference = 'Stop'
|
||||||
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
|
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
|
||||||
|
. (Join-Path $PSScriptRoot 'gpu-preflight.ps1')
|
||||||
if ($ProfileGpuBoundary -and !$AsyncInterop) { throw '-ProfileGpuBoundary requires -AsyncInterop.' }
|
if ($ProfileGpuBoundary -and !$AsyncInterop) { throw '-ProfileGpuBoundary requires -AsyncInterop.' }
|
||||||
if ($ProfileKernels -and $ProfileKernelsDeferred) { throw 'Choose either serializing or deferred kernel profiling.' }
|
if ($ProfileKernels -and $ProfileKernelsDeferred) { throw 'Choose either serializing or deferred kernel profiling.' }
|
||||||
if ($ProfileLegacyStream -and !$ProfileKernelsDeferred) { throw '-ProfileLegacyStream requires -ProfileKernelsDeferred.' }
|
if ($ProfileLegacyStream -and !$ProfileKernelsDeferred) { throw '-ProfileLegacyStream requires -ProfileKernelsDeferred.' }
|
||||||
@@ -74,6 +75,7 @@ foreach ($file in $metadata.files) {
|
|||||||
if ((Get-FileHash -LiteralPath (Join-Path $package $file.path) -Algorithm SHA256).Hash -ne $file.sha256) { throw "Package file changed; rebuild package: $($file.path)" }
|
if ((Get-FileHash -LiteralPath (Join-Path $package $file.path) -Algorithm SHA256).Hash -ne $file.sha256) { throw "Package file changed; rebuild package: $($file.path)" }
|
||||||
}
|
}
|
||||||
if ((Get-FileHash -LiteralPath $DlssDll -Algorithm SHA256).Hash -ne $metadata.dlssSha256) { throw 'DLSS DLL does not match the validated 310.9.1 native manifest. Rebuild and validate native manifests for this DLL first.' }
|
if ((Get-FileHash -LiteralPath $DlssDll -Algorithm SHA256).Hash -ne $metadata.dlssSha256) { throw 'DLSS DLL does not match the validated 310.9.1 native manifest. Rebuild and validate native manifests for this DLL first.' }
|
||||||
|
Invoke-D4RGpuPreflight $package $game $GpuArch (Join-Path $package ('results/preflight-' + (Get-Date -Format 'yyyyMMdd-HHmmss-fff')))
|
||||||
$textureFiles=@(); $textureManifest=@()
|
$textureFiles=@(); $textureManifest=@()
|
||||||
if ($LocalTextureKernels) {
|
if ($LocalTextureKernels) {
|
||||||
$LocalTextureKernels=(Get-Item -LiteralPath $LocalTextureKernels -ErrorAction Stop).FullName
|
$LocalTextureKernels=(Get-Item -LiteralPath $LocalTextureKernels -ErrorAction Stop).FullName
|
||||||
@@ -193,6 +195,7 @@ $settings = @{
|
|||||||
# false have the same numerical effect; unset reuses the validated cache.
|
# false have the same numerical effect; unset reuses the validated cache.
|
||||||
D4R_ZLUDA_IGNORE_DENORMAL=$null; D4R_ZLUDA_FAST_MATH=$null;
|
D4R_ZLUDA_IGNORE_DENORMAL=$null; D4R_ZLUDA_FAST_MATH=$null;
|
||||||
D4R_ZLUDA_WMMA_F32ACC=$null; D4R_ZLUDA_WAVE64=$null;
|
D4R_ZLUDA_WMMA_F32ACC=$null; D4R_ZLUDA_WAVE64=$null;
|
||||||
|
D4R_ZLUDA_WMMA_LAYOUT=$null;
|
||||||
D4R_QUIET_API=$(if ($VerboseRuntime) { $null } else { '1' });
|
D4R_QUIET_API=$(if ($VerboseRuntime) { $null } else { '1' });
|
||||||
D4R_VALIDATE_OUTPUT=$(if ($ValidateOutput) { '1' } else { $null });
|
D4R_VALIDATE_OUTPUT=$(if ($ValidateOutput) { '1' } else { $null });
|
||||||
D4R_PROFILE_STAGES=$(if ($ProfileStages) { '1' } else { $null });
|
D4R_PROFILE_STAGES=$(if ($ProfileStages) { '1' } else { $null });
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
"""Build a private RDNA4 texture override from the user's local DLSS DLL.
|
"""Build a private target-specific texture override from the user's local DLSS DLL.
|
||||||
|
|
||||||
The resulting PTX/code object contains NVIDIA code and must remain local.
|
The resulting PTX/code object contains NVIDIA code and must remain local.
|
||||||
No Wine, shell script, GPU, CUDA SDK or system installation is required.
|
No Wine, shell script, GPU, CUDA SDK or system installation is required.
|
||||||
@@ -13,13 +13,14 @@ import re
|
|||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
from gpu_targets import TARGETS
|
||||||
|
|
||||||
|
|
||||||
def require_code_object_target(path, target):
|
def require_code_object_target(path, target):
|
||||||
with path.open('rb') as file:
|
with path.open('rb') as file:
|
||||||
header = file.read(64)
|
header = file.read(64)
|
||||||
if (len(header) != 64 or header[:6] != b'\x7fELF\x02\x01' or
|
if (len(header) != 64 or header[:6] != b'\x7fELF\x02\x01' or
|
||||||
header[18:20] != b'\xe0\x00' or header[48] != {'gfx1200': 0x48, 'gfx1201': 0x4e}[target]):
|
header[18:20] != b'\xe0\x00' or header[48] != TARGETS[target]['elfMachine']):
|
||||||
raise RuntimeError(f'Code object does not target {target}: {path}')
|
raise RuntimeError(f'Code object does not target {target}: {path}')
|
||||||
|
|
||||||
|
|
||||||
@@ -30,7 +31,7 @@ def main():
|
|||||||
parser.add_argument('--zluda-root', type=pathlib.Path, required=True)
|
parser.add_argument('--zluda-root', type=pathlib.Path, required=True)
|
||||||
parser.add_argument('--kernel', required=True)
|
parser.add_argument('--kernel', required=True)
|
||||||
parser.add_argument('--output-directory', type=pathlib.Path, required=True)
|
parser.add_argument('--output-directory', type=pathlib.Path, required=True)
|
||||||
parser.add_argument('--gpu-arch', choices=['gfx1200', 'gfx1201'], default='gfx1201')
|
parser.add_argument('--gpu-arch', choices=tuple(TARGETS), default='gfx1201')
|
||||||
parser.add_argument('--shader-mode', choices=['cu', 'wgp'], default='cu')
|
parser.add_argument('--shader-mode', choices=['cu', 'wgp'], default='cu')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
if not re.fullmatch(r'hiluma_engine_(?:output_depth(?:inv|reg)_mv(?:hi|lo)_(?:hdr|ldr)(?:_max)?|'
|
if not re.fullmatch(r'hiluma_engine_(?:output_depth(?:inv|reg)_mv(?:hi|lo)_(?:hdr|ldr)(?:_max)?|'
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ API unsigned NVSDK_NGX_D3D12_GetFeatureRequirements(IDXGIAdapter* adapter, const
|
|||||||
DXGI_ADAPTER_DESC desc{}; d4r::win::dx(adapter->GetDesc(&desc), "NGX requirements adapter");
|
DXGI_ADAPTER_DESC desc{}; d4r::win::dx(adapter->GetDesc(&desc), "NGX requirements adapter");
|
||||||
// OptiScaler can override the DXGI vendor ID. The physical HIP
|
// OptiScaler can override the DXGI vendor ID. The physical HIP
|
||||||
// architecture and full adapter LUID are the authoritative identity.
|
// architecture and full adapter LUID are the authoritative identity.
|
||||||
d4r::diag::HipApi hip(d4r::win::env_path("D4R_HIP_ROOT")); hipDeviceProp_t props{}; hip.select_architecture(-1,props);
|
d4r::diag::HipApi hip(d4r::win::env_path("D4R_HIP_ROOT")); hipDeviceProp_t props{}; hip.select_architecture(-1,props,&desc.AdapterLuid);
|
||||||
requirements->FeatureSupported = std::memcmp(&desc.AdapterLuid,props.luid,sizeof(LUID)) ? 4u : 0u;
|
requirements->FeatureSupported = std::memcmp(&desc.AdapterLuid,props.luid,sizeof(LUID)) ? 4u : 0u;
|
||||||
std::strcpy(requirements->MinOSVersion,"10.0.22000.0");
|
std::strcpy(requirements->MinOSVersion,"10.0.22000.0");
|
||||||
std::printf("D4R_REQUIREMENTS feature=%u support=%u architecture=%s\n",info->FeatureID,requirements->FeatureSupported,d4r::diag::HipApi::target_arch());
|
std::printf("D4R_REQUIREMENTS feature=%u support=%u architecture=%s\n",info->FeatureID,requirements->FeatureSupported,d4r::diag::HipApi::target_arch());
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"schema": 1,
|
||||||
|
"targets": [
|
||||||
|
{"architecture":"gfx1100","elfMachine":65,"isaMajor":11,"family":"RDNA3"},
|
||||||
|
{"architecture":"gfx1101","elfMachine":70,"isaMajor":11,"family":"RDNA3"},
|
||||||
|
{"architecture":"gfx1102","elfMachine":71,"isaMajor":11,"family":"RDNA3"},
|
||||||
|
{"architecture":"gfx1103","elfMachine":68,"isaMajor":11,"family":"RDNA3"},
|
||||||
|
{"architecture":"gfx1150","elfMachine":67,"isaMajor":11,"family":"RDNA3.5"},
|
||||||
|
{"architecture":"gfx1151","elfMachine":74,"isaMajor":11,"family":"RDNA3.5"},
|
||||||
|
{"architecture":"gfx1152","elfMachine":85,"isaMajor":11,"family":"RDNA3.5"},
|
||||||
|
{"architecture":"gfx1153","elfMachine":88,"isaMajor":11,"family":"RDNA3.5"},
|
||||||
|
{"architecture":"gfx1154","elfMachine":87,"isaMajor":11,"family":"RDNA3.5"},
|
||||||
|
{"architecture":"gfx1200","elfMachine":72,"isaMajor":12,"family":"RDNA4"},
|
||||||
|
{"architecture":"gfx1201","elfMachine":78,"isaMajor":12,"family":"RDNA4"}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
#include "hip_api.h"
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
|
static std::string json_string(const std::string& value) {
|
||||||
|
std::ostringstream out; out << '"';
|
||||||
|
for (unsigned char c : value) {
|
||||||
|
if (c == '"' || c == '\\') out << '\\' << char(c);
|
||||||
|
else if (c < 32) out << "\\u" << std::hex << std::setw(4) << std::setfill('0') << unsigned(c);
|
||||||
|
else out << char(c);
|
||||||
|
}
|
||||||
|
out << '"'; return out.str();
|
||||||
|
}
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
using namespace d4r::diag;
|
||||||
|
start();
|
||||||
|
try {
|
||||||
|
Args args(argc, argv);
|
||||||
|
if (args.output_dir.empty()) throw std::runtime_error("--output-dir is required");
|
||||||
|
for (const char* name : {"HSA_OVERRIDE_GFX_VERSION", "HSA_OVERRIDE_GFX_VERSION_0"})
|
||||||
|
if (std::getenv(name)) throw std::runtime_error(std::string("Unset architecture override ") + name);
|
||||||
|
HipApi hip(args.hip_root);
|
||||||
|
hip.check(hip.hipInit(0), "hipInit(inventory)");
|
||||||
|
int count=0, version=0, driver=0;
|
||||||
|
hip.check(hip.hipRuntimeGetVersion(&version), "hipRuntimeGetVersion");
|
||||||
|
hip.check(hip.hipDriverGetVersion(&driver), "hipDriverGetVersion");
|
||||||
|
std::printf("GPU_INVENTORY_RUNTIME runtime=%d driver_api=%d headers=%d.%d.%d sizeof(properties)=%zu\n",
|
||||||
|
version,driver,HIP_VERSION_MAJOR,HIP_VERSION_MINOR,HIP_VERSION_PATCH,sizeof(hipDeviceProp_t));
|
||||||
|
hip.check(hip.hipGetDeviceCount(&count), "hipGetDeviceCount");
|
||||||
|
std::ostringstream json;
|
||||||
|
json << "{\"schema\":1,\"runtimeVersion\":" << version << ",\"driverApiVersion\":" << driver << ",\"compiledTarget\":"
|
||||||
|
<< json_string(D4R_TARGET_ARCH) << ",\"gpuWorkExecuted\":false,\"devices\":[";
|
||||||
|
for (int i=0; i<count; ++i) {
|
||||||
|
hipDeviceProp_t p{}; hip.check(hip.hipGetDeviceProperties(&p,i), "hipGetDevicePropertiesR0600");
|
||||||
|
const auto arch=gpu_architecture(p.gcnArchName);
|
||||||
|
std::printf("GPU_INVENTORY ordinal=%d name=%s gcnArchName=%s wave=%d build_eligible=%d\n",
|
||||||
|
i,p.name,p.gcnArchName,p.warpSize,supported_gpu_target(arch));
|
||||||
|
if (i) json << ',';
|
||||||
|
json << "{\"ordinal\":" << i << ",\"name\":" << json_string(p.name)
|
||||||
|
<< ",\"gcnArchName\":" << json_string(p.gcnArchName) << ",\"architecture\":" << json_string(arch)
|
||||||
|
<< ",\"wavefrontSize\":" << p.warpSize << ",\"vramBytes\":" << p.totalGlobalMem
|
||||||
|
<< ",\"buildEligible\":" << (supported_gpu_target(arch) ? "true" : "false") << '}';
|
||||||
|
}
|
||||||
|
json << "]}\n";
|
||||||
|
std::filesystem::create_directories(wide(args.output_dir));
|
||||||
|
std::ofstream file(std::filesystem::path(wide(args.output_dir))/L"gpu-inventory.json",std::ios::binary);
|
||||||
|
file << json.str(); file.close();
|
||||||
|
if (!file) throw std::runtime_error("Cannot write GPU inventory");
|
||||||
|
if (!count) throw std::runtime_error("HIP reports no devices");
|
||||||
|
loaded_modules();
|
||||||
|
std::printf("PASS GPU_INVENTORY devices=%d gpu_work_executed=0\n",count);
|
||||||
|
return 0;
|
||||||
|
} catch (const std::exception& error) {
|
||||||
|
std::fprintf(stderr,"FAIL GPU_INVENTORY %s\n",error.what()); loaded_modules(); return 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include "gpu_targets.generated.h"
|
||||||
|
|
||||||
#ifndef D4R_TARGET_ARCH
|
#ifndef D4R_TARGET_ARCH
|
||||||
#define D4R_TARGET_ARCH "gfx1201"
|
#define D4R_TARGET_ARCH "gfx1201"
|
||||||
@@ -11,7 +12,8 @@
|
|||||||
|
|
||||||
namespace d4r::diag {
|
namespace d4r::diag {
|
||||||
inline bool supported_gpu_target(const std::string& target) {
|
inline bool supported_gpu_target(const std::string& target) {
|
||||||
return target == "gfx1200" || target == "gfx1201";
|
for (const auto& row : gpu_targets) if (target == row.architecture) return true;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
inline std::string gpu_architecture(const std::string& name) {
|
inline std::string gpu_architecture(const std::string& name) {
|
||||||
return name.substr(0, name.find(':'));
|
return name.substr(0, name.find(':'));
|
||||||
@@ -29,11 +31,8 @@ inline std::string code_object_target(const std::filesystem::path& path) {
|
|||||||
header[0] != 0x7f || header[1] != 'E' || header[2] != 'L' || header[3] != 'F' ||
|
header[0] != 0x7f || header[1] != 'E' || header[2] != 'L' || header[3] != 'F' ||
|
||||||
header[4] != 2 || header[5] != 1 || header[18] != 0xe0 || header[19] != 0)
|
header[4] != 2 || header[5] != 1 || header[18] != 0xe0 || header[19] != 0)
|
||||||
throw std::runtime_error("Invalid AMDGPU ELF64 code object: " + path.string());
|
throw std::runtime_error("Invalid AMDGPU ELF64 code object: " + path.string());
|
||||||
switch (header[48]) {
|
for (const auto& row : gpu_targets) if (header[48] == row.elf_machine) return row.architecture;
|
||||||
case 0x48: return "gfx1200";
|
throw std::runtime_error("Unsupported AMDGPU code-object target: " + path.string());
|
||||||
case 0x4e: return "gfx1201";
|
|
||||||
default: throw std::runtime_error("Unsupported AMDGPU code-object target: " + path.string());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
inline void require_code_object_target(const std::filesystem::path& path, const std::string& expected) {
|
inline void require_code_object_target(const std::filesystem::path& path, const std::string& expected) {
|
||||||
require_gpu_target(code_object_target(path), expected);
|
require_gpu_target(code_object_target(path), expected);
|
||||||
|
|||||||
@@ -5,10 +5,11 @@ int main(int argc, char** argv) {
|
|||||||
using namespace d4r::diag;
|
using namespace d4r::diag;
|
||||||
try {
|
try {
|
||||||
unsigned rejected = 0, objects = 0;
|
unsigned rejected = 0, objects = 0;
|
||||||
for (const char* target : {"gfx1200", "gfx1201"}) {
|
for (const auto& info : gpu_targets) {
|
||||||
|
const char* target = info.architecture;
|
||||||
require_gpu_target(target, target);
|
require_gpu_target(target, target);
|
||||||
require_gpu_target(std::string(target) + ":xnack-:sramecc-", target);
|
require_gpu_target(std::string(target) + ":xnack-:sramecc-", target);
|
||||||
for (const char* invalid : {"gfx1101", "gfx12000", "gfx1202", "gfx1250", ""}) {
|
for (const char* invalid : {"gfx1030", "gfx1104", "gfx1155", "gfx1170", "gfx12000", "gfx1202", "gfx1250", ""}) {
|
||||||
try { require_gpu_target(invalid, target); }
|
try { require_gpu_target(invalid, target); }
|
||||||
catch (const std::exception&) { ++rejected; continue; }
|
catch (const std::exception&) { ++rejected; continue; }
|
||||||
throw std::runtime_error("Invalid GPU target accepted");
|
throw std::runtime_error("Invalid GPU target accepted");
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <array>
|
||||||
|
namespace d4r::diag {
|
||||||
|
struct GpuTarget { const char* architecture; unsigned elf_machine; unsigned isa_major; const char* family; };
|
||||||
|
inline constexpr std::array<GpuTarget, @d4r_target_count@> gpu_targets = {{
|
||||||
|
@d4r_target_cpp_entries@}};
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
"""Canonical Windows build target registry, shared with CMake and PowerShell."""
|
||||||
|
import json
|
||||||
|
import pathlib
|
||||||
|
|
||||||
|
data = json.loads(pathlib.Path(__file__).with_name('gpu-targets.json').read_text())
|
||||||
|
if data['schema'] != 1:
|
||||||
|
raise RuntimeError('Unsupported GPU target registry schema')
|
||||||
|
TARGETS = {row['architecture']: row for row in data['targets']}
|
||||||
|
if len(TARGETS) != len(data['targets']):
|
||||||
|
raise RuntimeError('Duplicate GPU target')
|
||||||
@@ -42,7 +42,7 @@ struct HipApi {
|
|||||||
if (result != hipSuccess) throw std::runtime_error(std::string(call) + ": " + hipGetErrorString(result));
|
if (result != hipSuccess) throw std::runtime_error(std::string(call) + ": " + hipGetErrorString(result));
|
||||||
}
|
}
|
||||||
static const char* target_arch() { return D4R_TARGET_ARCH; }
|
static const char* target_arch() { return D4R_TARGET_ARCH; }
|
||||||
int select_architecture(int requested, hipDeviceProp_t& selected) const {
|
int select_architecture(int requested, hipDeviceProp_t& selected, const void* required_luid = nullptr) const {
|
||||||
// Architecture spoofing invalidates a gfx12 correctness test.
|
// Architecture spoofing invalidates a gfx12 correctness test.
|
||||||
for (const char* name : {"HSA_OVERRIDE_GFX_VERSION", "HSA_OVERRIDE_GFX_VERSION_0"})
|
for (const char* name : {"HSA_OVERRIDE_GFX_VERSION", "HSA_OVERRIDE_GFX_VERSION_0"})
|
||||||
if (std::getenv(name)) throw std::runtime_error(std::string("Unset architecture override ") + name);
|
if (std::getenv(name)) throw std::runtime_error(std::string("Unset architecture override ") + name);
|
||||||
@@ -61,12 +61,14 @@ struct HipApi {
|
|||||||
i, props.name, props.gcnArchName, props.warpSize, props.totalGlobalMem,
|
i, props.name, props.gcnArchName, props.warpSize, props.totalGlobalMem,
|
||||||
props.pciDomainID, props.pciBusID, props.pciDeviceID);
|
props.pciDomainID, props.pciBusID, props.pciDeviceID);
|
||||||
const std::string arch = props.gcnArchName;
|
const std::string arch = props.gcnArchName;
|
||||||
if (gpu_architecture(arch) == target_arch() && (requested < 0 || requested == i) && found < 0) {
|
if (gpu_architecture(arch) == target_arch() && (requested < 0 || requested == i) && found < 0 &&
|
||||||
|
(!required_luid || std::memcmp(props.luid, required_luid, sizeof(props.luid)) == 0)) {
|
||||||
found = i;
|
found = i;
|
||||||
selected = props;
|
selected = props;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (found < 0) throw std::runtime_error(std::string("No selected ") + target_arch() + " device; refusing architecture substitution");
|
if (found < 0) throw std::runtime_error(std::string("No selected ") + target_arch() +
|
||||||
|
" device for this adapter; use the package matching the actual HIP architecture (see GPU log)");
|
||||||
require_gpu_target(selected.gcnArchName, target_arch());
|
require_gpu_target(selected.gcnArchName, target_arch());
|
||||||
check(hipSetDevice(found), "hipSetDevice");
|
check(hipSetDevice(found), "hipSetDevice");
|
||||||
std::printf("SELECTED HIP ordinal=%d architecture=%s validation=%s\n", found, target_arch(),
|
std::printf("SELECTED HIP ordinal=%d architecture=%s validation=%s\n", found, target_arch(),
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""Compare RDNA4 K enc1/enc2 launches with the existing numpy reference."""
|
"""Compare native K enc1/enc2 launches with the existing numpy reference."""
|
||||||
import argparse
|
import argparse
|
||||||
import math
|
import math
|
||||||
import pathlib
|
import pathlib
|
||||||
@@ -73,7 +73,7 @@ def main():
|
|||||||
# after each K stage has been compared on captured DLSS weights/activations.
|
# after each K stage has been compared on captured DLSS weights/activations.
|
||||||
if full_abs > 0.001 or full_psnr < 60.0 or merged_abs > 0.001 or merged_psnr < 60.0:
|
if full_abs > 0.001 or full_psnr < 60.0 or merged_abs > 0.001 or merged_psnr < 60.0:
|
||||||
raise RuntimeError(f"K {args.kernel_name} numerical mismatch against pwin_model.py")
|
raise RuntimeError(f"K {args.kernel_name} numerical mismatch against pwin_model.py")
|
||||||
print(f"PASS K_REFERENCE reference_layout=gfx12 kernel={args.kernel_name} "
|
print(f"PASS K_REFERENCE reference=logical kernel={args.kernel_name} "
|
||||||
"nonzero_weights=1 transformer_executed=1 nan_inf=0")
|
"nonzero_weights=1 transformer_executed=1 nan_inf=0")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ def validate(layer, directory, output, window_count=1, real_capture=False):
|
|||||||
if maximum > absolute_limit or psnr < 60:
|
if maximum > absolute_limit or psnr < 60:
|
||||||
worst = int(difference.argmax())
|
worst = int(difference.argmax())
|
||||||
raise RuntimeError(f'K mismatch at {worst}: reference={expected[worst]}, gpu={actual[worst]}')
|
raise RuntimeError(f'K mismatch at {worst}: reference={expected[worst]}, gpu={actual[worst]}')
|
||||||
print(f'PASS K_REPLAY_REFERENCE kernel={layer} reference_layout=gfx12 nan_inf=0')
|
print(f'PASS K_REPLAY_REFERENCE kernel={layer} reference=logical nan_inf=0')
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ def validate(layer, directory, output, block_count, real_capture, exact=False):
|
|||||||
maximum, peak, psnr, steps = metrics(expected, actual, f'M_REPLAY_REFERENCE kernel={layer}')
|
maximum, peak, psnr, steps = metrics(expected, actual, f'M_REPLAY_REFERENCE kernel={layer}')
|
||||||
if ((exact or not real_capture) and maximum != 0) or (real_capture and (steps.max() > 1 or psnr < 50)):
|
if ((exact or not real_capture) and maximum != 0) or (real_capture and (steps.max() > 1 or psnr < 50)):
|
||||||
raise RuntimeError(f'M mismatch: exact synthetic / <=1 FP8 step and >=50 dB real gate; peak={peak}')
|
raise RuntimeError(f'M mismatch: exact synthetic / <=1 FP8 step and >=50 dB real gate; peak={peak}')
|
||||||
print(f'PASS M_REPLAY_REFERENCE kernel={layer} blocks={len(pairs)} reference_layout=gfx12 nan_inf=0')
|
print(f'PASS M_REPLAY_REFERENCE kernel={layer} blocks={len(pairs)} reference=logical nan_inf=0')
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
@@ -94,9 +94,9 @@ struct Runtime {
|
|||||||
if (!d3d) throw std::runtime_error("Null D3D12 device");
|
if (!d3d) throw std::runtime_error("Null D3D12 device");
|
||||||
try {
|
try {
|
||||||
hipDeviceProp_t props{};
|
hipDeviceProp_t props{};
|
||||||
hip.select_architecture(-1, props);
|
|
||||||
hip.verbose = cuda.verbose = !std::getenv("D4R_QUIET_API");
|
|
||||||
const auto luid = adapter_luid(d3d);
|
const auto luid = adapter_luid(d3d);
|
||||||
|
hip.select_architecture(-1, props, &luid);
|
||||||
|
hip.verbose = cuda.verbose = !std::getenv("D4R_QUIET_API");
|
||||||
if (std::memcmp(&luid, props.luid, sizeof(luid))) throw std::runtime_error("D3D12/HIP LUID mismatch");
|
if (std::memcmp(&luid, props.luid, sizeof(luid))) throw std::runtime_error("D3D12/HIP LUID mismatch");
|
||||||
cuda.check(cuda.cuInit(0), "cuInit(Windows runtime)");
|
cuda.check(cuda.cuInit(0), "cuInit(Windows runtime)");
|
||||||
int count = 0; cuda.check(cuda.cuDeviceGetCount(&count), "cuDeviceGetCount");
|
int count = 0; cuda.check(cuda.cuDeviceGetCount(&count), "cuDeviceGetCount");
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ extern "C" __attribute__((global)) void d4r_wmma_gfx1201(
|
|||||||
const unsigned int group = lane >> 4;
|
const unsigned int group = lane >> 4;
|
||||||
const _Float16* a = reinterpret_cast<const _Float16*>(a_bits);
|
const _Float16* a = reinterpret_cast<const _Float16*>(a_bits);
|
||||||
const _Float16* b = reinterpret_cast<const _Float16*>(b_bits);
|
const _Float16* b = reinterpret_cast<const _Float16*>(b_bits);
|
||||||
|
#if defined(__GFX12__)
|
||||||
h8 a_frag, b_frag;
|
h8 a_frag, b_frag;
|
||||||
f8 c_frag;
|
f8 c_frag;
|
||||||
for (unsigned int i = 0; i < 8u; ++i) {
|
for (unsigned int i = 0; i < 8u; ++i) {
|
||||||
@@ -39,6 +40,23 @@ extern "C" __attribute__((global)) void d4r_wmma_gfx1201(
|
|||||||
b_frag, a_frag, result);
|
b_frag, a_frag, result);
|
||||||
for (unsigned int i = 0; i < 8u; ++i)
|
for (unsigned int i = 0; i < 8u; ++i)
|
||||||
output[row * 16u + group * 8u + i] = result[i];
|
output[row * 16u + group * 8u + i] = result[i];
|
||||||
|
#else
|
||||||
|
// Adapted from realdody/d4r ae530b0: real gfx11 operands/accumulators,
|
||||||
|
// independent of the shared layout abstraction.
|
||||||
|
d4r_wmma_h16 a_frag, b_frag;
|
||||||
|
d4r_wmma_f8 c_frag;
|
||||||
|
for (unsigned int i = 0; i < 16u; ++i) {
|
||||||
|
a_frag[i] = a[row * 16u + i];
|
||||||
|
b_frag[i] = b[row * 16u + i];
|
||||||
|
}
|
||||||
|
for (unsigned int i = 0; i < 8u; ++i)
|
||||||
|
c_frag[i] = initial_c[(2u * i + group) * 16u + row];
|
||||||
|
d4r_wmma_f8 result = __builtin_amdgcn_wmma_f32_16x16x16_f16_w32(a_frag, b_frag, c_frag);
|
||||||
|
if (steps == 2u)
|
||||||
|
result = __builtin_amdgcn_wmma_f32_16x16x16_f16_w32(a_frag, b_frag, result);
|
||||||
|
for (unsigned int i = 0; i < 8u; ++i)
|
||||||
|
output[(2u * i + group) * 16u + row] = result[i];
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// d4r's original gfx11 fragment contract, exercised independently of K/M.
|
// d4r's original gfx11 fragment contract, exercised independently of K/M.
|
||||||
|
|||||||
Reference in new issue
Block a user