Build native Windows packages for both RDNA4 targets

Add explicit gfx1200/gfx1201 builds, runtime selection and per-target
code objects. Guard staging, packaging and installation against mixed
architectures; retain gfx1201 compatibility and strict K/M arithmetic.

Adapt realdody's target configuration and MSVC binary16/BOOL portability
fixes from ae530b0. Do not import its forced gfx12 layout on RDNA3.
Add exhaustive binary16 and C++/PowerShell target contract regressions.

Validation: 20 CTest gates on RX 9070 XT; four software-only gfx1200 gates;
MSVC portability compile checks; exact 4K K async and M control outputs;
isolated package install/restore and mixed-target rejection tests.
No physical gfx1200 validation is claimed.

Co-authored-by: realdody <[email protected]>
This commit is contained in:
xdfnx-devandrealdody committed 2026-10-02 16:18:18 +03:00
1 parent 8f7058d2ba
commit 98de8e3a3e
51 files changed
+636 -127

No files matched your search

+51 -16
View File
@@ -13,25 +13,36 @@ if(NOT EXISTS "${D4R_HIP_ROOT}/include/hip/hip_runtime_api.h")
message(FATAL_ERROR "Set D4R_HIP_ROOT to a Windows HIP SDK (headers and bin/clang++.exe required)") message(FATAL_ERROR "Set D4R_HIP_ROOT to a Windows HIP SDK (headers and bin/clang++.exe required)")
endif() 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)
set(probe_object "${CMAKE_CURRENT_BINARY_DIR}/probe_gfx1201.hsaco") # Architecture parameterization adapted from realdody/d4r ae530b0.
# Keep explicit subtargets: no gfx11 substitution or untested future gfx12 ISA.
set(D4R_GPU_ARCH "gfx1201" CACHE STRING "Native Windows package GPU target")
set_property(CACHE D4R_GPU_ARCH PROPERTY STRINGS gfx1201 gfx1200)
set(d4r_supported_targets gfx1200 gfx1201)
if(NOT D4R_GPU_ARCH IN_LIST d4r_supported_targets)
message(FATAL_ERROR "D4R_GPU_ARCH must be gfx1200 or gfx1201")
endif()
add_compile_definitions(D4R_TARGET_ARCH="${D4R_GPU_ARCH}")
configure_file(tools/windows/gpu-target.json.in gpu-target.json @ONLY)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/gpu-target.json" DESTINATION .)
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=gfx1201 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/probe_kernel.hip" -nogpuinc -nogpulib -O2 "${CMAKE_CURRENT_SOURCE_DIR}/tools/windows/probe_kernel.hip"
-o "${probe_object}" -o "${probe_object}"
DEPENDS tools/windows/probe_kernel.hip VERBATIM) DEPENDS tools/windows/probe_kernel.hip VERBATIM)
add_custom_target(d4r_probe_code_object ALL DEPENDS "${probe_object}") add_custom_target(d4r_probe_code_object ALL DEPENDS "${probe_object}")
set(pixel_object "${CMAKE_CURRENT_BINARY_DIR}/pixel_convert_gfx1201.hsaco") set(pixel_object "${CMAKE_CURRENT_BINARY_DIR}/pixel_convert_${D4R_GPU_ARCH}.hsaco")
add_custom_command(OUTPUT "${pixel_object}" add_custom_command(OUTPUT "${pixel_object}"
COMMAND "${D4R_HIP_CLANG}" -x hip -std=c++17 --offload-arch=gfx1201 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 -O2 "${CMAKE_CURRENT_SOURCE_DIR}/tools/windows/pixel_convert_gfx1201.hip" -nogpuinc -nogpulib -O2 "${CMAKE_CURRENT_SOURCE_DIR}/tools/windows/pixel_convert_gfx1201.hip"
-o "${pixel_object}" -o "${pixel_object}"
DEPENDS tools/windows/pixel_convert_gfx1201.hip tools/windows/pixel_format.h kernels/common/hip_device_minimal.h VERBATIM) DEPENDS tools/windows/pixel_convert_gfx1201.hip tools/windows/pixel_format.h kernels/common/hip_device_minimal.h VERBATIM)
add_custom_target(d4r_pixel_code_object ALL DEPENDS "${pixel_object}") add_custom_target(d4r_pixel_code_object ALL DEPENDS "${pixel_object}")
set(wmma_object "${CMAKE_CURRENT_BINARY_DIR}/wmma_gfx1201.hsaco") 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=gfx1201 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 "${CMAKE_CURRENT_SOURCE_DIR}/tools/windows/wmma_gfx1201.hip"
-o "${wmma_object}" -o "${wmma_object}"
@@ -49,7 +60,7 @@ foreach(family k m)
file(GLOB native_headers CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/kernels/${family}/*.h") file(GLOB native_headers CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/kernels/${family}/*.h")
foreach(source IN LISTS native_sources) foreach(source IN LISTS native_sources)
get_filename_component(kernel_name "${source}" NAME_WE) get_filename_component(kernel_name "${source}" NAME_WE)
set(native_object "${CMAKE_CURRENT_BINARY_DIR}/${kernel_name}_gfx1201.hsaco") set(native_object "${CMAKE_CURRENT_BINARY_DIR}/${kernel_name}_${D4R_GPU_ARCH}.hsaco")
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${source}") set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${source}")
file(READ "${source}" kernel_source) file(READ "${source}" kernel_source)
string(REGEX MATCH "// d4r-build-flags: ([^\r\n]+)" flags_line "${kernel_source}") string(REGEX MATCH "// d4r-build-flags: ([^\r\n]+)" flags_line "${kernel_source}")
@@ -65,7 +76,7 @@ foreach(family k m)
list(APPEND native_flags ${source_flags}) list(APPEND native_flags ${source_flags})
endif() endif()
add_custom_command(OUTPUT "${native_object}" add_custom_command(OUTPUT "${native_object}"
COMMAND "${D4R_HIP_CLANG}" -x hip -std=c++17 --offload-arch=gfx1201 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 ${native_flags}
"${source}" -o "${native_object}" "${source}" -o "${native_object}"
@@ -75,7 +86,9 @@ foreach(family k m)
install(FILES "${native_object}" DESTINATION "experimental/${family}") install(FILES "${native_object}" DESTINATION "experimental/${family}")
endforeach() endforeach()
endforeach() endforeach()
add_custom_target(d4r_native_gfx1201_compile ALL DEPENDS ${native_objects}) add_custom_target(d4r_native_compile ALL DEPENDS ${native_objects})
# Retain the old manual build target for existing scripts.
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 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__)
@@ -92,6 +105,16 @@ foreach(probe hip_gfx1201_probe gfx12_wmma_probe k_module_probe native_replay_pr
endif() endif()
install(TARGETS d4r_${probe} RUNTIME DESTINATION bin) install(TARGETS d4r_${probe} RUNTIME DESTINATION bin)
endforeach() endforeach()
foreach(probe binary16_probe gpu_target_probe)
add_executable(d4r_${probe} tools/windows/${probe}.cpp)
if(MINGW)
target_link_options(d4r_${probe} PRIVATE -static)
elseif(MSVC)
set_property(TARGET d4r_${probe} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
endif()
install(TARGETS d4r_${probe} RUNTIME DESTINATION bin)
endforeach()
add_dependencies(d4r_gpu_target_probe d4r_probe_code_object d4r_pixel_code_object)
set(D4R_MINHOOK_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/external/MinHook" CACHE PATH "MinHook 1.3.4 source checkout") set(D4R_MINHOOK_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/external/MinHook" CACHE PATH "MinHook 1.3.4 source checkout")
if(NOT EXISTS "${D4R_MINHOOK_ROOT}/include/MinHook.h") if(NOT EXISTS "${D4R_MINHOOK_ROOT}/include/MinHook.h")
message(FATAL_ERROR "Clone MinHook v1.3.4 into external/MinHook or set D4R_MINHOOK_ROOT") message(FATAL_ERROR "Clone MinHook v1.3.4 into external/MinHook or set D4R_MINHOOK_ROOT")
@@ -171,11 +194,13 @@ if(EXISTS "${D4R_AGILITY_ROOT}/build/native/bin/x64/d3d12SDKLayers.dll")
endif() endif()
add_dependencies(d4r_hip_gfx1201_probe d4r_probe_code_object) add_dependencies(d4r_hip_gfx1201_probe d4r_probe_code_object)
add_dependencies(d4r_gfx12_wmma_probe d4r_wmma_code_object) add_dependencies(d4r_gfx12_wmma_probe d4r_wmma_code_object)
add_dependencies(d4r_k_module_probe d4r_native_gfx1201_compile) add_dependencies(d4r_k_module_probe d4r_native_compile)
install(FILES "${probe_object}" DESTINATION bin) install(FILES "${probe_object}" DESTINATION bin)
install(FILES "${pixel_object}" DESTINATION bin) 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/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 .)
install(FILES scripts/windows/test-native-overrides.ps1 DESTINATION .) install(FILES scripts/windows/test-native-overrides.ps1 DESTINATION .)
@@ -192,13 +217,23 @@ install(FILES kernels/tools/pwin_model.py kernels/tools/pwin_check.py kernels/to
kernels/tools/extract_dlss_ptx.py kernels/tools/kernel_manifest.py DESTINATION reference) kernels/tools/extract_dlss_ptx.py kernels/tools/kernel_manifest.py DESTINATION reference)
install(FILES kernels/tools/model_enc3.py kernels/tools/swin_model.py kernels/tools/swin_check.py DESTINATION reference) install(FILES kernels/tools/model_enc3.py kernels/tools/swin_model.py kernels/tools/swin_check.py DESTINATION reference)
install(FILES docs/windows-rdna4-port.md DESTINATION docs) install(FILES docs/windows-rdna4-port.md DESTINATION docs)
install(FILES docs/windows-gpu-support.md DESTINATION docs)
include(CTest) include(CTest)
add_test(NAME binary16_rounding COMMAND d4r_binary16_probe)
set_tests_properties(binary16_rounding PROPERTIES TIMEOUT 30 LABELS "software;numerics")
add_test(NAME gpu_target_contract COMMAND d4r_gpu_target_probe "${probe_object}" "${pixel_object}")
set_tests_properties(gpu_target_contract PROPERTIES TIMEOUT 30 LABELS "software;architecture")
find_program(D4R_POWERSHELL NAMES pwsh.exe powershell.exe REQUIRED)
add_test(NAME gpu_target_script_contract COMMAND "${D4R_POWERSHELL}" -NoProfile -File
"${CMAKE_CURRENT_SOURCE_DIR}/scripts/windows/test-gpu-target-contract.ps1"
-PackageRoot "${CMAKE_CURRENT_BINARY_DIR}" -CodeObject "${probe_object}")
set_tests_properties(gpu_target_script_contract PROPERTIES TIMEOUT 30 LABELS "software;architecture")
add_test(NAME d3d12_gpu_pixel_formats COMMAND d4r_d3d12_pixel_probe add_test(NAME d3d12_gpu_pixel_formats COMMAND d4r_d3d12_pixel_probe
--hip-root "${D4R_HIP_ROOT}" --module "${pixel_object}" --iterations 2) --hip-root "${D4R_HIP_ROOT}" --module "${pixel_object}" --iterations 2)
set_tests_properties(d3d12_gpu_pixel_formats PROPERTIES TIMEOUT 120 LABELS "hardware;gfx1201;formats") set_tests_properties(d3d12_gpu_pixel_formats PROPERTIES TIMEOUT 120 LABELS "hardware;${D4R_GPU_ARCH};formats")
add_test(NAME d3d12_gpu_enhanced_formats COMMAND d4r_d3d12_pixel_probe add_test(NAME d3d12_gpu_enhanced_formats COMMAND d4r_d3d12_pixel_probe
--hip-root "${D4R_HIP_ROOT}" --module "${pixel_object}" --interop-mode enhanced --iterations 2) --hip-root "${D4R_HIP_ROOT}" --module "${pixel_object}" --interop-mode enhanced --iterations 2)
set_tests_properties(d3d12_gpu_enhanced_formats PROPERTIES TIMEOUT 120 LABELS "hardware;gfx1201;formats;enhanced_barriers") set_tests_properties(d3d12_gpu_enhanced_formats PROPERTIES TIMEOUT 120 LABELS "hardware;${D4R_GPU_ARCH};formats;enhanced_barriers")
add_test(NAME d3d12_command_backend COMMAND d4r_d3d12_command_probe add_test(NAME d3d12_command_backend COMMAND d4r_d3d12_command_probe
--hip-root "${D4R_HIP_ROOT}" --module "$<TARGET_FILE:d4r_nvngx_windows>" --interop-mode indirect --iterations 32) --hip-root "${D4R_HIP_ROOT}" --module "$<TARGET_FILE:d4r_nvngx_windows>" --interop-mode indirect --iterations 32)
set_tests_properties(d3d12_command_backend PROPERTIES TIMEOUT 120 LABELS "hardware;d3d12;command_lists;lifetime") set_tests_properties(d3d12_command_backend PROPERTIES TIMEOUT 120 LABELS "hardware;d3d12;command_lists;lifetime")
@@ -211,16 +246,16 @@ set_tests_properties(d3d12_command_root_reset_warp PROPERTIES TIMEOUT 120 LABELS
ENVIRONMENT "D4R_COMMAND_PROBE_WARP=1;D4R_COMMAND_PROBE_NO_HIP=1") ENVIRONMENT "D4R_COMMAND_PROBE_WARP=1;D4R_COMMAND_PROBE_NO_HIP=1")
add_test(NAME hip_gfx1201 COMMAND d4r_hip_gfx1201_probe add_test(NAME hip_gfx1201 COMMAND d4r_hip_gfx1201_probe
--hip-root "${D4R_HIP_ROOT}" --module "${probe_object}") --hip-root "${D4R_HIP_ROOT}" --module "${probe_object}")
set_tests_properties(hip_gfx1201 PROPERTIES TIMEOUT 90 LABELS "hardware;gfx1201") set_tests_properties(hip_gfx1201 PROPERTIES TIMEOUT 90 LABELS "hardware;${D4R_GPU_ARCH}")
add_test(NAME gfx12_wmma COMMAND d4r_gfx12_wmma_probe add_test(NAME gfx12_wmma COMMAND d4r_gfx12_wmma_probe
--hip-root "${D4R_HIP_ROOT}" --module "${wmma_object}" --iterations 16) --hip-root "${D4R_HIP_ROOT}" --module "${wmma_object}" --iterations 16)
set_tests_properties(gfx12_wmma PROPERTIES TIMEOUT 90 LABELS "hardware;gfx1201;wmma") set_tests_properties(gfx12_wmma PROPERTIES TIMEOUT 90 LABELS "hardware;${D4R_GPU_ARCH};wmma")
foreach(layer enc1 enc2) foreach(layer enc1 enc2)
add_test(NAME k_${layer}_execution COMMAND d4r_k_module_probe add_test(NAME k_${layer}_execution COMMAND d4r_k_module_probe
--hip-root "${D4R_HIP_ROOT}" --hip-root "${D4R_HIP_ROOT}"
--module "${CMAKE_CURRENT_BINARY_DIR}/dltss_pwin_${layer}_layer_gfx1201.hsaco" --module "${CMAKE_CURRENT_BINARY_DIR}/dltss_pwin_${layer}_layer_${D4R_GPU_ARCH}.hsaco"
--kernel-name ${layer}) --kernel-name ${layer})
set_tests_properties(k_${layer}_execution PROPERTIES TIMEOUT 90 LABELS "hardware;gfx1201;k_execution") set_tests_properties(k_${layer}_execution PROPERTIES TIMEOUT 90 LABELS "hardware;${D4R_GPU_ARCH};k_execution")
endforeach() endforeach()
add_test(NAME d3d12_hip_interop COMMAND d4r_d3d12_hip_interop_probe add_test(NAME d3d12_hip_interop COMMAND d4r_d3d12_hip_interop_probe
--hip-root "${D4R_HIP_ROOT}" --module "${probe_object}" --iterations 32) --hip-root "${D4R_HIP_ROOT}" --module "${probe_object}" --iterations 32)
+8
View File
@@ -8,6 +8,14 @@ The user reports 49-51 FPS for K in the measured scene after the command-hook
fix and locally built output-store optimization. This is a local fix and locally built output-store optimization. This is a local
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
**compile-tested only**; no physical gfx1200 validation has been performed.
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
code objects must agree. Installation/runtime reject mixed targets. See
[windows-gpu-support.md](windows-gpu-support.md) for separate-target build
commands, the fork review and the first hardware diagnostic gate.
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:
+130
View File
@@ -0,0 +1,130 @@
# Windows GPU targets
The native Windows build accepts **gfx1200** and **gfx1201**. It builds a
separate shim, diagnostics and code objects for each target. The default stays
gfx1201. GPU selection uses HIP's real `gcnArchName`, followed by D3D12/HIP
adapter LUID matching; it does not depend on a marketing name or overridden
DXGI vendor ID.
| Target | Examples in LLVM's processor table | This project's validation |
| --- | --- | --- |
| gfx1201 | RX 9070, RX 9070 XT | RX 9070 XT: hardware, K/M and game tests. Other cards untested. |
| gfx1200 | RX 9060, RX 9060 XT | Host/device compilation and software tests only. No physical gfx1200 available. |
Sources: [LLVM AMDGPU 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).
AMD's matrix is dependency information, not evidence that d4r's K/M or external
memory path works on an untested card. Other RDNA4 SKUs are eligible only when
HIP reports one of these exact targets and exposes the required Windows APIs.
Device-specific drivers, performance and memory capacity still need testing.
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
host target and each ELF code-object target must agree. Runtime selection
rejects another architecture before launching kernels. Staging, packaging and
installation inspect the documented AMDGPU ELF machine ID and reject mixed
objects. They never rewrite a binary target or set `HSA_OVERRIDE_GFX_VERSION`.
Legacy packages without target metadata remain gfx1201 only.
## Build and package
Prepare the pinned dependencies as described in `windows-rdna4-port.md`.
Select a target explicitly; this example creates the experimental gfx1200
package. Use gfx1201 for a 9070/9070 XT. Keep separate output directories when
building both targets.
```powershell
$arch = 'gfx1200'
$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\stage-native-k.ps1 -DlssDll "$PWD\nvngx_dlss.dll" -PackageRoot $diag
.\scripts\windows\stage-native-m.ps1 -DlssDll "$PWD\nvngx_dlss.dll" -PackageRoot $diag
.\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
the strict K FP16 and M FP16-equivalent baseline; native FP8 stays disabled.
The architecture does not change arithmetic or the existing WMMA layout.
Private NVIDIA-derived texture overrides remain optional local experiments;
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
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
.\scripts\windows\test-windows-rdna4.ps1 -RuntimeProfile therock -PackageRoot "$PWD\dist\windows-gfx1200-diagnostics" -ZludaRoot "$PWD\dist\zluda-windows-final"
```
Success requires exit 0, all selected tests passed in `summary.json`, the
correct actual GPU/target in stdout, exact HIP/PTX/WMMA/pixel-format checks and
stable interop lifetime. On failure, retain the single printed diagnostic ZIP;
it includes stdout/stderr, exit code, runtime/driver inventory and DLL identity.
No NVIDIA DLL is required for this first gate. Full K/M reference, temporal,
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
--output-on-failure`. These CPU/WARP checks do not execute gfx1200 kernels.
## Fork review
Reviewed [realdody's windows-rdna3 branch](https://github.com/realdody/d4r/tree/windows-rdna3)
at `ae530b0f53ed5c0bb87558dd7c20f619e014e4fd`, on 2026-10-02. Adapted:
- Per-target build configuration and actual-target diagnostics, narrowed here
to the two documented RDNA4 subtargets, with package/ELF guards added.
- MSVC binary16 conversion in the synthetic CUDA MMA reference. An exhaustive
CPU test covers 63,490 finite/infinity encodings and 31,743 rounding
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
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
- Both targets: complete MinGW host build and 19 device code objects using
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
`test-results/rdna4-target-objects.json`; they contain no public NVIDIA DLLs.
+14 -2
View File
@@ -1,6 +1,7 @@
# Windows / RDNA4 port # Windows / RDNA4 port
Branch: `windows-rdna4`. Target: Windows 11 x64, RX 9070 XT, **gfx1201**. Branch: `windows-rdna4`. Native Windows build targets: **gfx1200 / 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)
is merged into `countervolts/d4r:windows` at `c522101`. is merged into `countervolts/d4r:windows` at `c522101`.
@@ -17,6 +18,16 @@ 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
builds and guarded packages. Both compile; gfx1201 passes 20 CTest gates on
RX 9070 XT, and gfx1200 passes four software-only gates. No physical gfx1200
test is available. K's new host build passes twelve finite 4K burst/recreation
frames with all six async RGB images exact. M's four new-build 4K RGB images
exactly match the previous build. The fork audit, adopted MSVC fixes,
per-target commands, validation limits and first hardware gate are maintained
in [windows-gpu-support.md](windows-gpu-support.md). RDNA3 runtime/layout changes
from the reviewed fork are not imported. 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
reproducible archive do not close this gate. Prioritize measured K kernel cost reproducible archive do not close this gate. Prioritize measured K kernel cost
@@ -1496,7 +1507,8 @@ automatically on CUDA failure when `trace/nvcuda.dll` is available. The trace
DLL forwards to the real DLL through `ZLUDA_CUDA_LIB`; explicit loading no DLL forwards to the real DLL through `ZLUDA_CUDA_LIB`; explicit loading no
longer bypasses the trace by accidentally passing the real DLL to the launcher. longer bypasses the trace by accidentally passing the real DLL to the launcher.
The HIP module compiler uses the selected SDK, fixed `--offload-arch=gfx1201`, The HIP module compiler uses the selected SDK, `--offload-arch=${D4R_GPU_ARCH}`
(gfx1201 by default, optionally gfx1200),
wave32 and no host/device library dependency. Host code uses the installed HIP wave32 and no host/device library dependency. Host code uses the installed HIP
header ABI and loads that SDK's `amdhip64_7.dll` by absolute path. CUDA loads the header ABI and loads that SDK's `amdhip64_7.dll` by absolute path. CUDA loads the
provided ZLUDA DLL by absolute path, matches the adapter against HIP PCI identity, provided ZLUDA DLL by absolute path, matches the adapter against HIP PCI identity,
+3 -2
View File
@@ -5,12 +5,13 @@ 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]$OutputDirectory [string]$OutputDirectory
) )
$ErrorActionPreference='Stop' $ErrorActionPreference='Stop'
$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-gfx1201' } if (!$OutputDirectory) { $OutputDirectory=Join-Path $repo "build/private-textures-$GpuArch" }
& python (Join-Path $repo 'tools/windows/build_native_texture.py') --dlss-dll $DlssDll --hip-root $HipRoot ` & python (Join-Path $repo 'tools/windows/build_native_texture.py') --dlss-dll $DlssDll --hip-root $HipRoot `
--zluda-root $ZludaRoot --kernel $Kernel --output-directory $OutputDirectory --shader-mode $ShaderMode --zluda-root $ZludaRoot --kernel $Kernel --output-directory $OutputDirectory --shader-mode $ShaderMode --gpu-arch $GpuArch
if ($LASTEXITCODE) { throw "Native texture build failed ($LASTEXITCODE); inspect the output work directory." } if ($LASTEXITCODE) { throw "Native texture build failed ($LASTEXITCODE); inspect the output work directory." }
+6 -1
View File
@@ -2,6 +2,7 @@
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]$ZludaRoot, [string]$ZludaRoot,
[string]$ToolchainRoot, [string]$ToolchainRoot,
[string]$BuildDirectory, [string]$BuildDirectory,
@@ -17,6 +18,10 @@ if ($RuntimeProfile -eq 'therock') {
if (!$HipRoot) { $HipRoot = 'C:\Program Files\AMD\ROCm\7.2' } if (!$HipRoot) { $HipRoot = 'C:\Program Files\AMD\ROCm\7.2' }
if (!$BuildDirectory) { $BuildDirectory = Join-Path $repo 'build/windows-rdna4' } if (!$BuildDirectory) { $BuildDirectory = Join-Path $repo 'build/windows-rdna4' }
if (!$InstallDirectory) { $InstallDirectory = Join-Path $repo 'dist/windows-rdna4-diagnostics' } if (!$InstallDirectory) { $InstallDirectory = Join-Path $repo 'dist/windows-rdna4-diagnostics' }
if ($GpuArch -ne 'gfx1201') {
if (!$PSBoundParameters.ContainsKey('BuildDirectory')) { $BuildDirectory += "-$GpuArch" }
if (!$PSBoundParameters.ContainsKey('InstallDirectory')) { $InstallDirectory += "-$GpuArch" }
}
$HipRoot = [IO.Path]::GetFullPath($HipRoot).TrimEnd('\', '/') $HipRoot = [IO.Path]::GetFullPath($HipRoot).TrimEnd('\', '/')
$BuildDirectory = [IO.Path]::GetFullPath($BuildDirectory).TrimEnd('\', '/') $BuildDirectory = [IO.Path]::GetFullPath($BuildDirectory).TrimEnd('\', '/')
$InstallDirectory = [IO.Path]::GetFullPath($InstallDirectory).TrimEnd('\', '/') $InstallDirectory = [IO.Path]::GetFullPath($InstallDirectory).TrimEnd('\', '/')
@@ -47,7 +52,7 @@ if ($minhookCommit -ne 'c3fcafdc10146beb5919319d0683e44e3c30d537') {
$originalPath = $env:PATH $originalPath = $env:PATH
try { try {
$configure = @('--fresh', '-S', $repo, '-B', $BuildDirectory, '-G', 'Ninja', '-DCMAKE_BUILD_TYPE=RelWithDebInfo', $configure = @('--fresh', '-S', $repo, '-B', $BuildDirectory, '-G', 'Ninja', '-DCMAKE_BUILD_TYPE=RelWithDebInfo',
"-DCMAKE_MAKE_PROGRAM=$ninja", "-DD4R_HIP_ROOT=$HipRoot", "-DCMAKE_INSTALL_PREFIX=$InstallDirectory") "-DCMAKE_MAKE_PROGRAM=$ninja", "-DD4R_HIP_ROOT=$HipRoot", "-DD4R_GPU_ARCH=$GpuArch", "-DCMAKE_INSTALL_PREFIX=$InstallDirectory")
if ($ToolchainRoot) { if ($ToolchainRoot) {
$compiler = Join-Path $ToolchainRoot 'bin/x86_64-w64-mingw32-clang++.exe' $compiler = Join-Path $ToolchainRoot 'bin/x86_64-w64-mingw32-clang++.exe'
if (!(Test-Path $compiler)) { throw "Compiler missing: $compiler" } if (!(Test-Path $compiler)) { throw "Compiler missing: $compiler" }
+26
View File
@@ -0,0 +1,26 @@
# Shared by the build, diagnostics, staging and game package scripts.
function Get-D4RGpuTarget([string]$Root, [string]$Requested) {
$configured=$null
$targetFile=Join-Path $Root 'gpu-target.json'
if (Test-Path -LiteralPath $targetFile) {
$configured=(Get-Content -LiteralPath $targetFile -Raw | ConvertFrom-Json).architecture
if ($configured -notin @('gfx1200','gfx1201')) { throw "Unsupported package GPU target: $configured" }
}
$target=if ($Requested) { $Requested } elseif ($configured) { $configured } else { 'gfx1201' }
if ($target -notin @('gfx1200','gfx1201')) { throw "Unsupported GPU target: $target" }
if (!$configured -and $target -ne 'gfx1201') { throw 'A gfx1200 build requires gpu-target.json; rebuild with -GpuArch gfx1200.' }
if ($configured -and $target -ne $configured) { throw "Requested $target differs from package target $configured" }
return $target
}
function Assert-D4RCodeObjectTarget([string]$Path, [string]$Target) {
if ($Target -notin @('gfx1200','gfx1201')) { throw "Unsupported GPU target: $Target" }
$reader=[IO.BinaryReader]::new([IO.File]::OpenRead($Path))
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
$header[4] -ne 2 -or $header[5] -ne 1 -or $header[18] -ne 224 -or $header[19] -ne 0) {
throw "Invalid AMDGPU ELF64 code object: $Path"
}
# LLVM AMDGPU e_flags machine IDs; inspect, never patch or spoof them.
$expected=if ($Target -eq 'gfx1200') { 0x48 } else { 0x4e }
if ($header[48] -ne $expected) { throw "Code object does not target ${Target}: $Path (ELF machine=$($header[48]))" }
}
+32 -5
View File
@@ -2,18 +2,32 @@
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]$ArchivePath [string]$ArchivePath
) )
$ErrorActionPreference = 'Stop' $ErrorActionPreference = 'Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..')) $repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
$defaults = @{PackageRoot='dist/windows-rdna4-game'; DiagnosticRoot='dist/windows-rdna4-command-list'; $defaults = @{PackageRoot='dist/windows-rdna4-game'; DiagnosticRoot='dist/windows-rdna4-command-list';
OptiScalerRoot='dist/optiscaler-windows-d4r'; ZludaRoot='dist/zluda-windows-final'; OptiScalerRoot='dist/optiscaler-windows-d4r'; ZludaRoot='dist/zluda-windows-final';
HipRoot='.tools/therock-10.2.0a20260929/_rocm_sdk_core'; HipRoot='.tools/therock-10.2.0a20260929/_rocm_sdk_core'}
KernelKRoot='build/native-k-gfx1201'; KernelMRoot='build/native-m-gfx1201'}
foreach ($name in $defaults.Keys) { 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
if ($GpuArch -eq 'gfx1200' -and !$PSBoundParameters.ContainsKey('PackageRoot')) { $PackageRoot += '-gfx1200' }
if (!$KernelKRoot) { $KernelKRoot=Join-Path $repo "build/native-k-$GpuArch" }
if (!$KernelMRoot) { $KernelMRoot=Join-Path $repo "build/native-m-$GpuArch" }
foreach ($directory in @($KernelKRoot,$KernelMRoot)) {
$info=Join-Path $directory 'build-info.json'
if ((Test-Path -LiteralPath $info) -and (Get-Content -LiteralPath $info -Raw | ConvertFrom-Json).architecture -ne $GpuArch) {
throw "Native kernel directory does not target ${GpuArch}: $directory"
}
}
$PackageRoot = [IO.Path]::GetFullPath($PackageRoot) $PackageRoot = [IO.Path]::GetFullPath($PackageRoot)
if (Test-Path -LiteralPath (Join-Path $PackageRoot 'gpu-target.json')) {
[void](Get-D4RGpuTarget $PackageRoot $GpuArch)
}
$sourceCommit=(& git -C $repo rev-parse HEAD).Trim() $sourceCommit=(& git -C $repo rev-parse HEAD).Trim()
$sourceDirty=[bool](& git -C $repo status --porcelain) $sourceDirty=[bool](& git -C $repo status --porcelain)
if ($ArchivePath -and $sourceDirty) { throw 'Commit source changes before creating the distributable archive.' } if ($ArchivePath -and $sourceDirty) { throw 'Commit source changes before creating the distributable archive.' }
@@ -21,6 +35,7 @@ New-Item -ItemType Directory -Force $PackageRoot | Out-Null
$stagedFiles = [Collections.Generic.List[string]]::new() $stagedFiles = [Collections.Generic.List[string]]::new()
function Stage([string]$source, [string]$relative) { function Stage([string]$source, [string]$relative) {
if (!(Test-Path -LiteralPath $source -PathType Leaf)) { throw "Required file missing: $source" } if (!(Test-Path -LiteralPath $source -PathType Leaf)) { throw "Required file missing: $source" }
if ($source.EndsWith('.hsaco')) { Assert-D4RCodeObjectTarget $source $GpuArch }
$destination = Join-Path $PackageRoot $relative $destination = Join-Path $PackageRoot $relative
New-Item -ItemType Directory -Force (Split-Path $destination) | Out-Null New-Item -ItemType Directory -Force (Split-Path $destination) | Out-Null
Copy-Item -LiteralPath $source -Destination $destination -Force Copy-Item -LiteralPath $source -Destination $destination -Force
@@ -28,7 +43,7 @@ function Stage([string]$source, [string]$relative) {
} }
Stage (Join-Path $OptiScalerRoot 'OptiScaler.dll') 'OptiScaler.dll' Stage (Join-Path $OptiScalerRoot 'OptiScaler.dll') 'OptiScaler.dll'
Stage (Join-Path $DiagnosticRoot 'bin/d4r_nvngx.dll') 'd4r/_nvngx.dll' Stage (Join-Path $DiagnosticRoot 'bin/d4r_nvngx.dll') 'd4r/_nvngx.dll'
Stage (Join-Path $DiagnosticRoot 'bin/pixel_convert_gfx1201.hsaco') 'd4r/pixel_convert_gfx1201.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'
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" }
@@ -46,14 +61,26 @@ foreach ($directory in @($KernelKRoot, $KernelMRoot)) {
} }
} }
if ($entries.Count -ne 16) { throw "Expected 11 K and 5 M native objects; found $($entries.Count)" } if ($entries.Count -ne 16) { throw "Expected 11 K and 5 M native objects; found $($entries.Count)" }
@('# Audited DLSS 310.9.1: K + M gfx1201 native kernels', '# Generated by package-windows-game.ps1') + @($entries.Values | Sort-Object) | @("# Audited DLSS 310.9.1: K + M $GpuArch native kernels", '# Generated by package-windows-game.ps1') + @($entries.Values | Sort-Object) |
Set-Content -LiteralPath (Join-Path $PackageRoot 'd4r/native/d4r-kernels.txt') -Encoding ASCII Set-Content -LiteralPath (Join-Path $PackageRoot 'd4r/native/d4r-kernels.txt') -Encoding ASCII
$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'
if (Test-Path -LiteralPath (Join-Path $DiagnosticRoot 'gpu-target.json')) {
Stage (Join-Path $DiagnosticRoot 'gpu-target.json') 'gpu-target.json'
} else {
# Builds predating target metadata were gfx1201 only. The resolver rejects
# any attempt to label such a build gfx1200.
@{schema=1; architecture=$GpuArch; wavefrontSize=32; validation='Legacy gfx1201 build; run the GPU diagnostics.'} |
ConvertTo-Json | Set-Content -LiteralPath (Join-Path $PackageRoot 'gpu-target.json') -Encoding UTF8
$stagedFiles.Add('gpu-target.json')
}
Stage (Join-Path $repo 'scripts/windows/capture-game-window.ps1') 'capture-game-window.ps1' Stage (Join-Path $repo 'scripts/windows/capture-game-window.ps1') 'capture-game-window.ps1'
Stage (Join-Path $repo 'scripts/windows/send-game-key.ps1') 'send-game-key.ps1' Stage (Join-Path $repo 'scripts/windows/send-game-key.ps1') 'send-game-key.ps1'
Stage (Join-Path $repo 'docs/windows-game.md') 'README.md' Stage (Join-Path $repo 'docs/windows-game.md') 'README.md'
Stage (Join-Path $repo 'docs/windows-performance.md') 'windows-performance.md' Stage (Join-Path $repo 'docs/windows-performance.md') 'windows-performance.md'
Stage (Join-Path $repo 'docs/windows-gpu-support.md') 'windows-gpu-support.md'
Stage (Join-Path $repo 'docs/windows-rdna4-port.md') 'windows-rdna4-port.md'
Stage (Join-Path $repo 'LICENSE') 'licenses/d4r.txt' Stage (Join-Path $repo 'LICENSE') 'licenses/d4r.txt'
Stage (Join-Path $OptiScalerRoot 'GPL-3.0.txt') 'licenses/OptiScaler.txt' Stage (Join-Path $OptiScalerRoot 'GPL-3.0.txt') 'licenses/OptiScaler.txt'
Stage (Join-Path $repo 'external/ZLUDA/LICENSE-MIT') 'licenses/ZLUDA-MIT.txt' Stage (Join-Path $repo 'external/ZLUDA/LICENSE-MIT') 'licenses/ZLUDA-MIT.txt'
@@ -70,7 +97,7 @@ New-Item -ItemType Directory -Force (Split-Path $sourceArchive) | Out-Null
if ($LASTEXITCODE) { throw 'Cannot archive the committed d4r source.' } if ($LASTEXITCODE) { throw 'Cannot archive the committed d4r source.' }
Stage $sourceArchive 'source/d4r-windows-rdna4-source.zip' Stage $sourceArchive 'source/d4r-windows-rdna4-source.zip'
$metadata = [ordered]@{ $metadata = [ordered]@{
architecture='gfx1201'; nativeKernels=16; dlssSha256='3975567b8943c53acce397f2b72380092f84f162d00b0d2c7d08a1025c563983'; architecture=$GpuArch; hardwareValidation=$(if ($GpuArch -eq 'gfx1201') { 'RX9070XT tested; other SKUs unverified' } else { 'compile-only; hardware unverified' }); nativeKernels=16; dlssSha256='3975567b8943c53acce397f2b72380092f84f162d00b0d2c7d08a1025c563983';
d4rCommit=$sourceCommit; d4rCommit=$sourceCommit;
d4rWorkingTreeDirty=$sourceDirty; d4rWorkingTreeDirty=$sourceDirty;
optiScaler=(Get-Content -LiteralPath (Join-Path $OptiScalerRoot 'build-info.json') -Raw | ConvertFrom-Json); optiScaler=(Get-Content -LiteralPath (Join-Path $OptiScalerRoot 'build-info.json') -Raw | ConvertFrom-Json);
+3 -1
View File
@@ -6,13 +6,15 @@ param(
[switch]$Translated [switch]$Translated
) )
$ErrorActionPreference='Stop' $ErrorActionPreference='Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
$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 (!$PackageRoot) { $PackageRoot=Join-Path $repo 'dist/windows-rdna4-command-list' } if (!$PackageRoot) { $PackageRoot=Join-Path $repo 'dist/windows-rdna4-command-list' }
$GpuArch=Get-D4RGpuTarget $PackageRoot $null
if (!$OutputDirectory) { $OutputDirectory=Join-Path $repo ('test-results/profile-' + $Preset + '-' + (Get-Date -Format 'yyyyMMdd-HHmmss-fff')) } if (!$OutputDirectory) { $OutputDirectory=Join-Path $repo ('test-results/profile-' + $Preset + '-' + (Get-Date -Format 'yyyyMMdd-HHmmss-fff')) }
$settings=@{D4R_ZLUDA_PROFILE='1'; D4R_PROFILE_STAGES='1'; D4R_VALIDATE_OUTPUT='1'; $settings=@{D4R_ZLUDA_PROFILE='1'; D4R_PROFILE_STAGES='1'; D4R_VALIDATE_OUTPUT='1';
D4R_ZLUDA_PROFILE_DEFERRED=$null; D4R_ZLUDA_PROFILE_ALLOW_LEGACY=$null; D4R_ZLUDA_PROFILE_EVERY=$null; D4R_ZLUDA_PROFILE_DEFERRED=$null; D4R_ZLUDA_PROFILE_ALLOW_LEGACY=$null; D4R_ZLUDA_PROFILE_EVERY=$null;
D4R_ZLUDA_NATIVE_DIR=$(if ($Translated) { $null } elseif ($Preset -eq 11) { Join-Path $repo 'build/native-k-gfx1201' } else { Join-Path $repo 'build/native-m-gfx1201' })} D4R_ZLUDA_NATIVE_DIR=$(if ($Translated) { $null } elseif ($Preset -eq 11) { Join-Path $repo "build/native-k-$GpuArch" } else { Join-Path $repo "build/native-m-$GpuArch" })}
$old=@{} $old=@{}
try { try {
foreach ($key in $settings.Keys) { $old[$key]=[Environment]::GetEnvironmentVariable($key,'Process'); [Environment]::SetEnvironmentVariable($key,$settings[$key],'Process') } foreach ($key in $settings.Keys) { $old[$key]=[Environment]::GetEnvironmentVariable($key,'Process'); [Environment]::SetEnvironmentVariable($key,$settings[$key],'Process') }
+11 -5
View File
@@ -1,24 +1,30 @@
[CmdletBinding()] [CmdletBinding()]
param([Parameter(Mandatory=$true)][string]$DlssDll, [string]$PackageRoot, [string]$OutputDirectory) param([Parameter(Mandatory=$true)][string]$DlssDll, [string]$PackageRoot, [string]$OutputDirectory, [ValidateSet('gfx1200','gfx1201')][string]$GpuArch)
$ErrorActionPreference = 'Stop' $ErrorActionPreference = 'Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..')) $repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$PackageRoot) { $PackageRoot = Join-Path $repo 'dist/windows-rdna4-therock' } if (!$PackageRoot) { $PackageRoot = Join-Path $repo 'dist/windows-rdna4-therock' }
if (!$OutputDirectory) { $OutputDirectory = Join-Path $repo 'build/native-k-gfx1201' } $GpuArch=Get-D4RGpuTarget $PackageRoot $GpuArch
if (!$OutputDirectory) { $OutputDirectory = Join-Path $repo "build/native-k-$GpuArch" }
if (![IO.Path]::IsPathRooted($DlssDll) -or !(Test-Path -LiteralPath $DlssDll)) { if (![IO.Path]::IsPathRooted($DlssDll) -or !(Test-Path -LiteralPath $DlssDll)) {
throw 'Supply the absolute path to your local nvngx_dlss.dll.' throw 'Supply the absolute path to your local nvngx_dlss.dll.'
} }
New-Item -ItemType Directory -Force $OutputDirectory | Out-Null New-Item -ItemType Directory -Force $OutputDirectory | Out-Null
foreach ($object in Get-ChildItem -LiteralPath $OutputDirectory -Filter '*.hsaco') {
Assert-D4RCodeObjectTarget $object.FullName $GpuArch
}
$layers = @('enc0','enc1','enc2','enc3','enc4','dec5','dec4','dec3','dec2','dec1','dec0') $layers = @('enc0','enc1','enc2','enc3','enc4','dec5','dec4','dec3','dec2','dec1','dec0')
foreach ($layer in $layers) { foreach ($layer in $layers) {
$name = "dltss_pwin_${layer}_layer" $name = "dltss_pwin_${layer}_layer"
$source = Join-Path $PackageRoot "experimental/k/${name}_gfx1201.hsaco" $source = Join-Path $PackageRoot "experimental/k/${name}_${GpuArch}.hsaco"
if (!(Test-Path -LiteralPath $source)) { throw "Native K module missing: $source" } if (!(Test-Path -LiteralPath $source)) { throw "Native K module missing: $source" }
Assert-D4RCodeObjectTarget $source $GpuArch
Copy-Item -LiteralPath $source -Destination (Join-Path $OutputDirectory "$name.hsaco") -Force Copy-Item -LiteralPath $source -Destination (Join-Path $OutputDirectory "$name.hsaco") -Force
} }
& python (Join-Path $repo 'kernels/tools/kernel_manifest.py') $OutputDirectory $DlssDll & python (Join-Path $repo 'kernels/tools/kernel_manifest.py') $OutputDirectory $DlssDll
if ($LASTEXITCODE) { throw "Native manifest generation failed ($LASTEXITCODE)" } if ($LASTEXITCODE) { throw "Native manifest generation failed ($LASTEXITCODE)" }
@{architecture='gfx1201'; family='K'; dlssSha256=(Get-FileHash -LiteralPath $DlssDll -Algorithm SHA256).Hash; @{architecture=$GpuArch; family='K'; dlssSha256=(Get-FileHash -LiteralPath $DlssDll -Algorithm SHA256).Hash;
validation='synthetic layers passed; actual DLSS capture/reference validation required'; validation='staged only; GPU execution and DLSS capture/reference validation required';
modules=@(Get-ChildItem -LiteralPath $OutputDirectory -Filter '*.hsaco' | Get-FileHash -Algorithm SHA256)} | modules=@(Get-ChildItem -LiteralPath $OutputDirectory -Filter '*.hsaco' | Get-FileHash -Algorithm SHA256)} |
ConvertTo-Json -Depth 5 | Set-Content -LiteralPath (Join-Path $OutputDirectory 'build-info.json') -Encoding UTF8 ConvertTo-Json -Depth 5 | Set-Content -LiteralPath (Join-Path $OutputDirectory 'build-info.json') -Encoding UTF8
Write-Host "Experimental native K directory: $OutputDirectory" Write-Host "Experimental native K directory: $OutputDirectory"
+11 -5
View File
@@ -1,24 +1,30 @@
[CmdletBinding()] [CmdletBinding()]
param([Parameter(Mandatory=$true)][string]$DlssDll, [string]$PackageRoot, [string]$OutputDirectory) param([Parameter(Mandatory=$true)][string]$DlssDll, [string]$PackageRoot, [string]$OutputDirectory, [ValidateSet('gfx1200','gfx1201')][string]$GpuArch)
$ErrorActionPreference = 'Stop' $ErrorActionPreference = 'Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..')) $repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$PackageRoot) { $PackageRoot = Join-Path $repo 'dist/windows-rdna4-therock' } if (!$PackageRoot) { $PackageRoot = Join-Path $repo 'dist/windows-rdna4-therock' }
if (!$OutputDirectory) { $OutputDirectory = Join-Path $repo 'build/native-m-gfx1201' } $GpuArch=Get-D4RGpuTarget $PackageRoot $GpuArch
if (!$OutputDirectory) { $OutputDirectory = Join-Path $repo "build/native-m-$GpuArch" }
if (![IO.Path]::IsPathRooted($DlssDll) -or !(Test-Path -LiteralPath $DlssDll)) { if (![IO.Path]::IsPathRooted($DlssDll) -or !(Test-Path -LiteralPath $DlssDll)) {
throw 'Supply the absolute path to your local nvngx_dlss.dll.' throw 'Supply the absolute path to your local nvngx_dlss.dll.'
} }
New-Item -ItemType Directory -Force $OutputDirectory | Out-Null New-Item -ItemType Directory -Force $OutputDirectory | Out-Null
foreach ($object in Get-ChildItem -LiteralPath $OutputDirectory -Filter '*.hsaco') {
Assert-D4RCodeObjectTarget $object.FullName $GpuArch
}
foreach ($layer in @('enc1','enc2','enc3_tube','dec2','dec1')) { foreach ($layer in @('enc1','enc2','enc3_tube','dec2','dec1')) {
$name = "rrlite_${layer}_4x4" $name = "rrlite_${layer}_4x4"
$source = Join-Path $PackageRoot "experimental/m/${name}_gfx1201.hsaco" $source = Join-Path $PackageRoot "experimental/m/${name}_${GpuArch}.hsaco"
if (!(Test-Path -LiteralPath $source)) { throw "Native M module missing: $source" } if (!(Test-Path -LiteralPath $source)) { throw "Native M module missing: $source" }
Assert-D4RCodeObjectTarget $source $GpuArch
Copy-Item -LiteralPath $source -Destination (Join-Path $OutputDirectory "$name.hsaco") -Force Copy-Item -LiteralPath $source -Destination (Join-Path $OutputDirectory "$name.hsaco") -Force
} }
& python (Join-Path $repo 'kernels/tools/kernel_manifest.py') $OutputDirectory $DlssDll & python (Join-Path $repo 'kernels/tools/kernel_manifest.py') $OutputDirectory $DlssDll
if ($LASTEXITCODE) { throw "Native manifest generation failed ($LASTEXITCODE)" } if ($LASTEXITCODE) { throw "Native manifest generation failed ($LASTEXITCODE)" }
@{architecture='gfx1201'; family='M'; numerics='SWIN_EXACT; SWIN_EXACT_PV; FP16 widening; native FP8 disabled'; @{architecture=$GpuArch; family='M'; numerics='SWIN_EXACT; SWIN_EXACT_PV; FP16 widening; native FP8 disabled';
dlssSha256=(Get-FileHash -LiteralPath $DlssDll -Algorithm SHA256).Hash; dlssSha256=(Get-FileHash -LiteralPath $DlssDll -Algorithm SHA256).Hash;
validation='synthetic layers passed; actual DLSS capture/reference validation required'; validation='staged only; GPU execution and DLSS capture/reference validation required';
modules=@(Get-ChildItem -LiteralPath $OutputDirectory -Filter '*.hsaco' | Get-FileHash -Algorithm SHA256)} | modules=@(Get-ChildItem -LiteralPath $OutputDirectory -Filter '*.hsaco' | Get-FileHash -Algorithm SHA256)} |
ConvertTo-Json -Depth 5 | Set-Content -LiteralPath (Join-Path $OutputDirectory 'build-info.json') -Encoding UTF8 ConvertTo-Json -Depth 5 | Set-Content -LiteralPath (Join-Path $OutputDirectory 'build-info.json') -Encoding UTF8
Write-Host "Experimental native M directory: $OutputDirectory" Write-Host "Experimental native M directory: $OutputDirectory"
+4 -2
View File
@@ -11,12 +11,14 @@ param(
[string]$OutputDirectory [string]$OutputDirectory
) )
$ErrorActionPreference = 'Stop' $ErrorActionPreference = 'Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..')) $repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$NgxCore) { $NgxCore = Join-Path $repo '_nvngx.dll' } if (!$NgxCore) { $NgxCore = Join-Path $repo '_nvngx.dll' }
if (!$DlssDll) { $DlssDll = Join-Path $repo 'nvngx_dlss.dll' } if (!$DlssDll) { $DlssDll = Join-Path $repo 'nvngx_dlss.dll' }
if (!$NativeRoot) { $NativeRoot = Join-Path $repo 'build/native-k-gfx1201' }
if (!$ZludaRoot) { $ZludaRoot = Join-Path $repo 'dist/zluda-windows-api-profile' } if (!$ZludaRoot) { $ZludaRoot = Join-Path $repo 'dist/zluda-windows-api-profile' }
if (!$PackageRoot) { $PackageRoot = Join-Path $repo 'dist/windows-rdna4-command-list' } if (!$PackageRoot) { $PackageRoot = Join-Path $repo 'dist/windows-rdna4-command-list' }
$GpuArch=Get-D4RGpuTarget $PackageRoot $null
if (!$NativeRoot) { $NativeRoot = Join-Path $repo "build/native-k-$GpuArch" }
if (!$OutputDirectory) { $OutputDirectory = Join-Path $repo ('test-results/async-k-' + (Get-Date -Format 'yyyyMMdd-HHmmss-fff')) } if (!$OutputDirectory) { $OutputDirectory = Join-Path $repo ('test-results/async-k-' + (Get-Date -Format 'yyyyMMdd-HHmmss-fff')) }
if ($Resolution -notmatch '^([0-9]+)x([0-9]+)$') { throw 'Resolution must be WIDTHxHEIGHT' } if ($Resolution -notmatch '^([0-9]+)x([0-9]+)$') { throw 'Resolution must be WIDTHxHEIGHT' }
$width=$Matches[1]; $height=$Matches[2] $width=$Matches[1]; $height=$Matches[2]
@@ -71,7 +73,7 @@ try {
Tee-Object -FilePath (Join-Path $OutputDirectory "$mode-comparison.log") Tee-Object -FilePath (Join-Path $OutputDirectory "$mode-comparison.log")
if ($LASTEXITCODE) { throw "Async $mode output mismatch" } if ($LASTEXITCODE) { throw "Async $mode output mismatch" }
} }
@{passed=$true; architecture='gfx1201'; preset=11; resolution=$Resolution; @{passed=$true; architecture=$GpuArch; preset=11; resolution=$Resolution;
inputResolution=$InputResolution; inputResolution=$InputResolution;
modes=@('burst','recreate'); framesPerMode=3; exactRgb=$true; gpuBoundaryTiming=[bool]$ProfileGpuBoundary; modes=@('burst','recreate'); framesPerMode=3; exactRgb=$true; gpuBoundaryTiming=[bool]$ProfileGpuBoundary;
deferredKernelTiming=[bool]$ProfileKernelsDeferred; batchInputs=[bool]$BatchInputCopies; pixelProfile=$PixelProfile} | deferredKernelTiming=[bool]$ProfileKernelsDeferred; batchInputs=[bool]$BatchInputCopies; pixelProfile=$PixelProfile} |
@@ -1,9 +1,11 @@
[CmdletBinding()] [CmdletBinding()]
param([string]$ZludaRoot, [string]$PackageRoot, [string]$HipRoot, [string]$OutputDirectory) param([string]$ZludaRoot, [string]$PackageRoot, [string]$HipRoot, [string]$OutputDirectory)
$ErrorActionPreference = 'Stop' $ErrorActionPreference = 'Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..')) $repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$ZludaRoot) { $ZludaRoot = Join-Path $repo 'dist/zluda-windows-deferred-profile' } if (!$ZludaRoot) { $ZludaRoot = Join-Path $repo 'dist/zluda-windows-deferred-profile' }
if (!$PackageRoot) { $PackageRoot = Join-Path $repo 'dist/windows-rdna4-command-list' } if (!$PackageRoot) { $PackageRoot = Join-Path $repo 'dist/windows-rdna4-command-list' }
$GpuArch=Get-D4RGpuTarget $PackageRoot $null
if (!$HipRoot) { $HipRoot = Join-Path $repo '.tools/therock-10.2.0a20260929/_rocm_sdk_core' } if (!$HipRoot) { $HipRoot = Join-Path $repo '.tools/therock-10.2.0a20260929/_rocm_sdk_core' }
if (!$OutputDirectory) { $OutputDirectory = Join-Path $repo ('test-results/deferred-profile-' + (Get-Date -Format 'yyyyMMdd-HHmmss-fff')) } if (!$OutputDirectory) { $OutputDirectory = Join-Path $repo ('test-results/deferred-profile-' + (Get-Date -Format 'yyyyMMdd-HHmmss-fff')) }
New-Item -ItemType Directory -Force $OutputDirectory | Out-Null New-Item -ItemType Directory -Force $OutputDirectory | Out-Null
@@ -64,7 +66,7 @@ try {
if ($exitCode) { throw "$name failed ($exitCode); logs: $OutputDirectory" } if ($exitCode) { throw "$name failed ($exitCode); logs: $OutputDirectory" }
$out=Get-Content -LiteralPath $stdout -Raw $out=Get-Content -LiteralPath $stdout -Raw
$err=Get-Content -LiteralPath $stderr -Raw $err=Get-Content -LiteralPath $stderr -Raw
if ($out -notmatch 'PASS CUDA architecture=gfx1201' -or $out -notmatch 'guard_verified=1') { throw "$name did not verify PTX output" } if ($out -notmatch "PASS CUDA architecture=$GpuArch" -or $out -notmatch 'guard_verified=1') { throw "$name did not verify PTX output" }
$records=[regex]::Matches($err, '(?m)^D4R_KERNEL_PROFILE kernel="d4r_ptx_pattern" [^\r\n]*serializing=0 deferred=1 [^\r\n]+') $records=[regex]::Matches($err, '(?m)^D4R_KERNEL_PROFILE kernel="d4r_ptx_pattern" [^\r\n]*serializing=0 deferred=1 [^\r\n]+')
$invalid=[regex]::Matches($err, '(?m)^D4R_KERNEL_PROFILE_INVALID kernel="d4r_ptx_pattern" [^\r\n]*reason=invalid_elapsed_time serializing=0 deferred=1 [^\r\n]+') $invalid=[regex]::Matches($err, '(?m)^D4R_KERNEL_PROFILE_INVALID kernel="d4r_ptx_pattern" [^\r\n]*reason=invalid_elapsed_time serializing=0 deferred=1 [^\r\n]+')
if ($records.Count + $invalid.Count -ne $iterations -or $err -match 'serializing=1|D4R_KERNEL_PROFILE_SKIPPED') { if ($records.Count + $invalid.Count -ne $iterations -or $err -match 'serializing=1|D4R_KERNEL_PROFILE_SKIPPED') {
@@ -89,11 +91,11 @@ try {
$arguments=@('--hip-root', ('"' + $HipRoot + '"'), '--cuda-dll', ('"' + (Join-Path $ZludaRoot 'nvcuda.dll') + '"'), '--iterations', '3') $arguments=@('--hip-root', ('"' + $HipRoot + '"'), '--cuda-dll', ('"' + (Join-Path $ZludaRoot 'nvcuda.dll') + '"'), '--iterations', '3')
$exitCode=RunProbe $arguments $stdout $stderr $exitCode=RunProbe $arguments $stdout $stderr
$out=Get-Content -LiteralPath $stdout -Raw; $err=Get-Content -LiteralPath $stderr -Raw $out=Get-Content -LiteralPath $stdout -Raw; $err=Get-Content -LiteralPath $stderr -Raw
if ($exitCode -or $out -notmatch 'PASS CUDA architecture=gfx1201' -or if ($exitCode -or $out -notmatch "PASS CUDA architecture=$GpuArch" -or
$err -notmatch 'reason=legacy_default_stream' -or $err -match '(?m)^D4R_KERNEL_PROFILE ') { $err -notmatch 'reason=legacy_default_stream' -or $err -match '(?m)^D4R_KERNEL_PROFILE ') {
throw 'Default-stream diagnostics did not safely skip timing events.' throw 'Default-stream diagnostics did not safely skip timing events.'
} }
@{passed=$true; architecture='gfx1201'; cases=$cases; defaultStreamSkipped=$true; addedCompletionWaits=0} | @{passed=$true; architecture=$GpuArch; cases=$cases; defaultStreamSkipped=$true; addedCompletionWaits=0} |
ConvertTo-Json -Depth 5 | Set-Content -LiteralPath (Join-Path $OutputDirectory 'validation.json') -Encoding UTF8 ConvertTo-Json -Depth 5 | Set-Content -LiteralPath (Join-Path $OutputDirectory 'validation.json') -Encoding UTF8
Write-Host "PASS deferred kernel profiling: $OutputDirectory" Write-Host "PASS deferred kernel profiling: $OutputDirectory"
} finally { } finally {
@@ -0,0 +1,23 @@
[CmdletBinding()]
param([Parameter(Mandatory=$true)][string]$PackageRoot, [Parameter(Mandatory=$true)][string]$CodeObject)
$ErrorActionPreference='Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
$target=Get-D4RGpuTarget $PackageRoot $null
$other=if ($target -eq 'gfx1201') { 'gfx1200' } else { 'gfx1201' }
function Expect-Rejection([scriptblock]$Action) {
$rejected=$false
try { & $Action | Out-Null } catch { $rejected=$true }
if (!$rejected) { throw 'GPU target contract accepted incompatible input.' }
}
if ((Get-D4RGpuTarget $PackageRoot $target) -ne $target) { throw 'Incorrect package target.' }
Assert-D4RCodeObjectTarget $CodeObject $target
Expect-Rejection { Get-D4RGpuTarget $PackageRoot $other }
Expect-Rejection { Get-D4RGpuTarget $PackageRoot 'gfx1250' }
Expect-Rejection { Assert-D4RCodeObjectTarget $CodeObject $other }
Expect-Rejection { Assert-D4RCodeObjectTarget (Join-Path $PackageRoot 'gpu-target.json') $target }
# Old packages had no target metadata and were gfx1201 only.
$legacy=Join-Path $PackageRoot '__no-target-metadata__'
if (Test-Path -LiteralPath (Join-Path $legacy 'gpu-target.json')) { throw 'Unexpected legacy test fixture.' }
if ((Get-D4RGpuTarget $legacy $null) -ne 'gfx1201') { throw 'Legacy target changed.' }
Expect-Rejection { Get-D4RGpuTarget $legacy 'gfx1200' }
Write-Host "PASS GPU_TARGET_SCRIPT target=$target rejected=5 hardware_executed=0"
+3 -1
View File
@@ -3,9 +3,11 @@ param([Parameter(Mandatory=$true)][string]$CaptureDirectory, [string]$HipRoot,
[string]$PackageRoot, [string]$OutputDirectory, [int]$Windows = 12, [string]$PackageRoot, [string]$OutputDirectory, [int]$Windows = 12,
[Parameter(Mandatory=$true)][string]$DlssDll, [int]$PtxWindows = 2) [Parameter(Mandatory=$true)][string]$DlssDll, [int]$PtxWindows = 2)
$ErrorActionPreference = 'Stop' $ErrorActionPreference = 'Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..')) $repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$HipRoot) { $HipRoot = Join-Path $repo '.tools/therock-10.2.0a20260929/_rocm_sdk_core' } if (!$HipRoot) { $HipRoot = Join-Path $repo '.tools/therock-10.2.0a20260929/_rocm_sdk_core' }
if (!$PackageRoot) { $PackageRoot = Join-Path $repo 'dist/windows-rdna4-therock' } if (!$PackageRoot) { $PackageRoot = Join-Path $repo 'dist/windows-rdna4-therock' }
$GpuArch=Get-D4RGpuTarget $PackageRoot $null
if (!$OutputDirectory) { $OutputDirectory = Join-Path $repo ('test-results/k-real-reference-' + (Get-Date -Format 'yyyyMMdd-HHmmss')) } if (!$OutputDirectory) { $OutputDirectory = Join-Path $repo ('test-results/k-real-reference-' + (Get-Date -Format 'yyyyMMdd-HHmmss')) }
New-Item -ItemType Directory -Force $OutputDirectory | Out-Null New-Item -ItemType Directory -Force $OutputDirectory | Out-Null
$previousPython = $env:PYTHONPATH $previousPython = $env:PYTHONPATH
@@ -23,7 +25,7 @@ try {
New-Item -ItemType Directory -Force $folder | Out-Null New-Item -ItemType Directory -Force $folder | Out-Null
$env:D4R_DIAG_DIR = $folder $env:D4R_DIAG_DIR = $folder
& (Join-Path $PackageRoot 'bin/d4r_native_replay_probe.exe') --hip-root $HipRoot ` & (Join-Path $PackageRoot 'bin/d4r_native_replay_probe.exe') --hip-root $HipRoot `
--module (Join-Path $PackageRoot "experimental/k/${name}_gfx1201.hsaco") ` --module (Join-Path $PackageRoot "experimental/k/${name}_${GpuArch}.hsaco") `
--fixture-dir $capture.FullName --output-dir $output --iterations 1 ` --fixture-dir $capture.FullName --output-dir $output --iterations 1 `
> (Join-Path $folder 'gpu.stdout.log') 2> (Join-Path $folder 'gpu.stderr.log') > (Join-Path $folder 'gpu.stdout.log') 2> (Join-Path $folder 'gpu.stderr.log')
if ($LASTEXITCODE) { throw "K $layer actual GPU replay failed: $folder" } if ($LASTEXITCODE) { throw "K $layer actual GPU replay failed: $folder" }
+4 -2
View File
@@ -7,15 +7,17 @@ param(
[int]$Iterations = 32 [int]$Iterations = 32
) )
$ErrorActionPreference = 'Stop' $ErrorActionPreference = 'Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..')) $repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$HipRoot) { $HipRoot = Join-Path $repo '.tools/therock-10.2.0a20260929/_rocm_sdk_core' } if (!$HipRoot) { $HipRoot = Join-Path $repo '.tools/therock-10.2.0a20260929/_rocm_sdk_core' }
if (!$PackageRoot) { $PackageRoot = Join-Path $repo 'dist/windows-rdna4-therock' } if (!$PackageRoot) { $PackageRoot = Join-Path $repo 'dist/windows-rdna4-therock' }
$GpuArch=Get-D4RGpuTarget $PackageRoot $null
if (!$OutputDirectory) { $OutputDirectory = Join-Path $repo ('test-results/k-replay-' + (Get-Date -Format 'yyyyMMdd-HHmmss')) } if (!$OutputDirectory) { $OutputDirectory = Join-Path $repo ('test-results/k-replay-' + (Get-Date -Format 'yyyyMMdd-HHmmss')) }
New-Item -ItemType Directory -Force $OutputDirectory | Out-Null New-Item -ItemType Directory -Force $OutputDirectory | Out-Null
$previousPython = $env:PYTHONPATH $previousPython = $env:PYTHONPATH
$previousDiag = $env:D4R_DIAG_DIR $previousDiag = $env:D4R_DIAG_DIR
$env:PYTHONPATH = "$(Join-Path $repo '.tools/python/vendor');$previousPython" $env:PYTHONPATH = "$(Join-Path $repo '.tools/python/vendor');$previousPython"
$summary = [ordered]@{utc=[DateTime]::UtcNow.ToString('o'); hipRoot=$HipRoot; layers=@(); passed=$false} $summary = [ordered]@{utc=[DateTime]::UtcNow.ToString('o'); hipRoot=$HipRoot; architecture=$GpuArch; layers=@(); passed=$false}
try { try {
if ($Iterations -lt 1 -or $Iterations -gt 10000) { throw 'Iterations must be 1..10000' } if ($Iterations -lt 1 -or $Iterations -gt 10000) { throw 'Iterations must be 1..10000' }
foreach ($layer in $Layers) { foreach ($layer in $Layers) {
@@ -29,7 +31,7 @@ try {
> (Join-Path $folder 'fixture.stdout.log') 2> (Join-Path $folder 'fixture.stderr.log') > (Join-Path $folder 'fixture.stdout.log') 2> (Join-Path $folder 'fixture.stderr.log')
if ($LASTEXITCODE) { throw "K $layer fixture generation failed; see $folder" } if ($LASTEXITCODE) { throw "K $layer fixture generation failed; see $folder" }
& (Join-Path $PackageRoot 'bin/d4r_native_replay_probe.exe') --hip-root $HipRoot ` & (Join-Path $PackageRoot 'bin/d4r_native_replay_probe.exe') --hip-root $HipRoot `
--module (Join-Path $PackageRoot "experimental/k/dltss_pwin_${layer}_layer_gfx1201.hsaco") ` --module (Join-Path $PackageRoot "experimental/k/dltss_pwin_${layer}_layer_${GpuArch}.hsaco") `
--fixture-dir $fixture --output-dir $output --iterations $Iterations ` --fixture-dir $fixture --output-dir $output --iterations $Iterations `
> (Join-Path $folder 'gpu.stdout.log') 2> (Join-Path $folder 'gpu.stderr.log') > (Join-Path $folder 'gpu.stdout.log') 2> (Join-Path $folder 'gpu.stderr.log')
if ($LASTEXITCODE) { throw "K $layer GPU replay failed; see $folder" } if ($LASTEXITCODE) { throw "K $layer GPU replay failed; see $folder" }
+3 -1
View File
@@ -3,9 +3,11 @@ param([Parameter(Mandatory=$true)][string]$CaptureDirectory, [string]$HipRoot,
[string]$PackageRoot, [string]$OutputDirectory, [int]$Blocks = 12, [string]$PackageRoot, [string]$OutputDirectory, [int]$Blocks = 12,
[Parameter(Mandatory=$true)][string]$DlssDll, [int]$PtxBlocks = 2) [Parameter(Mandatory=$true)][string]$DlssDll, [int]$PtxBlocks = 2)
$ErrorActionPreference = 'Stop' $ErrorActionPreference = 'Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..')) $repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$HipRoot) { $HipRoot = Join-Path $repo '.tools/therock-10.2.0a20260929/_rocm_sdk_core' } if (!$HipRoot) { $HipRoot = Join-Path $repo '.tools/therock-10.2.0a20260929/_rocm_sdk_core' }
if (!$PackageRoot) { $PackageRoot = Join-Path $repo 'dist/windows-rdna4-therock' } if (!$PackageRoot) { $PackageRoot = Join-Path $repo 'dist/windows-rdna4-therock' }
$GpuArch=Get-D4RGpuTarget $PackageRoot $null
if (!$OutputDirectory) { $OutputDirectory = Join-Path $repo ('test-results/m-real-reference-' + (Get-Date -Format 'yyyyMMdd-HHmmss')) } if (!$OutputDirectory) { $OutputDirectory = Join-Path $repo ('test-results/m-real-reference-' + (Get-Date -Format 'yyyyMMdd-HHmmss')) }
New-Item -ItemType Directory -Force $OutputDirectory | Out-Null New-Item -ItemType Directory -Force $OutputDirectory | Out-Null
$previousPython=$env:PYTHONPATH; $previousDiag=$env:D4R_DIAG_DIR $previousPython=$env:PYTHONPATH; $previousDiag=$env:D4R_DIAG_DIR
@@ -22,7 +24,7 @@ try {
New-Item -ItemType Directory -Force $folder | Out-Null New-Item -ItemType Directory -Force $folder | Out-Null
$env:D4R_DIAG_DIR = $folder $env:D4R_DIAG_DIR = $folder
& (Join-Path $PackageRoot 'bin/d4r_native_replay_probe.exe') --hip-root $HipRoot ` & (Join-Path $PackageRoot 'bin/d4r_native_replay_probe.exe') --hip-root $HipRoot `
--module (Join-Path $PackageRoot "experimental/m/${name}_gfx1201.hsaco") ` --module (Join-Path $PackageRoot "experimental/m/${name}_${GpuArch}.hsaco") `
--fixture-dir $capture.FullName --output-dir $output --iterations 1 ` --fixture-dir $capture.FullName --output-dir $output --iterations 1 `
> (Join-Path $folder 'gpu.stdout.log') 2> (Join-Path $folder 'gpu.stderr.log') > (Join-Path $folder 'gpu.stdout.log') 2> (Join-Path $folder 'gpu.stderr.log')
if ($LASTEXITCODE) { throw "M $layer actual GPU replay failed: $folder" } if ($LASTEXITCODE) { throw "M $layer actual GPU replay failed: $folder" }
+4 -2
View File
@@ -3,15 +3,17 @@ param([string]$HipRoot, [string]$PackageRoot, [string]$OutputDirectory,
[string[]]$Layers = @('enc1','enc2','enc3_tube','dec2','dec1'), [string[]]$Layers = @('enc1','enc2','enc3_tube','dec2','dec1'),
[ValidateRange(1,10000)][int]$Iterations = 32) [ValidateRange(1,10000)][int]$Iterations = 32)
$ErrorActionPreference = 'Stop' $ErrorActionPreference = 'Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..')) $repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$HipRoot) { $HipRoot = Join-Path $repo '.tools/therock-10.2.0a20260929/_rocm_sdk_core' } if (!$HipRoot) { $HipRoot = Join-Path $repo '.tools/therock-10.2.0a20260929/_rocm_sdk_core' }
if (!$PackageRoot) { $PackageRoot = Join-Path $repo 'dist/windows-rdna4-therock' } if (!$PackageRoot) { $PackageRoot = Join-Path $repo 'dist/windows-rdna4-therock' }
$GpuArch=Get-D4RGpuTarget $PackageRoot $null
if (!$OutputDirectory) { $OutputDirectory = Join-Path $repo ('test-results/m-replay-' + (Get-Date -Format 'yyyyMMdd-HHmmss')) } if (!$OutputDirectory) { $OutputDirectory = Join-Path $repo ('test-results/m-replay-' + (Get-Date -Format 'yyyyMMdd-HHmmss')) }
New-Item -ItemType Directory -Force $OutputDirectory | Out-Null New-Item -ItemType Directory -Force $OutputDirectory | Out-Null
$previousPython = $env:PYTHONPATH $previousPython = $env:PYTHONPATH
$previousDiag = $env:D4R_DIAG_DIR $previousDiag = $env:D4R_DIAG_DIR
$env:PYTHONPATH = "$(Join-Path $repo '.tools/python/vendor');$previousPython" $env:PYTHONPATH = "$(Join-Path $repo '.tools/python/vendor');$previousPython"
$summary = [ordered]@{utc=[DateTime]::UtcNow.ToString('o'); hipRoot=$HipRoot; layers=@(); passed=$false} $summary = [ordered]@{utc=[DateTime]::UtcNow.ToString('o'); hipRoot=$HipRoot; architecture=$GpuArch; layers=@(); passed=$false}
try { try {
foreach ($layer in $Layers) { foreach ($layer in $Layers) {
if ($layer -notmatch '^(enc[12]|enc3_tube|dec[12])$') { throw "Invalid M layer $layer" } if ($layer -notmatch '^(enc[12]|enc3_tube|dec[12])$') { throw "Invalid M layer $layer" }
@@ -24,7 +26,7 @@ try {
> (Join-Path $folder 'fixture.stdout.log') 2> (Join-Path $folder 'fixture.stderr.log') > (Join-Path $folder 'fixture.stdout.log') 2> (Join-Path $folder 'fixture.stderr.log')
if ($LASTEXITCODE) { throw "M $layer fixture generation failed: $folder" } if ($LASTEXITCODE) { throw "M $layer fixture generation failed: $folder" }
& (Join-Path $PackageRoot 'bin/d4r_native_replay_probe.exe') --hip-root $HipRoot ` & (Join-Path $PackageRoot 'bin/d4r_native_replay_probe.exe') --hip-root $HipRoot `
--module (Join-Path $PackageRoot "experimental/m/rrlite_${layer}_4x4_gfx1201.hsaco") ` --module (Join-Path $PackageRoot "experimental/m/rrlite_${layer}_4x4_${GpuArch}.hsaco") `
--fixture-dir $fixture --output-dir $output --iterations $Iterations ` --fixture-dir $fixture --output-dir $output --iterations $Iterations `
> (Join-Path $folder 'gpu.stdout.log') 2> (Join-Path $folder 'gpu.stderr.log') > (Join-Path $folder 'gpu.stdout.log') 2> (Join-Path $folder 'gpu.stderr.log')
if ($LASTEXITCODE) { throw "M $layer GPU replay failed: $folder" } if ($LASTEXITCODE) { throw "M $layer GPU replay failed: $folder" }
+3 -1
View File
@@ -1,9 +1,11 @@
[CmdletBinding()] [CmdletBinding()]
param([string]$HipRoot, [string]$PackageRoot, [string]$ZludaRoot, [string]$OutputDirectory) param([string]$HipRoot, [string]$PackageRoot, [string]$ZludaRoot, [string]$OutputDirectory)
$ErrorActionPreference = 'Stop' $ErrorActionPreference = 'Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
$repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..')) $repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$HipRoot) { $HipRoot = Join-Path $repo '.tools/therock-10.2.0a20260929/_rocm_sdk_core' } if (!$HipRoot) { $HipRoot = Join-Path $repo '.tools/therock-10.2.0a20260929/_rocm_sdk_core' }
if (!$PackageRoot) { $PackageRoot = Join-Path $repo 'dist/windows-rdna4-therock' } if (!$PackageRoot) { $PackageRoot = Join-Path $repo 'dist/windows-rdna4-therock' }
$GpuArch=Get-D4RGpuTarget $PackageRoot $null
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 ('test-results/native-identity-' + (Get-Date -Format 'yyyyMMdd-HHmmss')) } if (!$OutputDirectory) { $OutputDirectory = Join-Path $repo ('test-results/native-identity-' + (Get-Date -Format 'yyyyMMdd-HHmmss')) }
New-Item -ItemType Directory -Force $OutputDirectory | Out-Null New-Item -ItemType Directory -Force $OutputDirectory | Out-Null
@@ -29,7 +31,7 @@ try {
$good = Join-Path $OutputDirectory 'matching-identity' $good = Join-Path $OutputDirectory 'matching-identity'
New-Item -ItemType Directory -Force $bad,$good | Out-Null New-Item -ItemType Directory -Force $bad,$good | Out-Null
foreach ($directory in @($bad,$good)) { foreach ($directory in @($bad,$good)) {
Copy-Item -LiteralPath (Join-Path $PackageRoot 'bin/probe_gfx1201.hsaco') -Destination (Join-Path $directory 'd4r_ptx_pattern.hsaco') -Force Copy-Item -LiteralPath (Join-Path $PackageRoot "bin/probe_${GpuArch}.hsaco") -Destination (Join-Path $directory 'd4r_ptx_pattern.hsaco') -Force
} }
'd4r_ptx_pattern 0000000000000000' | Set-Content -LiteralPath (Join-Path $bad 'd4r-kernels.txt') -Encoding ASCII 'd4r_ptx_pattern 0000000000000000' | Set-Content -LiteralPath (Join-Path $bad 'd4r-kernels.txt') -Encoding ASCII
$env:D4R_ZLUDA_NATIVE_DIR = $bad $env:D4R_ZLUDA_NATIVE_DIR = $bad
+11 -7
View File
@@ -1,27 +1,30 @@
[CmdletBinding()] [CmdletBinding()]
param([string]$TextureRoot, [string]$ControlTextureRoot, [string]$CommonTextureRoot, [string]$ZludaRoot, param([string]$TextureRoot, [string]$ControlTextureRoot, [string]$CommonTextureRoot, [string]$ZludaRoot, [string]$PackageRoot,
[string]$OutputDirectory, [int]$Iterations=8, [string]$OutputResolution='512x288', [string]$InputResolution, [string]$OutputDirectory, [int]$Iterations=8, [string]$OutputResolution='512x288', [string]$InputResolution,
[switch]$CandidateFirst, [switch]$CandidateFirst,
[ValidateSet('output','input')][string]$KernelStage='output') [ValidateSet('output','input')][string]$KernelStage='output')
$ErrorActionPreference='Stop' $ErrorActionPreference='Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..')) $repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if (!$TextureRoot) { $TextureRoot=Join-Path $repo 'build/private-textures-gfx1201' } if (!$PackageRoot) { $PackageRoot=Join-Path $repo 'dist/windows-rdna4-command-list' }
$GpuArch=Get-D4RGpuTarget $PackageRoot $null
if (!$TextureRoot) { $TextureRoot=Join-Path $repo "build/private-textures-$GpuArch" }
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 'test-results/k-native-texture-reference' } if (!$OutputDirectory) { $OutputDirectory=Join-Path $repo 'test-results/k-native-texture-reference' }
if ($OutputResolution -notmatch '^([0-9]+)x([0-9]+)$') { throw 'OutputResolution must be WIDTHxHEIGHT.' } if ($OutputResolution -notmatch '^([0-9]+)x([0-9]+)$') { throw 'OutputResolution must be WIDTHxHEIGHT.' }
$outputWidth=[int]$Matches[1]; $outputHeight=[int]$Matches[2] $outputWidth=[int]$Matches[1]; $outputHeight=[int]$Matches[2]
$combined=Join-Path $OutputDirectory 'private-native' $combined=Join-Path $OutputDirectory 'private-native'
New-Item -ItemType Directory -Force $combined | Out-Null New-Item -ItemType Directory -Force $combined | Out-Null
foreach ($directory in @((Join-Path $repo 'build/native-k-gfx1201'),$CommonTextureRoot,$TextureRoot) | Where-Object { $_ }) { foreach ($directory in @((Join-Path $repo "build/native-k-$GpuArch"),$CommonTextureRoot,$TextureRoot) | Where-Object { $_ }) {
Get-ChildItem -LiteralPath $directory -Filter '*.hsaco' | Copy-Item -Destination $combined -Force Get-ChildItem -LiteralPath $directory -Filter '*.hsaco' | Copy-Item -Destination $combined -Force
} }
& python (Join-Path $repo 'kernels/tools/kernel_manifest.py') $combined (Join-Path $repo 'nvngx_dlss.dll') & python (Join-Path $repo 'kernels/tools/kernel_manifest.py') $combined (Join-Path $repo 'nvngx_dlss.dll')
if ($LASTEXITCODE) { throw 'Combined private manifest failed.' } if ($LASTEXITCODE) { throw 'Combined private manifest failed.' }
$controlNative=Join-Path $repo 'build/native-k-gfx1201' $controlNative=Join-Path $repo "build/native-k-$GpuArch"
if ($ControlTextureRoot -or $CommonTextureRoot) { if ($ControlTextureRoot -or $CommonTextureRoot) {
$controlNative=Join-Path $OutputDirectory 'control-private-native' $controlNative=Join-Path $OutputDirectory 'control-private-native'
New-Item -ItemType Directory -Force $controlNative | Out-Null New-Item -ItemType Directory -Force $controlNative | Out-Null
foreach ($directory in @((Join-Path $repo 'build/native-k-gfx1201'),$CommonTextureRoot,$ControlTextureRoot) | Where-Object { $_ }) { foreach ($directory in @((Join-Path $repo "build/native-k-$GpuArch"),$CommonTextureRoot,$ControlTextureRoot) | Where-Object { $_ }) {
Get-ChildItem -LiteralPath $directory -Filter '*.hsaco' | Copy-Item -Destination $controlNative -Force Get-ChildItem -LiteralPath $directory -Filter '*.hsaco' | Copy-Item -Destination $controlNative -Force
} }
& python (Join-Path $repo 'kernels/tools/kernel_manifest.py') $controlNative (Join-Path $repo 'nvngx_dlss.dll') & python (Join-Path $repo 'kernels/tools/kernel_manifest.py') $controlNative (Join-Path $repo 'nvngx_dlss.dll')
@@ -37,6 +40,7 @@ $stagedObjects=@{}
foreach ($stage in @(@{name='control'; root=$controlNative},@{name='candidate'; root=$combined})) { foreach ($stage in @(@{name='control'; root=$controlNative},@{name='candidate'; root=$combined})) {
$stagedObjects[$stage.name]=@{} $stagedObjects[$stage.name]=@{}
foreach ($object in Get-ChildItem -LiteralPath $stage.root -Filter '*.hsaco') { foreach ($object in Get-ChildItem -LiteralPath $stage.root -Filter '*.hsaco') {
Assert-D4RCodeObjectTarget $object.FullName $GpuArch
$stagedObjects[$stage.name][$object.Name]=(Get-FileHash -LiteralPath $object.FullName -Algorithm SHA256).Hash.ToLowerInvariant() $stagedObjects[$stage.name][$object.Name]=(Get-FileHash -LiteralPath $object.FullName -Algorithm SHA256).Hash.ToLowerInvariant()
} }
} }
@@ -52,7 +56,7 @@ try {
$expectedBackend=if (Test-Path -LiteralPath (Join-Path $env:D4R_ZLUDA_NATIVE_DIR ($kernel + '.hsaco'))) { 'native' } else { 'translated' } $expectedBackend=if (Test-Path -LiteralPath (Join-Path $env:D4R_ZLUDA_NATIVE_DIR ($kernel + '.hsaco'))) { 'native' } else { 'translated' }
if ($mode -eq 'candidate' -and $expectedBackend -ne 'native') { throw "Missing candidate object: $kernel" } if ($mode -eq 'candidate' -and $expectedBackend -ne 'native') { throw "Missing candidate object: $kernel" }
$arguments=@{RuntimeProfile='therock'; ZludaRoot=$ZludaRoot; $arguments=@{RuntimeProfile='therock'; ZludaRoot=$ZludaRoot;
PackageRoot=(Join-Path $repo 'dist/windows-rdna4-command-list'); NgxCore=(Join-Path $repo '_nvngx.dll'); PackageRoot=$PackageRoot; NgxCore=(Join-Path $repo '_nvngx.dll');
DlssDll=(Join-Path $repo 'nvngx_dlss.dll'); NgxMode='d3d12'; NgxAbi='project-legacy'; Preset=11; DlssDll=(Join-Path $repo 'nvngx_dlss.dll'); NgxMode='d3d12'; NgxAbi='project-legacy'; Preset=11;
NgxCreateFlags=$flags; NgxOutputResolution=$OutputResolution; NgxOnly=$true; RequireNativeNetwork=$true; CommandListBackend=$true; NgxCreateFlags=$flags; NgxOutputResolution=$OutputResolution; NgxOnly=$true; RequireNativeNetwork=$true; CommandListBackend=$true;
NgxInputResolution=$InputResolution; NgxInputResolution=$InputResolution;
@@ -76,7 +80,7 @@ try {
& python (Join-Path $repo 'tools/windows/frame_compare.py') --reference $control --actual $candidate --width $outputWidth --height $outputHeight --exact & python (Join-Path $repo 'tools/windows/frame_compare.py') --reference $control --actual $candidate --width $outputWidth --height $outputHeight --exact
if ($LASTEXITCODE) { throw "Texture flags=$flags full-frame RGB mismatch; preserve baseline." } if ($LASTEXITCODE) { throw "Texture flags=$flags full-frame RGB mismatch; preserve baseline." }
} }
@{passed=$true; architecture='gfx1201'; framesPerVariant=$Iterations; outputResolution=$OutputResolution; createFlags=@(0,11); strictRgb=$true; @{passed=$true; architecture=$GpuArch; framesPerVariant=$Iterations; outputResolution=$OutputResolution; createFlags=@(0,11); strictRgb=$true;
inputResolution=$InputResolution; inputResolution=$InputResolution;
serializingProfile=$true; candidateFirst=[bool]$CandidateFirst; kernelStage=$KernelStage; serializingProfile=$true; candidateFirst=[bool]$CandidateFirst; kernelStage=$KernelStage;
controlTextureRoot=$ControlTextureRoot; commonTextureRoot=$CommonTextureRoot; controlTextureRoot=$ControlTextureRoot; commonTextureRoot=$CommonTextureRoot;
+16 -13
View File
@@ -4,6 +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]$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,
@@ -26,6 +27,7 @@ param(
[int]$TimeoutSeconds = 180 [int]$TimeoutSeconds = 180
) )
$ErrorActionPreference = 'Stop' $ErrorActionPreference = 'Stop'
. (Join-Path $PSScriptRoot 'gpu-target.ps1')
$repoRoot = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..')) $repoRoot = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..'))
if ($RuntimeProfile -eq 'therock') { if ($RuntimeProfile -eq 'therock') {
# Works both from scripts/windows and the installed dist/<profile> directory. # Works both from scripts/windows and the installed dist/<profile> directory.
@@ -40,6 +42,7 @@ if (!$PackageRoot) {
else { $PackageRoot = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../../dist/windows-rdna4-diagnostics')) } else { $PackageRoot = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../../dist/windows-rdna4-diagnostics')) }
} }
$PackageRoot = [IO.Path]::GetFullPath($PackageRoot) $PackageRoot = [IO.Path]::GetFullPath($PackageRoot)
$GpuArch=Get-D4RGpuTarget $PackageRoot $GpuArch
if (!$HipRoot) { $HipRoot = 'C:\Program Files\AMD\ROCm\7.2' } if (!$HipRoot) { $HipRoot = 'C:\Program Files\AMD\ROCm\7.2' }
$HipRoot = [IO.Path]::GetFullPath($HipRoot) $HipRoot = [IO.Path]::GetFullPath($HipRoot)
if (!$ZludaRoot) { if (!$ZludaRoot) {
@@ -68,7 +71,7 @@ foreach ($setting in @('D4R_ZLUDA_WMMA','D4R_ZLUDA_WMMA_FP8','D4R_ZLUDA_WMMA_FP8
} }
$exitStatus = 1 $exitStatus = 1
$ngxRuntimeDirectory = $null $ngxRuntimeDirectory = $null
$summary = [ordered]@{utc=[DateTime]::UtcNow.ToString('o'); profile=$RuntimeProfile; hipRoot=$HipRoot; zludaRoot=$ZludaRoot; tests=@()} $summary = [ordered]@{utc=[DateTime]::UtcNow.ToString('o'); profile=$RuntimeProfile; architecture=$GpuArch; hipRoot=$HipRoot; zludaRoot=$ZludaRoot; tests=@()}
function Quote-Argument([string]$Value) { function Quote-Argument([string]$Value) {
# All generated paths are absolute file/directory paths, with no trailing backslash. # All generated paths are absolute file/directory paths, with no trailing backslash.
if ($Value.Contains('"')) { throw 'Double quotes are not allowed in arguments' } if ($Value.Contains('"')) { throw 'Double quotes are not allowed in arguments' }
@@ -162,10 +165,10 @@ try {
$comgr = Join-Path $HipRoot 'bin/amd_comgr_3.dll' $comgr = Join-Path $HipRoot 'bin/amd_comgr_3.dll'
if (!(Test-Path -LiteralPath $comgr)) { $comgr = Join-Path $HipRoot 'bin/amd_comgr.dll' } if (!(Test-Path -LiteralPath $comgr)) { $comgr = Join-Path $HipRoot 'bin/amd_comgr.dll' }
$files = @((Join-Path $HipRoot 'bin/amdhip64_7.dll'), $comgr, $files = @((Join-Path $HipRoot 'bin/amdhip64_7.dll'), $comgr,
(Join-Path $ZludaRoot 'nvcuda.dll'), (Join-Path $PackageRoot 'bin/probe_gfx1201.hsaco'), (Join-Path $ZludaRoot 'nvcuda.dll'), (Join-Path $PackageRoot "bin/probe_${GpuArch}.hsaco"),
(Join-Path $PackageRoot 'bin/wmma_gfx1201.hsaco'), (Join-Path $PackageRoot "bin/wmma_${GpuArch}.hsaco"),
(Join-Path $PackageRoot 'experimental/k/dltss_pwin_enc1_layer_gfx1201.hsaco'), (Join-Path $PackageRoot "experimental/k/dltss_pwin_enc1_layer_${GpuArch}.hsaco"),
(Join-Path $PackageRoot 'experimental/k/dltss_pwin_enc2_layer_gfx1201.hsaco')) (Join-Path $PackageRoot "experimental/k/dltss_pwin_enc2_layer_${GpuArch}.hsaco"))
if ($OptiScalerDll) { if ($OptiScalerDll) {
if ($NgxMode -ne 'd3d12' -or !$CommandListBackend) { throw '-OptiScalerDll requires D3D12 and -CommandListBackend' } if ($NgxMode -ne 'd3d12' -or !$CommandListBackend) { throw '-OptiScalerDll requires D3D12 and -CommandListBackend' }
if (![IO.Path]::IsPathRooted($OptiScalerDll)) { throw '-OptiScalerDll must be absolute' } if (![IO.Path]::IsPathRooted($OptiScalerDll)) { throw '-OptiScalerDll must be absolute' }
@@ -192,12 +195,12 @@ try {
$bin = Join-Path $PackageRoot 'bin' $bin = Join-Path $PackageRoot 'bin'
$hipOk = $true $hipOk = $true
if (!$NgxOnly) { $hipOk = Invoke-Probe 'hip' (Join-Path $bin 'd4r_hip_gfx1201_probe.exe') @( if (!$NgxOnly) { $hipOk = Invoke-Probe 'hip' (Join-Path $bin 'd4r_hip_gfx1201_probe.exe') @(
'--hip-root', $HipRoot, '--module', (Join-Path $bin 'probe_gfx1201.hsaco'), '--iterations', "$Iterations") '--hip-root', $HipRoot, '--module', (Join-Path $bin "probe_${GpuArch}.hsaco"), '--iterations', "$Iterations")
} }
if ($hipOk) { if ($hipOk) {
if (!$NgxOnly) { if (!$NgxOnly) {
$wmmaOk = Invoke-Probe 'gfx12-wmma' (Join-Path $bin 'd4r_gfx12_wmma_probe.exe') @( $wmmaOk = Invoke-Probe 'gfx12-wmma' (Join-Path $bin 'd4r_gfx12_wmma_probe.exe') @(
'--hip-root', $HipRoot, '--module', (Join-Path $bin 'wmma_gfx1201.hsaco'), '--iterations', "$Iterations") '--hip-root', $HipRoot, '--module', (Join-Path $bin "wmma_${GpuArch}.hsaco"), '--iterations', "$Iterations")
if (!$wmmaOk) { throw 'gfx12 WMMA layout validation failed; refusing to mark K/M readiness.' } if (!$wmmaOk) { throw 'gfx12 WMMA layout validation failed; refusing to mark K/M readiness.' }
$pythonCommand = Get-Command python -ErrorAction SilentlyContinue $pythonCommand = Get-Command python -ErrorAction SilentlyContinue
if (!$pythonCommand) { throw 'Python 3.11+ with NumPy 2.4.6 is needed for K reference checks; run setup-windows-tools.ps1.' } if (!$pythonCommand) { throw 'Python 3.11+ with NumPy 2.4.6 is needed for K reference checks; run setup-windows-tools.ps1.' }
@@ -205,7 +208,7 @@ try {
$kFixture = Join-Path $OutputDirectory "k-$layer-fixture" $kFixture = Join-Path $OutputDirectory "k-$layer-fixture"
$kModuleOk = Invoke-Probe "k-$layer-gpu" (Join-Path $bin 'd4r_k_module_probe.exe') @( $kModuleOk = Invoke-Probe "k-$layer-gpu" (Join-Path $bin 'd4r_k_module_probe.exe') @(
'--hip-root', $HipRoot, '--hip-root', $HipRoot,
'--module', (Join-Path $PackageRoot "experimental/k/dltss_pwin_${layer}_layer_gfx1201.hsaco"), '--module', (Join-Path $PackageRoot "experimental/k/dltss_pwin_${layer}_layer_${GpuArch}.hsaco"),
'--kernel-name', $layer, '--fixture-dir', $kFixture, '--iterations', "$Iterations") '--kernel-name', $layer, '--fixture-dir', $kFixture, '--iterations', "$Iterations")
if (!$kModuleOk) { throw "K $layer GPU execution failed; see the k-$layer-gpu logs." } if (!$kModuleOk) { throw "K $layer GPU execution failed; see the k-$layer-gpu logs." }
$kReferenceOk = Invoke-Probe "k-$layer-reference" $pythonCommand.Source @( $kReferenceOk = Invoke-Probe "k-$layer-reference" $pythonCommand.Source @(
@@ -247,19 +250,19 @@ try {
'--hip-root', $HipRoot, '--module', (Join-Path $bin 'd4r_nvngx.dll'), '--interop-mode', 'indirect', '--iterations', "$Iterations") '--hip-root', $HipRoot, '--module', (Join-Path $bin 'd4r_nvngx.dll'), '--interop-mode', 'indirect', '--iterations', "$Iterations")
if (!$commandOk) { throw 'D3D12 command-list order/state/lifetime validation failed.' } if (!$commandOk) { throw 'D3D12 command-list order/state/lifetime validation failed.' }
$pixelsOk = Invoke-Probe 'd3d12-gpu-pixel-formats' (Join-Path $bin 'd4r_d3d12_pixel_probe.exe') @( $pixelsOk = Invoke-Probe 'd3d12-gpu-pixel-formats' (Join-Path $bin 'd4r_d3d12_pixel_probe.exe') @(
'--hip-root', $HipRoot, '--module', (Join-Path $bin 'pixel_convert_gfx1201.hsaco'), '--iterations', '2') '--hip-root', $HipRoot, '--module', (Join-Path $bin "pixel_convert_${GpuArch}.hsaco"), '--iterations', '2')
if (!$pixelsOk) { throw 'D3D12 typed SRV/UAV format conversion validation failed.' } if (!$pixelsOk) { throw 'D3D12 typed SRV/UAV format conversion validation failed.' }
$mapOk = Invoke-Probe 'interop-map-lifetime' (Join-Path $bin 'd4r_d3d12_hip_interop_probe.exe') @( $mapOk = Invoke-Probe 'interop-map-lifetime' (Join-Path $bin 'd4r_d3d12_hip_interop_probe.exe') @(
'--hip-root', $HipRoot, '--interop-mode', 'map', '--iterations', '64') '--hip-root', $HipRoot, '--interop-mode', 'map', '--iterations', '64')
$interopOk = Invoke-Probe 'interop-roundtrip' (Join-Path $bin 'd4r_d3d12_hip_interop_probe.exe') @( $interopOk = Invoke-Probe 'interop-roundtrip' (Join-Path $bin 'd4r_d3d12_hip_interop_probe.exe') @(
'--hip-root', $HipRoot, '--module', (Join-Path $bin 'probe_gfx1201.hsaco'), '--iterations', "$Iterations") '--hip-root', $HipRoot, '--module', (Join-Path $bin "probe_${GpuArch}.hsaco"), '--iterations', "$Iterations")
if (!$mapOk -or !$interopOk) { if (!$mapOk -or !$interopOk) {
foreach ($mode in @('resource', 'import')) { foreach ($mode in @('resource', 'import')) {
Invoke-Probe "interop-$mode-lifetime" (Join-Path $bin 'd4r_d3d12_hip_interop_probe.exe') @( Invoke-Probe "interop-$mode-lifetime" (Join-Path $bin 'd4r_d3d12_hip_interop_probe.exe') @(
'--hip-root', $HipRoot, '--interop-mode', $mode, '--iterations', '32') | Out-Null '--hip-root', $HipRoot, '--interop-mode', $mode, '--iterations', '32') | Out-Null
} }
Invoke-Probe 'hip-stream-lifetime' (Join-Path $bin 'd4r_hip_stream_lifecycle_probe.exe') @( Invoke-Probe 'hip-stream-lifetime' (Join-Path $bin 'd4r_hip_stream_lifecycle_probe.exe') @(
'--hip-root', $HipRoot, '--module', (Join-Path $bin 'probe_gfx1201.hsaco'), '--iterations', '32') | Out-Null '--hip-root', $HipRoot, '--module', (Join-Path $bin "probe_${GpuArch}.hsaco"), '--iterations', '32') | Out-Null
} }
} }
if ($mapOk -and $interopOk) { $exitStatus = 0 } if ($mapOk -and $interopOk) { $exitStatus = 0 }
@@ -288,12 +291,12 @@ try {
# alongside the private user-supplied DLLs for this test. # alongside the private user-supplied DLLs for this test.
$localShim = Join-Path $ngxRuntimeDirectory 'd4r_nvngx.dll' $localShim = Join-Path $ngxRuntimeDirectory 'd4r_nvngx.dll'
Copy-Item -LiteralPath (Join-Path $bin 'd4r_nvngx.dll') -Destination $localShim Copy-Item -LiteralPath (Join-Path $bin 'd4r_nvngx.dll') -Destination $localShim
Copy-Item -LiteralPath (Join-Path $bin 'pixel_convert_gfx1201.hsaco') -Destination $ngxRuntimeDirectory Copy-Item -LiteralPath (Join-Path $bin "pixel_convert_${GpuArch}.hsaco") -Destination $ngxRuntimeDirectory
if ($OptiScalerDll) { if ($OptiScalerDll) {
$bridgeDirectory = Join-Path $ngxRuntimeDirectory 'd4r' $bridgeDirectory = Join-Path $ngxRuntimeDirectory 'd4r'
New-Item -ItemType Directory -Path $bridgeDirectory | Out-Null New-Item -ItemType Directory -Path $bridgeDirectory | Out-Null
Copy-Item -LiteralPath $localShim -Destination (Join-Path $bridgeDirectory '_nvngx.dll') Copy-Item -LiteralPath $localShim -Destination (Join-Path $bridgeDirectory '_nvngx.dll')
Copy-Item -LiteralPath (Join-Path $bin 'pixel_convert_gfx1201.hsaco') -Destination $bridgeDirectory Copy-Item -LiteralPath (Join-Path $bin "pixel_convert_${GpuArch}.hsaco") -Destination $bridgeDirectory
$localShim = Join-Path $ngxRuntimeDirectory 'OptiScaler.dll' $localShim = Join-Path $ngxRuntimeDirectory 'OptiScaler.dll'
Copy-Item -LiteralPath $OptiScalerDll -Destination $localShim Copy-Item -LiteralPath $OptiScalerDll -Destination $localShim
$ini = @" $ini = @"
+12 -3
View File
@@ -26,6 +26,7 @@ param(
[string]$OutputDirectory [string]$OutputDirectory
) )
$ErrorActionPreference = 'Stop' $ErrorActionPreference = 'Stop'
. (Join-Path $PSScriptRoot 'gpu-target.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.' }
@@ -67,7 +68,9 @@ if (!$NgxCore -or !$DlssDll) { throw 'Pass both local NVIDIA DLL paths with -Ngx
$NgxCore = (Get-Item -LiteralPath $NgxCore).FullName $NgxCore = (Get-Item -LiteralPath $NgxCore).FullName
$DlssDll = (Get-Item -LiteralPath $DlssDll).FullName $DlssDll = (Get-Item -LiteralPath $DlssDll).FullName
$metadata = Get-Content -LiteralPath (Join-Path $package 'package.json') -Raw | ConvertFrom-Json $metadata = Get-Content -LiteralPath (Join-Path $package 'package.json') -Raw | ConvertFrom-Json
$GpuArch=Get-D4RGpuTarget $package $metadata.architecture
foreach ($file in $metadata.files) { foreach ($file in $metadata.files) {
if ($file.path.EndsWith('.hsaco')) { Assert-D4RCodeObjectTarget (Join-Path $package $file.path) $GpuArch }
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.' }
@@ -75,7 +78,7 @@ $textureFiles=@(); $textureManifest=@()
if ($LocalTextureKernels) { if ($LocalTextureKernels) {
$LocalTextureKernels=(Get-Item -LiteralPath $LocalTextureKernels -ErrorAction Stop).FullName $LocalTextureKernels=(Get-Item -LiteralPath $LocalTextureKernels -ErrorAction Stop).FullName
$validation=Get-Content -LiteralPath (Join-Path $LocalTextureKernels 'validation.json') -Raw | ConvertFrom-Json $validation=Get-Content -LiteralPath (Join-Path $LocalTextureKernels 'validation.json') -Raw | ConvertFrom-Json
if (!$validation.passed -or !$validation.strictRgb -or $validation.architecture -ne 'gfx1201' -or if (!$validation.passed -or !$validation.strictRgb -or $validation.architecture -ne $GpuArch -or
$validation.source.dlssSha256 -ne $metadata.dlssSha256 -or !$validation.source.accuracy) { $validation.source.dlssSha256 -ne $metadata.dlssSha256 -or !$validation.source.accuracy) {
throw 'Local texture kernels must pass test-native-texture.ps1 with the exact packaged DLSS identity.' throw 'Local texture kernels must pass test-native-texture.ps1 with the exact packaged DLSS identity.'
} }
@@ -85,6 +88,7 @@ if ($LocalTextureKernels) {
} }
$path=Join-Path $LocalTextureKernels $object.Name $path=Join-Path $LocalTextureKernels $object.Name
if ((Get-FileHash -LiteralPath $path -Algorithm SHA256).Hash.ToLowerInvariant() -ne $object.Value) { throw 'Local texture object changed after validation.' } if ((Get-FileHash -LiteralPath $path -Algorithm SHA256).Hash.ToLowerInvariant() -ne $object.Value) { throw 'Local texture object changed after validation.' }
Assert-D4RCodeObjectTarget $path $GpuArch
$textureFiles+=Get-Item -LiteralPath $path $textureFiles+=Get-Item -LiteralPath $path
} }
if ($textureFiles.Count -ne 2) { throw 'Expected both validated local K output variants.' } if ($textureFiles.Count -ne 2) { throw 'Expected both validated local K output variants.' }
@@ -123,7 +127,12 @@ function InstallFile([string]$source, [string]$relative) {
$manifest | ConvertTo-Json -Depth 6 | Set-Content -LiteralPath $manifestPath -Encoding UTF8 $manifest | ConvertTo-Json -Depth 6 | Set-Content -LiteralPath $manifestPath -Encoding UTF8
} }
InstallFile (Join-Path $package 'OptiScaler.dll') 'dxgi.dll' InstallFile (Join-Path $package 'OptiScaler.dll') 'dxgi.dll'
foreach ($file in Get-ChildItem -LiteralPath (Join-Path $package 'd4r') -Recurse -File) { InstallFile $file.FullName $file.FullName.Substring($package.Length+1) } foreach ($file in $metadata.files) {
$relative=$file.path.Replace('/','\')
if ($relative.StartsWith('d4r\',[StringComparison]::OrdinalIgnoreCase)) {
InstallFile (Join-Path $package $relative) $relative
}
}
if ($LocalTextureKernels) { if ($LocalTextureKernels) {
foreach ($file in $textureFiles) { InstallFile $file.FullName ('d4r/native/' + $file.Name) } foreach ($file in $textureFiles) { InstallFile $file.FullName ('d4r/native/' + $file.Name) }
$combinedManifest=Join-Path $backup 'generated-native-manifest.txt' $combinedManifest=Join-Path $backup 'generated-native-manifest.txt'
@@ -177,7 +186,7 @@ $settings = @{
D4R_NVCUDA_DLL=(GamePath 'd4r/zluda/nvcuda.dll'); ZLUDA_CUDA_LIB=(GamePath 'd4r/zluda/nvcuda.dll'); D4R_NVCUDA_DLL=(GamePath 'd4r/zluda/nvcuda.dll'); ZLUDA_CUDA_LIB=(GamePath 'd4r/zluda/nvcuda.dll');
D4R_NVAPI_DLL=(GamePath 'd4r/nvapi/nvapi64.dll'); D4R_NVAPI_BACKEND=(GamePath 'd4r/zluda/nvapi64.dll'); D4R_NVAPI_DLL=(GamePath 'd4r/nvapi/nvapi64.dll'); D4R_NVAPI_BACKEND=(GamePath 'd4r/zluda/nvapi64.dll');
D4R_NGX_CORE=(GamePath 'd4r/vendor/_nvngx.dll'); D4R_DLSS_DLL=(GamePath 'd4r/vendor/nvngx_dlss.dll'); D4R_NGX_CORE=(GamePath 'd4r/vendor/_nvngx.dll'); D4R_DLSS_DLL=(GamePath 'd4r/vendor/nvngx_dlss.dll');
D4R_FORMAT_MODULE=(GamePath 'd4r/pixel_convert_gfx1201.hsaco'); D4R_FORMAT_MODULE=(GamePath "d4r/pixel_convert_${GpuArch}.hsaco");
D4R_ZLUDA_NATIVE_DIR=(GamePath 'd4r/native'); D4R_D3D12_COMMAND_BACKEND='1'; D4R_ZLUDA_VERBOSE='1'; D4R_ZLUDA_NATIVE_DIR=(GamePath 'd4r/native'); D4R_D3D12_COMMAND_BACKEND='1'; D4R_ZLUDA_VERBOSE='1';
D4R_ZLUDA_WMMA='1'; D4R_ZLUDA_WMMA_FP8='1'; D4R_ZLUDA_WMMA_FP8_NATIVE='0'; D4R_ZLUDA_WMMA_F16_REFERENCE='1'; D4R_ZLUDA_WMMA='1'; D4R_ZLUDA_WMMA_FP8='1'; D4R_ZLUDA_WMMA_FP8_NATIVE='0'; D4R_ZLUDA_WMMA_F16_REFERENCE='1';
# Do not inherit relaxation flags from unrelated experiments. Unset and # Do not inherit relaxation flags from unrelated experiments. Unset and
+51
View File
@@ -0,0 +1,51 @@
#pragma once
// Adapted from realdody/d4r ae530b0 (MIT), realdody <[email protected]>.
#include <cstdint>
#include <cstring>
#include <cmath>
#include <limits>
namespace d4r::diag::binary16 {
// MSVC has no _Float16 extension. Convert double<->IEEE binary16 explicitly with
// round-to-nearest-even, matching a native _Float16 cast. This probe compares the
// f16-accumulator MMA against a double sum rounded once to half, so the rounding
// must match IEEE 754 binary16 exactly.
inline uint16_t half_bits(double value) {
uint64_t bits;
std::memcpy(&bits, &value, sizeof(bits));
const uint16_t sign = static_cast<uint16_t>((bits >> 63) << 15);
int32_t exponent = static_cast<int32_t>((bits >> 52) & 0x7ff);
uint64_t mantissa = bits & 0x000fffffffffffffULL;
if (exponent == 0x7ff) return static_cast<uint16_t>(sign | (mantissa ? 0x7e00 : 0x7c00));
if (exponent == 0) return sign; // double subnormal rounds to half zero
int32_t unbiased = exponent - 1023;
if (unbiased > 15) return static_cast<uint16_t>(sign | 0x7c00);
mantissa |= 0x0010000000000000ULL; // implicit leading one (53-bit significand)
const int shift = unbiased >= -14 ? 42 : 28 - unbiased;
uint64_t rounded = shift >= 64 ? 0 : (mantissa >> shift);
if (shift < 64) {
const uint64_t remainder = mantissa & ((1ULL << shift) - 1);
const uint64_t halfway = 1ULL << (shift - 1);
if (remainder > halfway || (remainder == halfway && (rounded & 1))) ++rounded;
}
if (unbiased >= -14) {
if (rounded >= 0x800) { // rounding overflowed into the exponent
rounded = 0x400;
if (++unbiased > 15) return static_cast<uint16_t>(sign | 0x7c00);
}
return static_cast<uint16_t>(sign | ((unbiased + 15) << 10) | static_cast<uint16_t>(rounded & 0x3ff));
}
if (rounded >= 0x400) return static_cast<uint16_t>(sign | 0x0400); // smallest normal half
return static_cast<uint16_t>(sign | static_cast<uint16_t>(rounded));
}
inline double half_value(uint16_t bits) {
const bool negative = (bits & 0x8000u) != 0;
const uint32_t exponent = (bits >> 10) & 0x1fu;
const uint32_t mantissa = bits & 0x3ffu;
double magnitude;
if (exponent == 0) magnitude = std::ldexp(static_cast<double>(mantissa), -24);
else if (exponent == 0x1fu) magnitude = mantissa ? std::numeric_limits<double>::quiet_NaN() : std::numeric_limits<double>::infinity();
else magnitude = std::ldexp(static_cast<double>(mantissa) / 1024.0 + 1.0, static_cast<int>(exponent) - 15);
return negative ? -magnitude : magnitude;
}
}
+45
View File
@@ -0,0 +1,45 @@
#include "binary16.h"
#include <cstdio>
#include <initializer_list>
#include <stdexcept>
static void check(double value, uint16_t expected) {
const auto actual = d4r::diag::binary16::half_bits(value);
if (actual != expected) throw std::runtime_error("binary16 rounding mismatch");
}
int main() {
using namespace d4r::diag::binary16;
try {
unsigned encodings = 0, boundaries = 0;
for (unsigned bits = 0; bits < 65536; ++bits) {
if ((bits & 0x7c00) == 0x7c00 && (bits & 0x3ff)) continue;
check(half_value(uint16_t(bits)), uint16_t(bits));
++encodings;
}
for (unsigned bits = 0; bits < 0x7bff; ++bits) {
const double low = half_value(uint16_t(bits)), high = half_value(uint16_t(bits + 1));
const double midpoint = (low + high) * 0.5;
const uint16_t tie = uint16_t(bits + (bits & 1));
check(midpoint, tie); check(-midpoint, uint16_t(tie | 0x8000));
check(std::nextafter(midpoint, low), uint16_t(bits));
check(std::nextafter(midpoint, high), uint16_t(bits + 1));
#if !defined(_MSC_VER)
for (double value : {midpoint, -midpoint, std::nextafter(midpoint, low), std::nextafter(midpoint, high)}) {
const _Float16 native = static_cast<_Float16>(value);
uint16_t expected; std::memcpy(&expected, &native, sizeof(expected));
check(value, expected);
}
#endif
++boundaries;
}
check(65519.0, 0x7bff); check(65520.0, 0x7c00);
check(-65520.0, 0xfc00);
check(std::numeric_limits<double>::denorm_min(), 0);
check(-std::numeric_limits<double>::denorm_min(), 0x8000);
check(std::numeric_limits<double>::quiet_NaN(), 0x7e00);
std::printf("PASS BINARY16 encodings=%u rounding_boundaries=%u\n", encodings, boundaries);
return 0;
} catch (const std::exception& e) {
std::fprintf(stderr, "FAIL BINARY16 %s\n", e.what()); return 5;
}
}
+18 -6
View File
@@ -1,4 +1,4 @@
"""Build a private gfx1201 texture override from the user's local DLSS DLL. """Build a private RDNA4 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.
@@ -15,6 +15,14 @@ import subprocess
import sys import sys
def require_code_object_target(path, target):
with path.open('rb') as file:
header = file.read(64)
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]):
raise RuntimeError(f'Code object does not target {target}: {path}')
def main(): def main():
parser = argparse.ArgumentParser(description=__doc__) parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--dlss-dll', type=pathlib.Path, required=True) parser.add_argument('--dlss-dll', type=pathlib.Path, required=True)
@@ -22,6 +30,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('--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)?|'
@@ -30,6 +39,8 @@ def main():
repo = pathlib.Path(__file__).resolve().parents[2] repo = pathlib.Path(__file__).resolve().parents[2]
output = args.output_directory.resolve() output = args.output_directory.resolve()
output.mkdir(parents=True, exist_ok=True) output.mkdir(parents=True, exist_ok=True)
for existing in output.glob('*.hsaco'):
require_code_object_target(existing, args.gpu_arch)
work = output / ('work-' + args.kernel) work = output / ('work-' + args.kernel)
work.mkdir(exist_ok=True) work.mkdir(exist_ok=True)
hip = args.hip_root.resolve() hip = args.hip_root.resolve()
@@ -70,7 +81,7 @@ def main():
raise RuntimeError('PTX recipe made no changes; refuse a no-op override') raise RuntimeError('PTX recipe made no changes; refuse a no-op override')
raw, ir, extra = work / 'raw.bc', work / 'raw.ll', work / 'extra.bc' raw, ir, extra = work / 'raw.bc', work / 'raw.ll', work / 'extra.bc'
run('compile-helper', [tools['clang++'], '-x', 'hip', '-std=c++20', '-nogpuinc', '-nogpulib', '-O3', run('compile-helper', [tools['clang++'], '-x', 'hip', '-std=c++20', '-nogpuinc', '-nogpulib', '-O3',
'-mno-wavefrontsize64', '--offload-device-only', '--offload-arch=gfx1201', '-mno-wavefrontsize64', '--offload-device-only', '--offload-arch=' + args.gpu_arch,
'-fgpu-rdc', '-emit-llvm', '-c', '-Xclang', '-fdenormal-fp-math=dynamic', '-fgpu-rdc', '-emit-llvm', '-c', '-Xclang', '-fdenormal-fp-math=dynamic',
'-DD4R_ACCURACY', '-DD4R_KERNEL_NAME=' + args.kernel, '-DD4R_ACCURACY', '-DD4R_KERNEL_NAME=' + args.kernel,
'-o', raw, repo / 'kernels/tex/sust_only.hip']) '-o', raw, repo / 'kernels/tex/sust_only.hip'])
@@ -79,12 +90,12 @@ def main():
for line in ir.read_text().splitlines(): for line in ir.read_text().splitlines():
if re.search(r'@llvm.used|wchar_size|llvm.module.flags|__hip_cuid', line): if re.search(r'@llvm.used|wchar_size|llvm.module.flags|__hip_cuid', line):
continue continue
line = line.replace('optnone', '').replace('"target-cpu"="gfx1201"', '') line = line.replace('optnone', '').replace(f'"target-cpu"="{args.gpu_arch}"', '')
lines.append(re.sub(r'"target-features"="[^"]+"', '', line)) lines.append(re.sub(r'"target-features"="[^"]+"', '', line))
ir.write_text('\n'.join(lines) + '\n') ir.write_text('\n'.join(lines) + '\n')
run('assemble', [tools['llvm-as'], ir, '-o', extra]) run('assemble', [tools['llvm-as'], ir, '-o', extra])
env['D4R_ZLUDA_EXTRA_BC'] = str(extra) env['D4R_ZLUDA_EXTRA_BC'] = str(extra)
run('emit', [emitter, edited, work / 'emitted', 'gfx1201']) run('emit', [emitter, edited, work / 'emitted', args.gpu_arch])
optimized = (work / 'emitted/opt.ll').read_text() optimized = (work / 'emitted/opt.ll').read_text()
definition = re.search(r'^define amdgpu_kernel .*@' + re.escape(args.kernel) + r'\(.*#(\d+)\s*\{', optimized, re.M) definition = re.search(r'^define amdgpu_kernel .*@' + re.escape(args.kernel) + r'\(.*#(\d+)\s*\{', optimized, re.M)
if not definition: if not definition:
@@ -93,9 +104,10 @@ def main():
expected_mode = '-cumode' if args.shader_mode == 'wgp' else '+cumode' expected_mode = '-cumode' if args.shader_mode == 'wgp' else '+cumode'
if not attributes or expected_mode not in attributes[1]: if not attributes or expected_mode not in attributes[1]:
raise RuntimeError(f'Emitter did not honor {args.shader_mode} mode; build the corresponding ZLUDA patch first') raise RuntimeError(f'Emitter did not honor {args.shader_mode} mode; build the corresponding ZLUDA patch first')
require_code_object_target(work / 'emitted/module.hsaco', args.gpu_arch)
shutil.copyfile(work / 'emitted/module.hsaco', output / (args.kernel + '.hsaco')) shutil.copyfile(work / 'emitted/module.hsaco', output / (args.kernel + '.hsaco'))
run('manifest', [sys.executable, repo / 'kernels/tools/kernel_manifest.py', output, args.dlss_dll]) run('manifest', [sys.executable, repo / 'kernels/tools/kernel_manifest.py', output, args.dlss_dll])
metadata = dict(architecture='gfx1201', accuracy=True, nativeFP8=False, shaderMode=args.shader_mode, metadata = dict(architecture=args.gpu_arch, accuracy=True, nativeFP8=False, shaderMode=args.shader_mode,
lastBuiltKernel=args.kernel, lastRecipeRewrites=rewrite_counts, lastBuiltKernel=args.kernel, lastRecipeRewrites=rewrite_counts,
privateNvidiaDerivedCode=True, validation='not yet validated; do not install before comparison', privateNvidiaDerivedCode=True, validation='not yet validated; do not install before comparison',
dlssSha256=hashlib.sha256(args.dlss_dll.read_bytes()).hexdigest(), dlssSha256=hashlib.sha256(args.dlss_dll.read_bytes()).hexdigest(),
@@ -103,7 +115,7 @@ def main():
compiler=subprocess.check_output([str(tools['clang++']), '--version'], env=env).decode(errors='replace'), compiler=subprocess.check_output([str(tools['clang++']), '--version'], env=env).decode(errors='replace'),
objects={p.name: hashlib.sha256(p.read_bytes()).hexdigest() for p in output.glob('*.hsaco')}) objects={p.name: hashlib.sha256(p.read_bytes()).hexdigest() for p in output.glob('*.hsaco')})
(output / 'build-info.json').write_text(json.dumps(metadata, indent=2) + '\n') (output / 'build-info.json').write_text(json.dumps(metadata, indent=2) + '\n')
print(f'Built PRIVATE gfx1201 texture override: {output}; validation required before use') print(f'Built PRIVATE {args.gpu_arch} texture override: {output}; validation required before use')
if __name__ == '__main__': if __name__ == '__main__':
+2 -2
View File
@@ -46,7 +46,7 @@ int main(int argc, char** argv)
// Require the real HIP architecture, then match the CUDA device by PCI identity. // Require the real HIP architecture, then match the CUDA device by PCI identity.
HipApi hip(args.hip_root); HipApi hip(args.hip_root);
hipDeviceProp_t props{}; hipDeviceProp_t props{};
hip.select_gfx1201(args.device, props); hip.select_architecture(args.device, props);
CudaApi api(args.cuda_dll); CudaApi api(args.cuda_dll);
loaded_modules(); loaded_modules();
std::printf("STAGE cuInit\n"); std::printf("STAGE cuInit\n");
@@ -130,7 +130,7 @@ int main(int argc, char** argv)
if (primary) api.check(api.cuDevicePrimaryCtxRelease_v2(device), "cuDevicePrimaryCtxRelease_v2"); if (primary) api.check(api.cuDevicePrimaryCtxRelease_v2(device), "cuDevicePrimaryCtxRelease_v2");
else api.check(api.cuCtxDestroy_v2(context), "cuCtxDestroy_v2"); else api.check(api.cuCtxDestroy_v2(context), "cuCtxDestroy_v2");
cleanup.context = nullptr; cleanup.context = nullptr;
std::printf("PASS CUDA architecture=gfx1201 context=%s iterations=%u guard_verified=1 queued=%u\n", std::printf("PASS CUDA architecture=%s context=%s iterations=%u guard_verified=1 queued=%u\n", d4r::diag::HipApi::target_arch(),
args.context.c_str(), args.iterations, unsigned(queued)); args.context.c_str(), args.iterations, unsigned(queued));
return 0; return 0;
} catch (const std::exception& e) { } catch (const std::exception& e) {
+2 -2
View File
@@ -8,7 +8,7 @@ int main(int argc, char** argv) {
Args args(argc, argv); Args args(argc, argv);
HipApi hip(args.hip_root); HipApi hip(args.hip_root);
hipDeviceProp_t props{}; hipDeviceProp_t props{};
hip.select_gfx1201(args.device, props); hip.select_architecture(args.device, props);
SearchDirectory search(std::filesystem::path(wide(args.cuda_dll)).parent_path()); SearchDirectory search(std::filesystem::path(wide(args.cuda_dll)).parent_path());
CudaApi cuda(args.cuda_dll); CudaApi cuda(args.cuda_dll);
cuda.check(cuda.cuInit(0), "cuInit"); cuda.check(cuda.cuInit(0), "cuInit");
@@ -64,7 +64,7 @@ int main(int argc, char** argv) {
} }
} }
cuda.check(cuda.cuCtxSynchronize(), "cuCtxSynchronize"); cuda.check(cuda.cuCtxSynchronize(), "cuCtxSynchronize");
std::printf("PASS CUDA_IMAGES architecture=gfx1201 iterations=%u descriptor_and_storage=1 pitched_device_copies=1 fp16_fp32=1 async_array_copy=%u\n", std::printf("PASS CUDA_IMAGES architecture=%s iterations=%u descriptor_and_storage=1 pitched_device_copies=1 fp16_fp32=1 async_array_copy=%u\n", d4r::diag::HipApi::target_arch(),
args.iterations, unsigned(std::getenv("D4R_DIAG_ASYNC_ARRAY_COPY") != nullptr)); args.iterations, unsigned(std::getenv("D4R_DIAG_ASYNC_ARRAY_COPY") != nullptr));
return 0; return 0;
} catch (const std::exception& e) { } catch (const std::exception& e) {
+8 -2
View File
@@ -1,5 +1,6 @@
#include "hip_api.h" #include "hip_api.h"
#include "cuda_api.h" #include "cuda_api.h"
#include "binary16.h"
#include <array> #include <array>
#include <cmath> #include <cmath>
#include <cstring> #include <cstring>
@@ -60,6 +61,10 @@ static constexpr char source[] = R"PTX(
} }
)PTX"; )PTX";
#if defined(_MSC_VER)
using d4r::diag::binary16::half_bits;
using d4r::diag::binary16::half_value;
#else
static uint16_t half_bits(double value) { static uint16_t half_bits(double value) {
_Float16 half = static_cast<_Float16>(value); _Float16 half = static_cast<_Float16>(value);
uint16_t bits; uint16_t bits;
@@ -71,6 +76,7 @@ static double half_value(uint16_t bits) {
std::memcpy(&half, &bits, sizeof(bits)); std::memcpy(&half, &bits, sizeof(bits));
return static_cast<double>(half); return static_cast<double>(half);
} }
#endif
int main(int argc, char** argv) { int main(int argc, char** argv) {
using namespace d4r::diag; using namespace d4r::diag;
@@ -79,7 +85,7 @@ int main(int argc, char** argv) {
Args args(argc, argv); Args args(argc, argv);
HipApi hip(args.hip_root); HipApi hip(args.hip_root);
hipDeviceProp_t props{}; hipDeviceProp_t props{};
hip.select_gfx1201(args.device, props); hip.select_architecture(args.device, props);
CudaApi cuda(args.cuda_dll); CudaApi cuda(args.cuda_dll);
cuda.check(cuda.cuInit(0), "cuInit"); cuda.check(cuda.cuInit(0), "cuInit");
CUdevice device = -1; CUdevice device = -1;
@@ -155,7 +161,7 @@ int main(int argc, char** argv) {
} }
std::printf("MMA_REFERENCE cases=%zu elements=%zu differing=%zu\n", cases, d.size(), mismatch); std::printf("MMA_REFERENCE cases=%zu elements=%zu differing=%zu\n", cases, d.size(), mismatch);
if (mismatch) return 5; if (mismatch) return 5;
std::printf("PASS CUDA_F16_MMA architecture=gfx1201 cases=%zu exact_f16=1\n", cases); std::printf("PASS CUDA_F16_MMA architecture=%s cases=%zu exact_f16=1\n", d4r::diag::HipApi::target_arch(), cases);
return 0; return 0;
} catch (const std::exception& error) { } catch (const std::exception& error) {
std::fprintf(stderr, "FAIL CUDA_F16_MMA %s\n", error.what()); std::fprintf(stderr, "FAIL CUDA_F16_MMA %s\n", error.what());
@@ -360,9 +360,9 @@ static void STDMETHODCALLTYPE hook_SOSetTargets(ID3D12GraphicsCommandList* self,
return original_SOSetTargets(access.target(), start_slot, view_count, views); return original_SOSetTargets(access.target(), start_slot, view_count, views);
} }
using Fn_OMSetRenderTargets = void(STDMETHODCALLTYPE*)(ID3D12GraphicsCommandList* self, UINT render_target_descriptor_count, const D3D12_CPU_DESCRIPTOR_HANDLE *render_target_descriptors, WINBOOL single_descriptor_handle, const D3D12_CPU_DESCRIPTOR_HANDLE *depth_stencil_descriptor); using Fn_OMSetRenderTargets = void(STDMETHODCALLTYPE*)(ID3D12GraphicsCommandList* self, UINT render_target_descriptor_count, const D3D12_CPU_DESCRIPTOR_HANDLE *render_target_descriptors, BOOL single_descriptor_handle, const D3D12_CPU_DESCRIPTOR_HANDLE *depth_stencil_descriptor);
static Fn_OMSetRenderTargets original_OMSetRenderTargets = nullptr; static Fn_OMSetRenderTargets original_OMSetRenderTargets = nullptr;
static void STDMETHODCALLTYPE hook_OMSetRenderTargets(ID3D12GraphicsCommandList* self, UINT render_target_descriptor_count, const D3D12_CPU_DESCRIPTOR_HANDLE *render_target_descriptors, WINBOOL single_descriptor_handle, const D3D12_CPU_DESCRIPTOR_HANDLE *depth_stencil_descriptor) { static void STDMETHODCALLTYPE hook_OMSetRenderTargets(ID3D12GraphicsCommandList* self, UINT render_target_descriptor_count, const D3D12_CPU_DESCRIPTOR_HANDLE *render_target_descriptors, BOOL single_descriptor_handle, const D3D12_CPU_DESCRIPTOR_HANDLE *depth_stencil_descriptor) {
Access access(self); Access access(self);
auto saved_render_target_descriptors = copy_values(render_target_descriptors, (single_descriptor_handle ? 1 : render_target_descriptor_count)); auto saved_render_target_descriptors = copy_values(render_target_descriptors, (single_descriptor_handle ? 1 : render_target_descriptor_count));
auto saved_depth_stencil_descriptor = copy_values(depth_stencil_descriptor, 1); auto saved_depth_stencil_descriptor = copy_values(depth_stencil_descriptor, 1);
+2 -2
View File
@@ -123,7 +123,7 @@ int main(int argc, char** argv) {
std::unique_ptr<HipApi> hip; std::unique_ptr<HipApi> hip;
hipDeviceProp_t props{}; hipDeviceProp_t props{};
const bool no_hip = std::getenv("D4R_COMMAND_PROBE_NO_HIP") != nullptr; const bool no_hip = std::getenv("D4R_COMMAND_PROBE_NO_HIP") != nullptr;
if (!no_hip) { hip = std::make_unique<HipApi>(args.hip_root); hip->select_gfx1201(args.device, props); } if (!no_hip) { hip = std::make_unique<HipApi>(args.hip_root); hip->select_architecture(args.device, props); }
ComPtr<IDXGIFactory4> factory; dx(CreateDXGIFactory1(IID_PPV_ARGS(factory.GetAddressOf())), "Probe DXGI"); ComPtr<IDXGIFactory4> factory; dx(CreateDXGIFactory1(IID_PPV_ARGS(factory.GetAddressOf())), "Probe DXGI");
ComPtr<IDXGIAdapter1> adapter; ComPtr<IDXGIAdapter1> adapter;
for (UINT i = 0; ; ++i) { for (UINT i = 0; ; ++i) {
@@ -295,7 +295,7 @@ int main(int argc, char** argv) {
} }
const bool warp = std::getenv("D4R_COMMAND_PROBE_WARP") != nullptr; const bool warp = std::getenv("D4R_COMMAND_PROBE_WARP") != nullptr;
std::printf("PASS D3D12_COMMAND_BACKEND adapter=%s architecture=%s backend=%u iterations=%u batch_order=1 root_state=1 deep_copy=1 indirect=%u indirect_reset=%u reset_reuse=%u live_recordings=0 frame_age=0\n", std::printf("PASS D3D12_COMMAND_BACKEND adapter=%s architecture=%s backend=%u iterations=%u batch_order=1 root_state=1 deep_copy=1 indirect=%u indirect_reset=%u reset_reuse=%u live_recordings=0 frame_age=0\n",
warp ? "WARP" : "AMD", warp ? "software" : no_hip ? "not_queried" : "gfx1201", !no_hooks, warp ? "WARP" : "AMD", warp ? "software" : no_hip ? "not_queried" : HipApi::target_arch(), !no_hooks,
args.iterations, indirect_enabled, root_indirect, no_hooks ? 0 : 2 * args.iterations); args.iterations, indirect_enabled, root_indirect, no_hooks ? 0 : 2 * args.iterations);
return 0; return 0;
} catch (const std::exception& failure) { } catch (const std::exception& failure) {
+3 -3
View File
@@ -30,7 +30,7 @@ int main(int argc, char** argv) {
std::make_pair("D4R_NVCUDA_DLL", args.cuda_dll), std::make_pair("D4R_NVAPI_DLL", args.nvapi_dll), std::make_pair("D4R_NVCUDA_DLL", args.cuda_dll), std::make_pair("D4R_NVAPI_DLL", args.nvapi_dll),
std::make_pair("D4R_NGX_CORE", args.ngx_core), std::make_pair("D4R_DLSS_DLL", args.dlss_dll)}) std::make_pair("D4R_NGX_CORE", args.ngx_core), std::make_pair("D4R_DLSS_DLL", args.dlss_dll)})
if (_putenv_s(pair.first, pair.second.c_str())) throw std::runtime_error("Cannot set runtime environment"); if (_putenv_s(pair.first, pair.second.c_str())) throw std::runtime_error("Cannot set runtime environment");
HipApi hip(args.hip_root); hipDeviceProp_t props{}; hip.select_gfx1201(args.device, props); HipApi hip(args.hip_root); hipDeviceProp_t props{}; hip.select_architecture(args.device, props);
ComPtr<IDXGIFactory4> factory; dx(CreateDXGIFactory1(IID_PPV_ARGS(factory.GetAddressOf())), "CreateDXGIFactory1"); ComPtr<IDXGIFactory4> factory; dx(CreateDXGIFactory1(IID_PPV_ARGS(factory.GetAddressOf())), "CreateDXGIFactory1");
ComPtr<IDXGIAdapter1> adapter; ComPtr<IDXGIAdapter1> adapter;
bool found = false; bool found = false;
@@ -169,7 +169,7 @@ int main(int argc, char** argv) {
if (!matches) throw std::runtime_error("Imported D3D12 VRAM to CUDA array mismatch on plane " + std::to_string(i)); if (!matches) throw std::runtime_error("Imported D3D12 VRAM to CUDA array mismatch on plane " + std::to_string(i));
timeline.drain(queue.Get()); timeline.drain(queue.Get());
} }
std::printf("PASS D3D12_ARRAY_COPY architecture=gfx1201 planes=5 cpu_copies_between_apis=0\n"); std::printf("PASS D3D12_ARRAY_COPY architecture=%s planes=5 cpu_copies_between_apis=0\n", d4r::diag::HipApi::target_arch());
return 0; return 0;
} }
Library shim(wide(args.module)); Library shim(wide(args.module));
@@ -398,7 +398,7 @@ int main(int argc, char** argv) {
std::printf("D4R_BURST_VALIDATION frames=%zu cpu_readback_after_all_submissions=1\n", submitted.size()); std::printf("D4R_BURST_VALIDATION frames=%zu cpu_readback_after_all_submissions=1\n", submitted.size());
} }
loaded_modules(); loaded_modules();
std::printf("PASS D3D12_DLSS architecture=gfx1201 preset=%u frames=%u fast_path_cpu_copies=0 frame_age=0 enhanced=%u queue_integration=%s\n", std::printf("PASS D3D12_DLSS architecture=%s preset=%u frames=%u fast_path_cpu_copies=0 frame_age=0 enhanced=%u queue_integration=%s\n", d4r::diag::HipApi::target_arch(),
args.preset, args.iterations, enhanced, commandBackend ? "recorded_command_list" : "explicit_harness"); args.preset, args.iterations, enhanced, commandBackend ? "recorded_command_list" : "explicit_harness");
return 0; return 0;
} catch (const std::exception& error) { std::fprintf(stderr, "FAIL D3D12_DLSS %s\n", error.what()); loaded_modules(); return 4; } } catch (const std::exception& error) { std::fprintf(stderr, "FAIL D3D12_DLSS %s\n", error.what()); loaded_modules(); return 4; }
+2 -2
View File
@@ -137,7 +137,7 @@ int main(int argc, char** argv)
throw std::runtime_error("--stream-lifetime must be persistent or cycle"); throw std::runtime_error("--stream-lifetime must be persistent or cycle");
HipApi hip(args.hip_root); HipApi hip(args.hip_root);
hipDeviceProp_t props{}; hipDeviceProp_t props{};
hip.select_gfx1201(args.device, props); hip.select_architecture(args.device, props);
ExternalApi external{hip}; ExternalApi external{hip};
ComPtr<IDXGIFactory4> factory; ComPtr<IDXGIFactory4> factory;
dx(CreateDXGIFactory1(IID_PPV_ARGS(factory.GetAddressOf())), "CreateDXGIFactory1"); dx(CreateDXGIFactory1(IID_PPV_ARGS(factory.GetAddressOf())), "CreateDXGIFactory1");
@@ -336,7 +336,7 @@ int main(int argc, char** argv)
DWORD handles_after = 0; GetProcessHandleCount(GetCurrentProcess(), &handles_after); DWORD handles_after = 0; GetProcessHandleCount(GetCurrentProcess(), &handles_after);
std::printf("HANDLES before=%lu after=%lu\n", handles_before, handles_after); std::printf("HANDLES before=%lu after=%lu\n", handles_before, handles_after);
if (final_cycle_handles > warmed_handles + 4) throw std::runtime_error("Handle count grew after first-cycle warmup"); if (final_cycle_handles > warmed_handles + 4) throw std::runtime_error("Handle count grew after first-cycle warmup");
std::printf("PASS INTEROP architecture=gfx1201 iterations=%u texture=R32_UINT external_fence=1\n", args.iterations); std::printf("PASS INTEROP architecture=%s iterations=%u texture=R32_UINT external_fence=1\n", d4r::diag::HipApi::target_arch(), args.iterations);
return 0; return 0;
} catch (const std::exception& e) { } catch (const std::exception& e) {
std::fprintf(stderr, "FAIL INTEROP %s\n", e.what()); std::fprintf(stderr, "FAIL INTEROP %s\n", e.what());
+2 -2
View File
@@ -170,7 +170,7 @@ std::vector<uint32_t> read_reference(ID3D12Device* device, ID3D12CommandQueue* q
int main(int argc, char** argv) { int main(int argc, char** argv) {
start(); start();
try { try {
Args args(argc, argv); HipApi hip(args.hip_root); hipDeviceProp_t props{}; hip.select_gfx1201(args.device, props); Args args(argc, argv); HipApi hip(args.hip_root); hipDeviceProp_t props{}; hip.select_architecture(args.device, props);
ExternalApi external{hip}; PixelProgram program(hip, wide(args.module)); ExternalApi external{hip}; PixelProgram program(hip, wide(args.module));
{ {
PixelAllocation diagnostic(hip,3,1,8); PixelAllocation diagnostic(hip,3,1,8);
@@ -259,6 +259,6 @@ int main(int argc, char** argv) {
} }
++verified; std::printf("PASS PIXEL_FORMAT name=%s plane=%u pixels=%u decode_max_abs=%.9g encode=%u\n", item.name,item.plane,count,maxAbs,item.plane==0); ++verified; std::printf("PASS PIXEL_FORMAT name=%s plane=%u pixels=%u decode_max_abs=%.9g encode=%u\n", item.name,item.plane,count,maxAbs,item.plane==0);
} }
std::printf("PASS D3D12_GPU_FORMATS architecture=gfx1201 cases=%u iterations=%u width=%u height=%u enhanced=%u typed_srv_reference=1 typed_uav_reference=1\n", verified,args.iterations,width,height,enhanced); return 0; std::printf("PASS D3D12_GPU_FORMATS architecture=%s cases=%u iterations=%u width=%u height=%u enhanced=%u typed_srv_reference=1 typed_uav_reference=1\n", d4r::diag::HipApi::target_arch(), verified,args.iterations,width,height,enhanced); return 0;
} catch (const std::exception& error) { std::fprintf(stderr,"FAIL D3D12_GPU_FORMATS %s\n",error.what()); loaded_modules(); return 1; } } catch (const std::exception& error) { std::fprintf(stderr,"FAIL D3D12_GPU_FORMATS %s\n",error.what()); loaded_modules(); return 1; }
} }
+2 -2
View File
@@ -87,10 +87,10 @@ 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_gfx1201(-1,props); d4r::diag::HipApi hip(d4r::win::env_path("D4R_HIP_ROOT")); hipDeviceProp_t props{}; hip.select_architecture(-1,props);
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=gfx1201\n",info->FeatureID,requirements->FeatureSupported); std::printf("D4R_REQUIREMENTS feature=%u support=%u architecture=%s\n",info->FeatureID,requirements->FeatureSupported,d4r::diag::HipApi::target_arch());
return 1u; return 1u;
}); });
} }
+3 -2
View File
@@ -52,8 +52,9 @@ def generate(source):
slot = 9 # IUnknown(3), ID3D12Object(4), DeviceChild(1), CommandList(1). slot = 9 # IUnknown(3), ID3D12Object(4), DeviceChild(1), CommandList(1).
for version, interface, methods in sorted(classes): for version, interface, methods in sorted(classes):
for result, name, arguments in methods: for result, name, arguments in methods:
result = ' '.join(result.split()) # MinGW WINBOOL and Microsoft SDK BOOL have the same ABI.
arguments = ' '.join(arguments.split()) result = ' '.join(result.split()).replace('WINBOOL', 'BOOL')
arguments = ' '.join(arguments.split()).replace('WINBOOL', 'BOOL')
declarations = [arg.strip() for arg in arguments.split(',')] if arguments else [] declarations = [arg.strip() for arg in arguments.split(',')] if arguments else []
names = [] names = []
for declaration in declarations: for declaration in declarations:
+2 -2
View File
@@ -30,7 +30,7 @@ int main(int argc, char** argv)
if (args.module.empty()) throw std::runtime_error("--module is required"); if (args.module.empty()) throw std::runtime_error("--module is required");
HipApi hip(args.hip_root); HipApi hip(args.hip_root);
hipDeviceProp_t properties{}; hipDeviceProp_t properties{};
hip.select_gfx1201(args.device, properties); hip.select_architecture(args.device, properties);
hipModule_t module = nullptr; hipModule_t module = nullptr;
hip.check(hip.hipModuleLoad(&module, args.module.c_str()), "hipModuleLoad(WMMA)"); hip.check(hip.hipModuleLoad(&module, args.module.c_str()), "hipModuleLoad(WMMA)");
struct ModuleCleanup { struct ModuleCleanup {
@@ -120,7 +120,7 @@ int main(int argc, char** argv)
} }
} }
} }
std::printf("PASS GFX12_WMMA architecture=gfx1201 modes=raw,legacy_adapter,upstream_layout iterations=%u max_abs=%.9g max_rel=%.9g\n", std::printf("PASS GFX12_WMMA architecture=%s modes=raw,legacy_adapter,upstream_layout iterations=%u max_abs=%.9g max_rel=%.9g\n", d4r::diag::HipApi::target_arch(),
args.iterations, max_absolute_error, max_relative_error); args.iterations, max_absolute_error, max_relative_error);
return 0; return 0;
} catch (const std::exception& error) { } catch (const std::exception& error) {
+6
View File
@@ -0,0 +1,6 @@
{
"schema": 1,
"architecture": "@D4R_GPU_ARCH@",
"wavefrontSize": 32,
"validation": "Compilation is not hardware validation; run the GPU diagnostics."
}
+41
View File
@@ -0,0 +1,41 @@
#pragma once
#include <array>
#include <filesystem>
#include <fstream>
#include <stdexcept>
#include <string>
#ifndef D4R_TARGET_ARCH
#define D4R_TARGET_ARCH "gfx1201"
#endif
namespace d4r::diag {
inline bool supported_gpu_target(const std::string& target) {
return target == "gfx1200" || target == "gfx1201";
}
inline std::string gpu_architecture(const std::string& name) {
return name.substr(0, name.find(':'));
}
inline void require_gpu_target(const std::string& actual, const std::string& expected) {
if (!supported_gpu_target(expected) || gpu_architecture(actual) != expected)
throw std::runtime_error("GPU architecture mismatch: detected " + actual + ", package requires " + expected);
}
inline std::string code_object_target(const std::filesystem::path& path) {
// AMDGPU ELF e_flags machine IDs from LLVM's documented code-object ABI.
// Never infer compatibility from a filename or rewrite the ELF target.
std::ifstream file(path, std::ios::binary);
std::array<unsigned char, 64> header{};
if (!file.read(reinterpret_cast<char*>(header.data()), header.size()) ||
header[0] != 0x7f || header[1] != 'E' || header[2] != 'L' || header[3] != 'F' ||
header[4] != 2 || header[5] != 1 || header[18] != 0xe0 || header[19] != 0)
throw std::runtime_error("Invalid AMDGPU ELF64 code object: " + path.string());
switch (header[48]) {
case 0x48: return "gfx1200";
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) {
require_gpu_target(code_object_target(path), expected);
}
}
+31
View File
@@ -0,0 +1,31 @@
#include "gpu_target.h"
#include <cstdio>
int main(int argc, char** argv) {
using namespace d4r::diag;
try {
unsigned rejected = 0, objects = 0;
for (const char* target : {"gfx1200", "gfx1201"}) {
require_gpu_target(target, target);
require_gpu_target(std::string(target) + ":xnack-:sramecc-", target);
for (const char* invalid : {"gfx1101", "gfx12000", "gfx1202", "gfx1250", ""}) {
try { require_gpu_target(invalid, target); }
catch (const std::exception&) { ++rejected; continue; }
throw std::runtime_error("Invalid GPU target accepted");
}
}
for (int i = 1; i < argc; ++i) {
require_code_object_target(argv[i], D4R_TARGET_ARCH);
const auto other = std::string(D4R_TARGET_ARCH) == "gfx1201" ? "gfx1200" : "gfx1201";
try { require_code_object_target(argv[i], other); }
catch (const std::exception&) { ++rejected; ++objects; continue; }
throw std::runtime_error("Wrong code-object target accepted");
}
if (!objects) throw std::runtime_error("Supply actual compiled code objects");
std::printf("PASS GPU_TARGET_CONTRACT target=%s objects=%u rejected=%u hardware_executed=0\n",
D4R_TARGET_ARCH, objects, rejected);
return 0;
} catch (const std::exception& e) {
std::fprintf(stderr, "FAIL GPU_TARGET_CONTRACT %s\n", e.what()); return 5;
}
}
+8 -4
View File
@@ -1,5 +1,6 @@
#pragma once #pragma once
#include "diagnostic.h" #include "diagnostic.h"
#include "gpu_target.h"
#include <hip/hip_runtime_api.h> #include <hip/hip_runtime_api.h>
namespace d4r::diag { namespace d4r::diag {
@@ -40,7 +41,8 @@ struct HipApi {
if (verbose || result != hipSuccess) std::printf("HIP %s -> %d (%s)\n", call, static_cast<int>(result), hipGetErrorName(result)); if (verbose || result != hipSuccess) std::printf("HIP %s -> %d (%s)\n", call, static_cast<int>(result), hipGetErrorName(result));
if (result != hipSuccess) throw std::runtime_error(std::string(call) + ": " + hipGetErrorString(result)); if (result != hipSuccess) throw std::runtime_error(std::string(call) + ": " + hipGetErrorString(result));
} }
int select_gfx1201(int requested, hipDeviceProp_t& selected) const { static const char* target_arch() { return D4R_TARGET_ARCH; }
int select_architecture(int requested, hipDeviceProp_t& selected) 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);
@@ -59,14 +61,16 @@ 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 (arch.substr(0, arch.find(':')) == "gfx1201" && (requested < 0 || requested == i) && found < 0) { if (gpu_architecture(arch) == target_arch() && (requested < 0 || requested == i) && found < 0) {
found = i; found = i;
selected = props; selected = props;
} }
} }
if (found < 0) throw std::runtime_error("No selected gfx1201 device; never substitute gfx110x"); if (found < 0) throw std::runtime_error(std::string("No selected ") + target_arch() + " device; refusing architecture substitution");
require_gpu_target(selected.gcnArchName, target_arch());
check(hipSetDevice(found), "hipSetDevice"); check(hipSetDevice(found), "hipSetDevice");
std::printf("SELECTED HIP ordinal=%d architecture=gfx1201\n", found); std::printf("SELECTED HIP ordinal=%d architecture=%s validation=%s\n", found, target_arch(),
std::string(target_arch()) == "gfx1201" ? "previously_tested_target" : "hardware_unverified_target");
return found; return found;
} }
}; };
+3 -3
View File
@@ -9,13 +9,13 @@ int main(int argc, char** argv)
if (args.module.empty()) throw std::runtime_error("--module is required"); if (args.module.empty()) throw std::runtime_error("--module is required");
HipApi api(args.hip_root); HipApi api(args.hip_root);
hipDeviceProp_t props{}; hipDeviceProp_t props{};
api.select_gfx1201(args.device, props); api.select_architecture(args.device, props);
loaded_modules(); loaded_modules();
size_t free = 0, total = 0; size_t free = 0, total = 0;
api.check(api.hipMemGetInfo(&free, &total), "hipMemGetInfo"); api.check(api.hipMemGetInfo(&free, &total), "hipMemGetInfo");
std::printf("VRAM free=%zu total=%zu\n", free, total); std::printf("VRAM free=%zu total=%zu\n", free, total);
hipModule_t module = nullptr; hipModule_t module = nullptr;
api.check(api.hipModuleLoad(&module, args.module.c_str()), "hipModuleLoad(gfx1201)"); api.check(api.hipModuleLoad(&module, args.module.c_str()), "hipModuleLoad(target)");
struct ModuleCleanup { HipApi& api; hipModule_t m; ~ModuleCleanup() { if (m) (void)api.hipModuleUnload(m); } } cleanup{api, module}; struct ModuleCleanup { HipApi& api; hipModule_t m; ~ModuleCleanup() { if (m) (void)api.hipModuleUnload(m); } } cleanup{api, module};
hipFunction_t kernel = nullptr; hipFunction_t kernel = nullptr;
api.check(api.hipModuleGetFunction(&kernel, module, "d4r_probe_pattern"), "hipModuleGetFunction"); api.check(api.hipModuleGetFunction(&kernel, module, "d4r_probe_pattern"), "hipModuleGetFunction");
@@ -41,7 +41,7 @@ int main(int argc, char** argv)
allocation_cleanup.p = nullptr; allocation_cleanup.p = nullptr;
api.check(api.hipModuleUnload(module), "hipModuleUnload"); api.check(api.hipModuleUnload(module), "hipModuleUnload");
cleanup.m = nullptr; cleanup.m = nullptr;
std::printf("PASS HIP architecture=gfx1201 iterations=%u guard_verified=1\n", args.iterations); std::printf("PASS HIP architecture=%s iterations=%u guard_verified=1\n", d4r::diag::HipApi::target_arch(), args.iterations);
return 0; return 0;
} catch (const std::exception& e) { } catch (const std::exception& e) {
std::fprintf(stderr, "FAIL HIP %s\n", e.what()); std::fprintf(stderr, "FAIL HIP %s\n", e.what());
+1 -1
View File
@@ -9,7 +9,7 @@ int main(int argc, char** argv)
Args args(argc, argv); Args args(argc, argv);
HipApi hip(args.hip_root); HipApi hip(args.hip_root);
hipDeviceProp_t props{}; hipDeviceProp_t props{};
hip.select_gfx1201(args.device, props); hip.select_architecture(args.device, props);
hipModule_t module = nullptr; hipModule_t module = nullptr;
hipFunction_t kernel = nullptr; hipFunction_t kernel = nullptr;
void* output = nullptr; void* output = nullptr;
+2 -2
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
"""Compare real gfx1201 K enc1/enc2 launches with the existing numpy reference.""" """Compare RDNA4 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 architecture=gfx1201 kernel={args.kernel_name} " print(f"PASS K_REFERENCE reference_layout=gfx12 kernel={args.kernel_name} "
"nonzero_weights=1 transformer_executed=1 nan_inf=0") "nonzero_weights=1 transformer_executed=1 nan_inf=0")
+3 -3
View File
@@ -42,7 +42,7 @@ int main(int argc, char** argv)
if (args.module.empty()) throw std::runtime_error("--module is required"); if (args.module.empty()) throw std::runtime_error("--module is required");
HipApi hip(args.hip_root); HipApi hip(args.hip_root);
hipDeviceProp_t properties{}; hipDeviceProp_t properties{};
hip.select_gfx1201(args.device, properties); hip.select_architecture(args.device, properties);
if (args.kernel_name != "enc1" && args.kernel_name != "enc2") if (args.kernel_name != "enc1" && args.kernel_name != "enc2")
throw std::runtime_error("--kernel-name must be enc1 or enc2"); throw std::runtime_error("--kernel-name must be enc1 or enc2");
const bool enc2 = args.kernel_name == "enc2"; const bool enc2 = args.kernel_name == "enc2";
@@ -124,7 +124,7 @@ int main(int argc, char** argv)
return 5; return 5;
} }
} }
std::printf("PASS K_IDENTITY architecture=gfx1201 kernel=%s iterations=%u full_elements=%zu merged_elements=%zu transformer_executed=1 nonzero_weights=0\n", std::printf("PASS K_IDENTITY architecture=%s kernel=%s iterations=%u full_elements=%zu merged_elements=%zu transformer_executed=1 nonzero_weights=0\n", d4r::diag::HipApi::target_arch(),
args.kernel_name.c_str(), args.iterations, full_elements, merged_elements); args.kernel_name.c_str(), args.iterations, full_elements, merged_elements);
// Exercise nonzero V projection, position-only attention and Wo GEMMs. // Exercise nonzero V projection, position-only attention and Wo GEMMs.
@@ -213,7 +213,7 @@ int main(int argc, char** argv)
save("full.bin", full.data(), full.size() * sizeof(uint16_t)); save("full.bin", full.data(), full.size() * sizeof(uint16_t));
save("merged.bin", merged.data(), merged.size() * sizeof(uint16_t)); save("merged.bin", merged.data(), merged.size() * sizeof(uint16_t));
} }
std::printf("PASS K_NONZERO architecture=gfx1201 kernel=%s changed_elements=%zu full_elements=%zu merged_elements=%zu fixture_saved=%d numerical_reference_pending=1\n", std::printf("PASS K_NONZERO architecture=%s kernel=%s changed_elements=%zu full_elements=%zu merged_elements=%zu fixture_saved=%d numerical_reference_pending=1\n", d4r::diag::HipApi::target_arch(),
args.kernel_name.c_str(), changed, full.size(), merged.size(), !args.fixture_dir.empty()); args.kernel_name.c_str(), changed, full.size(), merged.size(), !args.fixture_dir.empty());
return 0; return 0;
} catch (const std::exception& error) { } catch (const std::exception& error) {
+1 -1
View File
@@ -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} architecture=gfx1201 nan_inf=0') print(f'PASS K_REPLAY_REFERENCE kernel={layer} reference_layout=gfx12 nan_inf=0')
if __name__ == '__main__': if __name__ == '__main__':
+1 -1
View File
@@ -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)} architecture=gfx1201 nan_inf=0') print(f'PASS M_REPLAY_REFERENCE kernel={layer} blocks={len(pairs)} reference_layout=gfx12 nan_inf=0')
if __name__ == '__main__': if __name__ == '__main__':
+3 -3
View File
@@ -37,7 +37,7 @@ int main(int argc, char** argv) {
throw std::runtime_error("--module, --fixture-dir and --output-dir are required"); throw std::runtime_error("--module, --fixture-dir and --output-dir are required");
HipApi hip(args.hip_root); HipApi hip(args.hip_root);
hipDeviceProp_t props{}; hipDeviceProp_t props{};
hip.select_gfx1201(args.device, props); hip.select_architecture(args.device, props);
const std::filesystem::path input(wide(args.fixture_dir)), output(wide(args.output_dir)); const std::filesystem::path input(wide(args.fixture_dir)), output(wide(args.output_dir));
auto parameters = read_file(input / L"args.bin"); auto parameters = read_file(input / L"args.bin");
if (parameters.empty() || parameters.size() > 4096) throw std::runtime_error("Invalid replay parameter size"); if (parameters.empty() || parameters.size() > 4096) throw std::runtime_error("Invalid replay parameter size");
@@ -84,7 +84,7 @@ int main(int argc, char** argv) {
std::memcpy(parameters.data() + offset, &pointer, 8); std::memcpy(parameters.data() + offset, &pointer, 8);
} }
hipModule_t module = nullptr; hipModule_t module = nullptr;
hip.check(hip.hipModuleLoad(&module, args.module.c_str()), "hipModuleLoad(replay gfx1201)"); hip.check(hip.hipModuleLoad(&module, args.module.c_str()), "hipModuleLoad(replay)");
struct Cleanup { HipApi& hip; hipModule_t module; ~Cleanup() { (void)hip.hipModuleUnload(module); } } cleanup{hip, module}; struct Cleanup { HipApi& hip; hipModule_t module; ~Cleanup() { (void)hip.hipModuleUnload(module); } } cleanup{hip, module};
if (const char* debugBlock = std::getenv("D4R_SWIN_DEBUG_BLOCK")) { if (const char* debugBlock = std::getenv("D4R_SWIN_DEBUG_BLOCK")) {
int coordinates[2]{}; int coordinates[2]{};
@@ -240,7 +240,7 @@ int main(int argc, char** argv) {
file.write(reinterpret_cast<const char*>(bytes.data()), std::streamsize(bytes.size())); file.write(reinterpret_cast<const char*>(bytes.data()), std::streamsize(bytes.size()));
if (!file) throw std::runtime_error("Cannot save replay allocation"); if (!file) throw std::runtime_error("Cannot save replay allocation");
} }
std::printf("PASS NATIVE_REPLAY architecture=gfx1201 kernel=%s iterations=%u benchmark_pairs=%u numerical_reference=pending\n", std::printf("PASS NATIVE_REPLAY architecture=%s kernel=%s iterations=%u benchmark_pairs=%u numerical_reference=pending\n", d4r::diag::HipApi::target_arch(),
kernel.c_str(), args.benchmark_module.empty() ? args.iterations : 1, args.benchmark_module.empty() ? 0 : args.iterations); kernel.c_str(), args.benchmark_module.empty() ? args.iterations : 1, args.benchmark_module.empty() ? 0 : args.iterations);
return 0; return 0;
} catch (const std::exception& error) { } catch (const std::exception& error) {
+2 -2
View File
@@ -34,7 +34,7 @@ int main(int argc, char** argv)
if (dlss_path.filename() != L"nvngx_dlss.dll") throw std::runtime_error("DLSS file must be named nvngx_dlss.dll"); if (dlss_path.filename() != L"nvngx_dlss.dll") throw std::runtime_error("DLSS file must be named nvngx_dlss.dll");
HipApi hip(args.hip_root); HipApi hip(args.hip_root);
hipDeviceProp_t props{}; hipDeviceProp_t props{};
hip.select_gfx1201(args.device, props); hip.select_architecture(args.device, props);
SearchDirectory cuda_search(std::filesystem::path(wide(args.cuda_dll)).parent_path()); SearchDirectory cuda_search(std::filesystem::path(wide(args.cuda_dll)).parent_path());
CudaApi cuda(args.cuda_dll); CudaApi cuda(args.cuda_dll);
cuda.check(cuda.cuInit(0), "cuInit"); cuda.check(cuda.cuInit(0), "cuInit");
@@ -124,7 +124,7 @@ int main(int argc, char** argv)
cuda.check(cuda.cuCtxSynchronize(), "cuCtxSynchronize"); cuda.check(cuda.cuCtxSynchronize(), "cuCtxSynchronize");
cuda.check(cuda.cuCtxSetCurrent(nullptr), "cuCtxSetCurrent(NULL)"); cuda.check(cuda.cuCtxSetCurrent(nullptr), "cuCtxSetCurrent(NULL)");
cuda.check(cuda.cuDevicePrimaryCtxRelease_v2(device), "cuDevicePrimaryCtxRelease_v2"); context = nullptr; cuda.check(cuda.cuDevicePrimaryCtxRelease_v2(device), "cuDevicePrimaryCtxRelease_v2"); context = nullptr;
std::printf("PASS NGX_INIT architecture=gfx1201 sr_available=1 transformer_validation=pending\n"); std::printf("PASS NGX_INIT architecture=%s sr_available=1 transformer_validation=pending\n", d4r::diag::HipApi::target_arch());
return 0; return 0;
} catch (const std::exception& e) { } catch (const std::exception& e) {
std::fprintf(stderr, "FAIL NGX_INIT %s\n", e.what()); std::fprintf(stderr, "FAIL NGX_INIT %s\n", e.what());
+3 -3
View File
@@ -42,7 +42,7 @@ inline std::filesystem::path pixel_module_path() {
reinterpret_cast<LPCWSTR>(&pixel_module_path), &module)) throw std::runtime_error("Locate GPU conversion module directory"); reinterpret_cast<LPCWSTR>(&pixel_module_path), &module)) throw std::runtime_error("Locate GPU conversion module directory");
wchar_t path[32768]{}; const DWORD length = GetModuleFileNameW(module, path, 32768); wchar_t path[32768]{}; const DWORD length = GetModuleFileNameW(module, path, 32768);
if (!length || length == 32768) throw std::runtime_error("GPU conversion module path is invalid"); if (!length || length == 32768) throw std::runtime_error("GPU conversion module path is invalid");
return std::filesystem::path(path).parent_path() / L"pixel_convert_gfx1201.hsaco"; return std::filesystem::path(path).parent_path() / diag::wide(std::string("pixel_convert_") + diag::HipApi::target_arch() + ".hsaco");
} }
struct Runtime { struct Runtime {
@@ -94,7 +94,7 @@ 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_gfx1201(-1, props); hip.select_architecture(-1, props);
hip.verbose = cuda.verbose = !std::getenv("D4R_QUIET_API"); hip.verbose = cuda.verbose = !std::getenv("D4R_QUIET_API");
const auto luid = adapter_luid(d3d); const auto luid = adapter_luid(d3d);
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");
@@ -155,7 +155,7 @@ struct Runtime {
ngx_check(destroy(caps), "Destroy capability parameters"); ngx_check(destroy(caps), "Destroy capability parameters");
if (available != 1 || initResult != 1 || needsDriver != 0) if (available != 1 || initResult != 1 || needsDriver != 0)
throw std::runtime_error("CUDA DLSS is unavailable after capability initialization"); throw std::runtime_error("CUDA DLSS is unavailable after capability initialization");
std::printf("D4R_RUNTIME platform=Windows architecture=gfx1201 cpu_frame_copies=0 frame_age=0\n"); std::printf("D4R_RUNTIME platform=Windows architecture=%s cpu_frame_copies=0 frame_age=0\n", d4r::diag::HipApi::target_arch());
} catch (...) { cleanup(); throw; } } catch (...) { cleanup(); throw; }
} }
Runtime(const Runtime&) = delete; Runtime(const Runtime&) = delete;
+3 -3
View File
@@ -27,11 +27,11 @@ int __cdecl initialize()
const char* root = std::getenv("HIP_PATH"); const char* root = std::getenv("HIP_PATH");
if (!root) return -5; if (!root) return -5;
auto runtime = std::make_unique<d4r::diag::HipApi>(root); auto runtime = std::make_unique<d4r::diag::HipApi>(root);
device_ordinal = runtime->select_gfx1201(-1, properties); device_ordinal = runtime->select_architecture(-1, properties);
hip = std::move(runtime); hip = std::move(runtime);
runtime_ready.store(true, std::memory_order_release); runtime_ready.store(true, std::memory_order_release);
} }
std::printf("NVAPI_COMPAT initialize physical=gfx1201 CUDA_model_profile=AD100\n"); std::printf("NVAPI_COMPAT initialize physical=%s CUDA_model_profile=AD100\n", properties.gcnArchName);
return 0; return 0;
} catch (const std::exception& e) { std::fprintf(stderr, "NVAPI_COMPAT init failed: %s\n", e.what()); return -1; } } catch (const std::exception& e) { std::fprintf(stderr, "NVAPI_COMPAT init failed: %s\n", e.what()); return -1; }
} }
@@ -48,7 +48,7 @@ int __cdecl architecture(void* handle, ArchInfo* info)
if (!valid(handle) || !info) return -5; if (!valid(handle) || !info) return -5;
if (info->version != (sizeof(ArchInfo) | 1u << 16) && info->version != (sizeof(ArchInfo) | 2u << 16)) return -9; if (info->version != (sizeof(ArchInfo) | 1u << 16) && info->version != (sizeof(ArchInfo) | 2u << 16)) return -9;
info->architecture = 0x190; info->implementation = 2; info->revision = 0x11; info->architecture = 0x190; info->implementation = 2; info->revision = 0x11;
std::printf("NVAPI_COMPAT GetArchInfo profile=AD102 physical=gfx1201\n"); std::printf("NVAPI_COMPAT GetArchInfo profile=AD102 physical=%s\n", properties.gcnArchName);
return 0; return 0;
} }
int __cdecl adapter_id(void* handle, void* luid) int __cdecl adapter_id(void* handle, void* luid)
+1
View File
@@ -58,6 +58,7 @@ class PixelProgram {
public: public:
PixelProgram(diag::HipApi& hip, const std::filesystem::path& module) : hip_(hip) { PixelProgram(diag::HipApi& hip, const std::filesystem::path& module) : hip_(hip) {
try { try {
diag::require_code_object_target(module, diag::HipApi::target_arch());
hip.check(hip.hipModuleLoad(&module_, diag::utf8(module.c_str()).c_str()), "Load native GPU format conversion"); hip.check(hip.hipModuleLoad(&module_, diag::utf8(module.c_str()).c_str()), "Load native GPU format conversion");
hip.check(hip.hipModuleGetFunction(&decode_, module_, "d4r_pixel_decode"), "Resolve GPU pixel decode"); hip.check(hip.hipModuleGetFunction(&decode_, module_, "d4r_pixel_decode"), "Resolve GPU pixel decode");
hip.check(hip.hipModuleGetFunction(&encode_, module_, "d4r_pixel_encode"), "Resolve GPU pixel encode"); hip.check(hip.hipModuleGetFunction(&encode_, module_, "d4r_pixel_encode"), "Resolve GPU pixel encode");