diff --git a/.gitignore b/.gitignore index c676d27..0d8033a 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ __pycache__/ .venv/ .tools/ /external/MinHook/ +/external/ZLUDA/ .vscode/ /windows/m11/build/ /windows/m11/.tools/ diff --git a/CMakeLists.txt b/CMakeLists.txt index f9fb96a..41130d2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,11 @@ if(NOT WIN32 OR NOT CMAKE_SIZEOF_VOID_P EQUAL 8) endif() set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) +add_executable(d4r_fsr_rr_probe EXCLUDE_FROM_ALL tools/fsr_rr_probe.cpp) +target_link_libraries(d4r_fsr_rr_probe PRIVATE d3d12 dxgi dxguid) +if(MINGW) + target_link_options(d4r_fsr_rr_probe PRIVATE -municode -static) +endif() set(D4R_HIP_ROOT "$ENV{HIP_PATH}" CACHE PATH "One stable HIP SDK or TheRock installation") if(NOT D4R_HIP_ROOT AND EXISTS "C:/Program Files/AMD/ROCm/7.2") set(D4R_HIP_ROOT "C:/Program Files/AMD/ROCm/7.2") @@ -121,11 +126,20 @@ if(D4R_BUILD_NATIVE_ENGINE) add_library(d4r_volk STATIC "${D4R_VOLK_ROOT}/volk.c") target_include_directories(d4r_volk PUBLIC "${D4R_VOLK_ROOT}" "${D4R_VULKAN_HEADERS_ROOT}/include") target_compile_definitions(d4r_volk PUBLIC VK_NO_PROTOTYPES) + add_executable(d4r_rr_interop_capabilities EXCLUDE_FROM_ALL tools/windows/rr_interop_capabilities.cpp) + target_link_libraries(d4r_rr_interop_capabilities PRIVATE d4r_volk d3d12 dxgi dxguid) + add_executable(d4r_rr_interop_probe EXCLUDE_FROM_ALL tools/windows/rr_interop_probe.cpp) + target_link_libraries(d4r_rr_interop_probe PRIVATE d4r_volk d3d12 dxgi dxguid) + if(MINGW) + target_link_options(d4r_rr_interop_capabilities PRIVATE -static) + target_link_options(d4r_rr_interop_probe PRIVATE -static) + endif() add_library(d4r_engine STATIC engine/runtime.cpp engine/game.cpp engine/game_m.cpp engine/game_rr.cpp) target_include_directories(d4r_engine PUBLIC "${D4R_VULKAN_HEADERS_ROOT}/include") target_compile_definitions(d4r_engine PUBLIC VK_NO_PROTOTYPES) target_precompile_headers(d4r_engine PRIVATE engine/volk_pch.h) target_link_libraries(d4r_engine PUBLIC d4r_volk) + target_link_libraries(d4r_rr_interop_probe PRIVATE d4r_engine) foreach(runner IN ITEMS k m rr) if(runner STREQUAL "k") set(runner_source engine/replay.cpp) @@ -187,6 +201,11 @@ set_target_properties(d4r_nvngx_windows PROPERTIES PREFIX "" OUTPUT_NAME "d4r_nv target_compile_definitions(d4r_nvngx_windows PRIVATE WIN32_LEAN_AND_MEAN NOMINMAX __HIP_PLATFORM_AMD__) target_include_directories(d4r_nvngx_windows PRIVATE "${D4R_HIP_ROOT}/include") target_link_libraries(d4r_nvngx_windows PRIVATE version dbghelp d3d12 dxguid minhook bcrypt) +if(TARGET d4r_engine) + target_sources(d4r_nvngx_windows PRIVATE tools/windows/rr_native_backend.cpp) + target_link_libraries(d4r_nvngx_windows PRIVATE d4r_engine) + target_compile_definitions(d4r_nvngx_windows PRIVATE D4R_NATIVE_RR_BACKEND=1) +endif() install(FILES "${D4R_MINHOOK_ROOT}/LICENSE.txt" DESTINATION licenses RENAME MinHook.txt) if(MINGW) target_link_options(d4r_nvngx_windows PRIVATE -static) @@ -195,6 +214,13 @@ install(TARGETS d4r_nvngx_windows RUNTIME DESTINATION bin) # Target-independent _nvngx.dll of drag-in releases: loads _nvngx_.dll # for the game's actual HIP architecture. Its own D4R_TARGET_ARCH is unused. add_library(d4r_nvngx_loader SHARED tools/windows/d4r_nvngx_loader.cpp) +add_executable(d4r_player_config_probe EXCLUDE_FROM_ALL tools/windows/player_config_probe.cpp) +target_include_directories(d4r_player_config_probe PRIVATE "${D4R_HIP_ROOT}/include") +target_compile_definitions(d4r_player_config_probe PRIVATE __HIP_PLATFORM_AMD__) +target_link_libraries(d4r_player_config_probe PRIVATE version dbghelp bcrypt) +if(MINGW) + target_link_options(d4r_player_config_probe PRIVATE -municode -static) +endif() set_target_properties(d4r_nvngx_loader PROPERTIES PREFIX "" OUTPUT_NAME "d4r_nvngx_loader") target_compile_definitions(d4r_nvngx_loader PRIVATE WIN32_LEAN_AND_MEAN NOMINMAX __HIP_PLATFORM_AMD__) target_include_directories(d4r_nvngx_loader PRIVATE "${D4R_HIP_ROOT}/include") @@ -219,6 +245,26 @@ else() target_sources(d4r_d3d12_dlss_probe PRIVATE "${ngx_parameter_object}" tools/d4r_ngx_param_host.cpp) target_sources(d4r_nvngx_windows PRIVATE "${ngx_parameter_object}" tools/d4r_ngx_param_host.cpp) endif() +if(TARGET d4r_engine) + add_executable(d4r_rr_ngx_probe EXCLUDE_FROM_ALL tools/windows/rr_ngx_probe.cpp tools/d4r_ngx_param_host.cpp) + target_include_directories(d4r_rr_ngx_probe PRIVATE "${D4R_HIP_ROOT}/include") + target_compile_definitions(d4r_rr_ngx_probe PRIVATE __HIP_PLATFORM_AMD__) + target_link_libraries(d4r_rr_ngx_probe PRIVATE d4r_engine d3d12 dxgi dxguid) + if(MSVC) + target_sources(d4r_rr_ngx_probe PRIVATE tools/d4r_ngx_param_msvc.cpp) + else() + target_sources(d4r_rr_ngx_probe PRIVATE "${ngx_parameter_object}") + target_link_options(d4r_rr_ngx_probe PRIVATE -static) + endif() + add_executable(d4r_rr_snapshot_probe EXCLUDE_FROM_ALL tools/windows/rr_snapshot_probe.cpp tools/d4r_ngx_param_host.cpp) + target_link_libraries(d4r_rr_snapshot_probe PRIVATE d4r_engine) + if(MSVC) + target_sources(d4r_rr_snapshot_probe PRIVATE tools/d4r_ngx_param_msvc.cpp) + else() + target_sources(d4r_rr_snapshot_probe PRIVATE "${ngx_parameter_object}") + target_link_options(d4r_rr_snapshot_probe PRIVATE -static) + endif() +endif() add_library(d4r_nvapi_trace SHARED tools/windows/nvapi_trace.cpp) set_target_properties(d4r_nvapi_trace PROPERTIES PREFIX "" OUTPUT_NAME "nvapi64" ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/nvapi-trace" diff --git a/docs/windows-fsr-rr.md b/docs/windows-fsr-rr.md new file mode 100644 index 0000000..71c31d9 --- /dev/null +++ b/docs/windows-fsr-rr.md @@ -0,0 +1,46 @@ +# Native Windows FSR Ray Regeneration investigation + +The native D3D12 provider check currently fails on RX 7700 XT. This does not +implement a working Windows FSR RR backend or DLSS RR replacement. + +AMD SDK 2.3's unmodified denoiser 1.2.0.2740 loads successfully and accepts the +provider query, but returns an empty provider list. The installed driver reports +shader model 6.6. No context creation or denoiser dispatch follows this result. +The DLL's Authenticode signature was valid, signed by Advanced Micro Devices; +its SHA256 matches the Linux reference's tested binary: +`48f1e5888ba6a0a3d59a98b9751e37c392b0f7b8c223d0082d5c1f40642879d3`. + +Linux's RDNA3 route uses vkd3d-proton, dxil-spirv scalar FP8 emulation, and +`wmma_rdna3_workaround`. Those are not native Windows driver features. Native +parity requires a compatible shader execution route as well as the DLSS guide +conversion and internal SR adapter. Merely importing the Linux backend or +selecting `Backend=fsr` would not supply those pieces. + +## Reproduce without a game + +```powershell +./scripts/windows/setup-fsr-rr.ps1 +cmake --build build/native-engine-windows-gfx1101 --target d4r_fsr_rr_probe +./scripts/windows/test-fsr-rr.ps1 ` + -Probe build/native-engine-windows-gfx1101/d4r_fsr_rr_probe.exe ` + -DenoiserDll .tools/fsr-rr-1.2/amd_fidelityfx_denoiser_dx12.dll ` + -OutputDirectory build/fsr-rr-new-query -QueryOnly +``` + +Use a new output folder under ignored `build/`. The wrapper pins the DLL hash, +captures stdout/stderr, limits execution to 120 seconds, and propagates failure. +Without `-QueryOnly`, the harness proceeds only if a provider exists: it measures +48 synthetic frames with static/moving cameras and a reset against noise-free +signals. A successful query alone is not execution or image-quality evidence. +The Windows adapter helper queries the device's DXGI identity. It does not load +Proton driver shims or modify drivers, GPU settings, or security policy. + +## Source provenance + +`tools/fsr_rr_probe.cpp`, `tools/fsr_rr_scene.h`, `tools/d4r_fsr_rr.h`, and the +MIT-licensed FidelityFX API headers were imported from Linux reference +`34e6b0fe71d770729000a553f79b784e9b2dc279`. The probe includes the native Windows +identity helper instead of Linux's sysfs/vkd3d identity helper. AMD's DLL stays +under ignored `.tools/` and is not included in source or release packages. + +Evidence: `build/fsr-rr-native-wrapper-query/probe.json`. No game was touched. diff --git a/docs/windows-k-performance.md b/docs/windows-k-performance.md new file mode 100644 index 0000000..7acd2a4 --- /dev/null +++ b/docs/windows-k-performance.md @@ -0,0 +1,180 @@ +# Windows K performance work + +Linux's reported 1.5 ms at 1080p and 2.47 ms at 1440p remain targets, not verified +Windows results. The synthetic measurements below include CPU synchronization, +format/array copies and NGX execution. They are not directly comparable to a +GPU network-only timer or a game's frame time. + +## Reproducible interop comparison + +`tools/windows/benchmark_k_interop.py` uses an existing private gfx1101 runtime +and the native D3D12 harness. It runs control/batch/batch/control, with 16 frames +per run and the first four excluded from timing. Every frame is read back; +candidate output hashes must match the control frame for frame. The harness +also rejects nonfinite or uniform outputs. No game is launched or modified. + +Use the current installer core, not an older isolated NGX fixture: + +```powershell +python tools/windows/benchmark_k_interop.py ` + --probe build/windows-rdna4-therock-gfx1101/d4r_d3d12_dlss_probe.exe ` + --shim build/windows-rdna4-therock-gfx1101/d4r_nvngx.dll ` + --runtime build/got-k-test/work/package-gfx1101-current/d4r ` + --core build/driver-617.14-core-check/_nvngx.dll ` + --dlss build/got-k-test/isolated-sr/sr/nvngx_dlss.dll ` + --output build/k-new-benchmark --resolution 2560x1440 +``` + +Paths above identify local ignored artifacts; provision matching artifacts on +another machine. The runtime argument supplies HIP, ZLUDA, NVAPI, the gfx1101 +pixel converter and native K objects. Output must be a new folder under +`build/`. Each process has a 180-second limit. Reports retain executable/DLL +hashes and native object hashes. `--profile-stages` adds CPU stage diagnostics; +its timings include logging overhead and must be reported separately. + +The harness otherwise defaults to half-resolution input. This runner explicitly +sets nominal Quality input: 1280x720 for 1920x1080 output; 1706x960 for 2560x1440. +Games can round the render width differently (GoT used 1712 at 1440p). + +## Evidence, RX 7700 XT, 2026-10-16 + +The 617.14 core SHA256 is +`66767018c36b3bab46398dade3adf173daa3730fda75965689ea848c9bc4e79b`; +SR 310.9.1 matches the installer pin. Native K encoders are reported loaded in +the captured stderr. Baseline RGBA16F inputs/output need no format conversion. + +At 1706x960 to 2560x1440, pooled warmed CPU interop medians were 5.2615 ms +control and 5.0800 ms batch. All 64 frame outputs passed and matched exactly +between modes. Evidence: `build/k-interop-batch-quality-1440-core617/summary.json`. +At 1280x720 to 1920x1080, the same check passed all 64 frames; pooled warmed +medians were 3.5730 ms control and 3.3820 ms batch. Evidence: +`build/k-interop-batch-quality-1080-core617/summary.json`. +These short runs suggest only a small batching benefit; defaults remain unchanged. +This does not establish image quality on realistic ray-traced/game content. + +Earlier investigation runs used core 596.36 or stage profiling. Their artifacts +are retained separately and are not the current-core baseline. Batched input +copies alone do not establish Linux speed parity. Next optimization needs paired +GPU kernel timings and an exact-output comparison, particularly for the native +gfx11 kernels' Windows lane-exchange workaround and the translated texture stages. + +## Kernel experiments and GPU profile + +The experiment builder now accepts an explicit gfx11/gfx12 target. gfx11 keeps +its Windows LDS lane-exchange workaround and strict FP16 accumulation. Gfx12-only +tiling/storage experiments are rejected on gfx11. Compiler arguments, target, +object hash and ISA remain in the experiment output directory. + +`benchmark_k_interop.py --candidate-native DIR` compares an experimental native +folder against the existing runtime, using identical interop settings. Candidate +runs must match every output file before their timing is accepted. No candidate +is installed into the existing runtime or a game. + +A strict enc1 `ds_bpermute` replacement failed exact temporal output comparison: +eight of 16 frames differed, maximum absolute difference 0.00048828125. The fresh +LDS control passed the same comparison. The DS source experiment was removed; +its local artifacts remain under `build/k-bpermute-strict-enc1-quality-1080/`. +Earlier non-strict experiments omitted `D4R_K_FP16_BASELINE` and cannot isolate +shuffle behavior. The DS builtin also folded to `v_permlanex16`; explicit assembly +was needed to test an actual DS instruction. + +Enc1 WGP mode passed all 64 frame comparisons but showed no reliable speed gain: +control/candidate pooled warmed CPU interop medians 3.5455 / 3.5865 ms. No default +or package change. Evidence: `build/k-enc1-wgp-quality-1080/summary.json`. + +`--profile-kernels` enables deferred GPU events with legacy-stream profiling +explicitly allowed for this synthetic diagnostic. This changes stream dependencies +and substantially raises CPU interop time; do not compare its wall times with the +uninstrumented baseline. In the first control run, the last-four-sample GPU medians +were approximately: + +| Stage | GPU ms | +|---|---:| +| translated output `hiluma_engine_output_depthreg_mvhi_ldr_max_v2_rel` | 0.820 | +| native dec0 | 0.301 | +| native enc0 | 0.293 | +| native dec1 | 0.261 | +| native enc1 | 0.213 | + +All 32 instrumented frames passed exact output checks across control/candidate. +Raw logs and per-run stage analysis are in +`build/k-enc1-wgp-gpu-profile-1080/gpu-stage-analysis.json`. These are instrumented +stage measurements, not an uninstrumented total. The translated output pass is +the largest measured stage and is the next optimization target. The existing +private texture recipe needs `d4r_emit.exe`, which is absent from the current +workspace's tool/runtime/build directories. No Linux speed parity is claimed. + +## Offline emitter provisioning + +The dependency checkout is now local under ignored `external/ZLUDA`, pinned to +`ee2f25a180099fa42f36b2346732e1f2470a03ad` with this repository's Windows patches. +LLVM is pinned to `ff4dc1f7c9e1c64d4d69e40f4ed30c2280a96dfd` plus the audited +gfx1154 backport. Rust 1.98.1 and locked Cargo dependencies are provisioned locally. +All four PTX helper variants built with TheRock's compiler. They have not yet +been linked or exercised by the emitter. LLVM library compilation is in progress. + +After the LLVM build succeeds, run: + +```powershell +./scripts/windows/build-zluda-windows.ps1 -EmitterOnly +./scripts/windows/build-native-texture.ps1 ` + -DlssDll build/got-k-test/isolated-sr/sr/nvngx_dlss.dll ` + -Kernel hiluma_engine_output_depthreg_mvhi_ldr_max_v2_rel ` + -HipRoot .tools/therock-10.2.0a20260929/_rocm_sdk_core ` + -ZludaRoot dist/zluda-windows-emitter -GpuArch gfx1101 ` + -OutputDirectory build/private-k-output-gfx1101 +``` + +Emitter-only mode does not build or replace `nvcuda.dll`, NVAPI, or the tracing +runtime. It writes the offline emitter and its local C++ DLL dependencies to a +separate directory. The texture recipe resolves compiler tools from either the +TheRock `lib/llvm/bin` layout or the HIP SDK `bin` layout; derived output must +stay under ignored `build/`. Each extraction/compile operation has a 600-second +limit. Output overrides remain unvalidated until full-frame comparison passes. + +## K native output override validated (2026-10-16) + +LLVM completed all 2,322 library build steps. The offline emitter now builds and +passes three gfx1101 compile fixtures (pattern, f16 reference MMA, f16 WMMA). +The validated CUDA/NVAPI runtime was not rebuilt or replaced. + +Two build compatibility fixes were required for TheRock's LLVM 24 frontend: + +- Remove stale ThinLTO summaries after stripping unused HIP/LLVM globals. +- Assemble helper IR with the pinned LLVM 22 assembler. A small compatibility + pass preserves float bit patterns, translates the dynamic denormal attribute + to LLVM 22's equivalent, and drops optimization promises the older reader + cannot express. It does not enable relaxed math. Five tests cover finite float + widening across exponent boundaries, NaN payloads, half constants, double/string + preservation and conservative attribute handling. End-to-end exact output + checks below are the runtime gate. + +The private native store override for +`hiluma_engine_output_depthreg_mvhi_ldr_max_v2_rel` built for gfx1101. The PTX recipe +replaced 13 formatted stores, four b32 stores and eight round-to-zero stores. +The runtime log confirms the new native output module is loaded. + +Paired control/candidate/control-order measurements (control, candidate, +candidate, control), 16 frames per run, first four excluded: + +| Nominal Quality geometry | Control CPU interop ms | Candidate CPU interop ms | +|---|---:|---:| +| 1280x720 to 1920x1080 | 3.791 | 3.440 | +| 1706x960 to 2560x1440 | 5.318 | 4.744 | + +All 128 frame outputs were finite/nonuniform and matched control bytes exactly. +These CPU measurements include synchronization and copies; they do not establish +Linux GPU-time parity or game speed. No game was accessed. + +A separate deferred-event diagnostic passed 32 additional exact frame checks. +The output-stage GPU medians were 0.812/0.815 ms in the two controls and +0.535/0.532 ms in the two candidates. Legacy-stream events add dependencies; +these instrumented stage measurements are not uninstrumented frame totals. + +Private artifacts: `build/private-k-output-gfx1101/` and combined +`build/k-output-native-gfx1101/`. Evidence: +`build/k-output-native-quality-{1080,1440}/summary.json` and +`build/k-output-native-gpu-profile-1080/output-stage-analysis.json`. +The override derives from the user's NVIDIA DLL and remains under ignored build/; +it is not included in the previously delivered local ZIP. Other K input/output +variants, game performance and automatic local override generation remain open. diff --git a/docs/windows-local-package.md b/docs/windows-local-package.md new file mode 100644 index 0000000..9ec13f1 --- /dev/null +++ b/docs/windows-local-package.md @@ -0,0 +1,98 @@ +# Local gfx1101 drop-in package + +## Current local development package: v4 + +`build/d4r-windows-gfx1101-local-v4.zip` is 90,720,715 bytes; SHA256 +`74fbb4c78dba3e616b9bbba7dc1fe4cddf0a17855968b174f8ea69968d873dfc`. +It refreshes the verified v3 package with the current native-RR shim, player INI, +README, checker and installer sources. Every manifest file hash verifies against +the final ZIP. Exact local modified-build provenance and base ZIP hash are +recorded; no clean source commit is asserted. Existing ZIPs remain unchanged. + +The package contains no NVIDIA binaries, private optimized kernels, or RR +models. RR defaults off. A locally generated D/E model can be selected through +`[RayReconstruction] Backend = native` and `ModelDir` in d4r.ini. Auto selects +`d4r/engine/rr-d`; relative paths resolve beside d4r.ini. The installer does not +generate that model yet, and FSR RR remains unavailable. This is a gfx1101-only +development package with synthetic RR coverage, not verified game RR support. + +The refreshed target shim passed six exact RR hardware-depth frames through the +packaged architecture loader using player INI selection without launcher path +overrides. The staged test supplied the pinned SR/core dependencies separately +and used a separate local RR model. It covered capability/negative contracts, +optional guides, enhanced/inherited state, inverted D32S8, unchanged stencil and +Release-before-submit. Evidence: `build/rr-ngx-local-v4-loader-v1/summary.json`. +ZIP verification: `build/d4r-windows-gfx1101-local-v4.validation.json`. +The installer itself was not rerun for v4 under the current script policy; no +policy bypass or system change was used. No game was touched or release published. + +The refresh helper is `tools/windows/refresh_local_package.py`. It accepts only +the pinned verified v3 base and fresh destinations under ignored build/, verifies +every base/output manifest hash, and marks output as local modified provenance. + +## Preserved v3 package evidence + +Local development ZIP: `build/d4r-windows-gfx1101-local-v3.zip` (92,158,725 bytes). +This package targets gfx1101, including this machine's RX 7700 XT. It is not a +multi-GPU public release, and it does not implement Windows game RR or FSR RR. + +Extract its contents beside the game's main executable, then run `install.bat` +and accept the dependency download prompt. Start the game normally afterward. +The ZIP contains the shim, architecture loader, OptiScaler, native K/M objects, +HIP/ZLUDA runtime, configuration, installer and licenses. NVIDIA binaries are +excluded; the installer fetches pinned official SR/RR/core DLLs locally. It does +not install the NVIDIA driver. See the ZIP's `WINDOWS_README.txt` for placement +and existing-install handling. + +Validation completed without touching a game: + +- Every ZIP entry listed in the manifest matches its recorded SHA256. +- No NVIDIA SR, RR or core binary is bundled; `d4r/_nvngx.dll` is d4r's loader. +- Extracted the real ZIP into an ignored mock game folder and ran its installer + with the verified local download cache. All three installed DLL hashes match + the current pins. The installed checker passed on RX 7700 XT. +- The packaged architecture loader and target shim passed 32 synthetic K Quality + frames at 1280x720 to 1920x1080. Outputs were finite, nonuniform and identical + between control/batched-input runs. This is synthetic execution, not a game or + image-quality claim. +- V3 adds `NativeDir` configuration for locally generated complete native + directories. The exact new target shim passed eight additional synthetic + player-mode frames through the architecture loader at 256x144 to 512x288. + Its log confirms selection of the generated private K output override. + Checker fixtures pass 20/20; release package fixtures pass 6/6. + +The input package is explicitly marked as a local modified build. Its clean +binary source commit is not asserted; exact file hashes are authoritative. The +dependency commits are inherited from the earlier package's provenance. No +source commit or public upload was created. + +Evidence: `build/windows-drop-in-v3-validation.json` and +`build/player-private-native-output/validation.json`. Earlier package validation +remains in `build/windows-drop-in-validation.json`. + +ZIP SHA256: +`e93be288f4013616cc2229be0132b40395d5031d8733bfa63886ba75ce1389ca`. + +## Optional private K output optimization + +Generate a complete private directory in this source workspace: + +```powershell +./scripts/windows/prepare-k-native-cache.ps1 ` + -DlssDll build/got-k-test/isolated-sr/sr/nvngx_dlss.dll ` + -NativeDirectory build/got-k-test/work/package-gfx1101-current/d4r/native ` + -OutputDirectory build/my-private-k-cache +``` + +This uses the locally built emitter and TheRock compiler. It verifies the input +target and pinned DLL, builds the selected output variant, combines the baseline +K/M objects, regenerates the native manifest and records hashes. It never edits +a game or configuration. Select the complete `native` subfolder with `[Paths] +`NativeDir` in the new shim's `d4r.ini` after validation. Relative paths resolve +beside `d4r.ini`; `auto` uses packaged kernels. Missing or wrong-target private +objects are rejected. The default variant currently optimized is LDR, regular +depth and high-resolution motion vectors; other variants retain the normal path. + +The workflow output under `build/k-native-cache-workflow/native` is byte-identical +to the previously validated 17-object candidate. The new player-mode smoke loaded +that directory. These NVIDIA-derived objects stay local and are absent from V3. diff --git a/docs/windows-rr-interop.md b/docs/windows-rr-interop.md new file mode 100644 index 0000000..606a6fe --- /dev/null +++ b/docs/windows-rr-interop.md @@ -0,0 +1,450 @@ +# Native RR D3D12/Vulkan bridge gate + +## Runtime extraction in progress (2026-10-16) + +The packet layout now has a geometry-only constructor with no fixture I/O. +The model recorder also accepts an owned `RFrameSettings` value independently +of the replay frame list. Existing fixture entry points delegate to the same +packet-layout and recording code. This prepares the production integration +described below. + +`rr_native_device.h` now owns the shared LUID-matched Vulkan setup, compute queue +selection, and inference feature checks. `rr_native_packet.h` owns dedicated +D3D12 resource memory import and shared-fence timeline import. The existing +probe uses both owners instead of its inline setup. Imports retain Vulkan +references while the caller keeps ownership of exported Win32 handles. These +owners require retired submissions before destruction; the probe preserves its +existing quarantine behavior after an incomplete submission. + +`rr_ngx_snapshot.h` adds typed RR creation/frame snapshots, independently of the +SR parameter whitelists. It copies both 16-float matrices, creation presets and +scalar baselines, per-frame overrides, render extents and required-guide subrect +origins. COM references retain required and optional guide/output resources. +D/E packed roughness uses normals.w only when a separate roughness texture is +absent, matching the Linux reference. Missing matrices and invalid/nonfinite +settings are rejected. Feature-13 evaluation uses this snapshot. + +The CPU-only `d4r_rr_snapshot_probe` passes mutation, parameter-destruction, +creation-fallback, per-frame-override, and invalid-input checks with the real NGX +parameter implementation. It does not exercise GPU execution, COM resource +retirement, command-list ordering, Create/Evaluate/Release, or game integration. +This separate CPU test did not retry the policy-blocked GPU regression wrapper. + +`rr_native_backend.cpp` now compiles into the Windows shim when the native engine +is available. It borrows the supplied D3D12 device/queue and actual input/output +textures, packs required guides on the GPU, records the existing model engine, +and copies output back on the GPU. It restores legacy/enhanced resource access, +supports bounded subrect copies in canonical formats, verifies device ownership +and preset selection, and retains all snapshot resources until both APIs finish. +Completion waits are bounded; a failed in-flight backend quarantines its full +ownership graph instead of freeing live GPU resources. Recording errors poison +history/upload state and require feature recreation. + +The backend rejects unresolved/split states, unsupported formats/encodings, +optional guides/exposure textures, non-unit exposure scale, unsupported creation +flags, aliased input/output, and dynamic render extents. These paths still need +implementation for broad game support. Global Volk dispatch is serialized and +reloaded for each backend operation. + +The shim now routes feature-13 Create/Evaluate/Release to the native backend +when `D4R_RR_BACKEND=native` and absolute `D4R_RR_MODEL_DIR` are configured. +Required-guide access is captured at Evaluate, inherited access is resolved at +submission, and the callback retains the feature and owned snapshot. Capability +and feature-requirement queries load-check the actual model, Vulkan adapter +features, and packet/fence import; they do not claim image-quality validation. +Default configurations continue to report RR unavailable. SR routing remains +separate. Native RR Init now defers the independent CUDA SR runtime, as described +in the independent-initialization evidence below. + +`d4r_rr_ngx_probe` and `tools/windows/test_rr_ngx.py` add a bounded, synthetic +NGX lifecycle gate using fixture textures and same-engine reference images. +The gate mutates matrices/scalars after Evaluate and releases the last feature, +parameters, and fixture texture ownership before submission. It does not touch +a game or retry the policy-blocked interop executable/wrapper. Initial attempts +stopped before RR creation because of an invalid legacy application ID and a +missing `HIP_PATH`; those failed artifacts remain separate. + +The actual native RX 7700 XT feature-13 gate now passes all six 64x64 to +128x128 camera/jitter/exposure/reset frames, byte-identical to standalone replay. +Every output is finite and nonuniform. The test includes parameter mutation +after Evaluate and feature/parameter/fixture-ownership release before the final +submission. Prefix guide uploads and suffix output readback exercise logical +command-list ordering through the real shim. Independent output-byte checks +also pass in the wrapper. Evidence: `build/rr-ngx-camera-reset-v3/summary.json`, +stdout/stderr and frame files. This is synthetic lifecycle/bridge consistency +against the same RR engine, not a game or NVIDIA quality reference. Additional +contract and inherited-state checks are recorded in the next section. + +## Additional NGX contract and inherited-state validation (2026-10-16) + +Unsupported frame contracts now fail synchronously during Evaluate, before a +logical command-list boundary is recorded. Submission revalidates the textures +and resolved states. This prevents unsupported guides/encodings/extents from +being reported as a successful Evaluate that fails only during submission. + +The real-shim contract run verifies configured RR availability/init success, +preserved SR availability, feature-13 requirements on the actual adapter, WARP +rejection, unknown feature rejection, and eight creation/evaluation failures. +Those failures cover an unknown feature ID, zero creation width, missing matrix, +unsupported optional hit distance, dynamic render width, unsupported encoding, +out-of-bounds subrect, and an invalid/aliased output. All six valid camera/reset +frames still match standalone bytes after these rejected calls. +Evidence: `build/rr-ngx-contracts-camera-reset-v1/summary.json` and logs. + +The harness can also omit all caller state overrides and upload guides in a +separate preceding list within the same ExecuteCommandLists batch. The NGX +list must resolve those inherited states at its delayed callback. That mode +passes six camera/reset frames at 64x64 to 128x128 and two full-size frames at +853x480 to 2560x1440, including the existing mutation/release-before-submit +checks. Every output remains finite/nonuniform and byte-identical to standalone. +Evidence: `build/rr-ngx-inherited-camera-reset-v1/summary.json` and +`build/rr-ngx-inherited-1440-v1/summary.json`. Enable the new gates with +`tools/windows/test_rr_ngx.py --contracts` or `--inherited`, alongside the +required explicit artifact/input/output arguments shown by `--help`. + +These are synthetic native feature-13 contract/ordering results. The following +section adds enhanced access, legacy split rejection, and unavailable-backend +checks. Stale-but-loadable models, concurrency, optional guides, format conversion, +FSR RR, game integration, quality and performance parity remain open. No +additional SR presets or game content were tested. + +## Enhanced access, split rejection, and unavailable configurations (2026-10-16) + +`--enhanced --inherited` now validates feature-13 transfers when a preceding +list establishes enhanced shader-resource/UAV access and the NGX list has no +caller state overrides. Fixture transitions cross COMMON when switching +between legacy and enhanced barriers, as required by the +[Microsoft enhanced-barrier specification](https://microsoft.github.io/DirectX-Specs/d3d/D3D12EnhancedBarriers.html). +The backend restores enhanced access before suffix readback/fixture reuse. All +six camera/reset frames match standalone bytes and remain finite/nonuniform. +Evidence: `build/rr-ngx-enhanced-inherited-camera-reset-v1/summary.json`. + +`--split` records a legacy BEGIN_ONLY transition, confirms Evaluate rejects +the unfinished split, completes the matching END_ONLY transition, and then +runs the normal feature-13 evaluation. The subsequent six camera/reset frames +still match standalone exactly. Evidence: +`build/rr-ngx-split-camera-reset-v1/summary.json`. This tests legacy split +rejection, not enhanced split rejection. No debug-layer validation is claimed. + +`--unavailable disabled`, `--unavailable missing-model`, and +`--unavailable fsr` separately verify requirements stay unsupported, RR capability +availability stays zero with a failure init result, and feature-13 creation +fails with a null output handle. SR availability remains one in every case. +These runs dispatch no RR frames. Evidence is under +`build/rr-ngx-unavailable-{disabled,missing-model,fsr}-v1/summary.json`. +The FSR case proves honest rejection of the unavailable backend; it is not +FSR execution or provider support. + +Native RR optional-guide/format conversion, dynamic geometry, +concurrent lifecycle, game integration, quality and performance +parity remain incomplete. The original full parity goal remains open. + +## Independent native RR initialization (2026-10-16) + +With an explicitly selected native RR backend, Init retains the borrowed D3D12 +device and an owned initialization contract without loading HIP, CUDA, NVAPI, +NVIDIA SR/core DLLs or the SR pixel converter. Required SR capability/feature +requests initialize the separate SR runtime on demand. A missing SR dependency +reports SR unavailable without hiding a ready native RR backend. Default +configurations retain eager SR initialization. Shutdown releases both paths. + +`RuntimeInitialization` owns the application data directory, project identity, +path strings, and path-list descriptor used by deferred SR startup. The harness +mutates those caller strings/descriptors after Init; subsequent SR capability +initialization still logs the original project/version and path. Both RR/SR +capabilities are available, negative contract checks pass, and all six inherited +camera/reset frames remain byte-identical to standalone. +Evidence: `build/rr-ngx-deferred-sr-init-v1/summary.json` and logs. + +The `--contracts --without-sr --enhanced --inherited` gate removes all SR +dependency path configuration and does not add runtime directories to PATH. +It verifies RR requirements/capability readiness, SR unavailability, negative +contracts, and six exact native RR camera/reset frames. No SR runtime initializes. +Evidence: `build/rr-ngx-independent-camera-reset-v1/summary.json` and logs. +This proves native RR execution independent of configured SR dependencies; +it does not change the package's model provisioning or broader game support. + +The default eager SR path still passes capability/readiness validation with RR +disabled: `build/rr-ngx-eager-sr-regression-v1/summary.json`. These checks add no +new SR-preset or game execution claim. + +## Native sampled guide formats (2026-10-16) + +The production packet now reserves each guide's maximum supported texel size, +so format changes do not recreate shared memory, the RR model, or temporal +history. The Vulkan replay caches sampled-image views by plane/format and keeps +old views alive for the engine's cached descriptors. New image variants receive +their own first-use layout transition. Production transfers still stay on GPU. +The larger reserved packet is a memory tradeoff, not a performance improvement. + +The backend maps float16/float32 RGBA and UNORM RGBA8/RGB10A2 color/guide inputs, +float16/float32 two-channel motion, float16/float32 scalar depth, and scalar +float16/float32/UNORM8 roughness where applicable. Vulkan sampled/transfer support +is checked when creating a view. Unsupported encodings, typeless/depth-stencil +formats and optional guides remain rejected; output remains RGBA16F. Mapping a +format does not establish game-specific guide encoding or quality correctness. + +Synthetic evidence tests RGBA32F color/normals, RG32F motion and R16F roughness, +with values exactly equivalent to the canonical fixtures. All six camera/reset +frames match standalone output bytes, including enhanced/inherited access, +negative contracts and independent SR initialization. A second run alternates +canonical and float guide formats each frame without feature recreation; all +six outputs remain exact. CPU conversions initialize fixture inputs only. +Evidence: `build/rr-ngx-float-guides-camera-reset-v1/summary.json` and +`build/rr-ngx-switch-guides-camera-reset-v1/summary.json`. +The unchanged canonical baseline also passes six frames: +`build/rr-ngx-format-layout-baseline-v1/summary.json`. + +Other mapped formats have not received format-specific execution coverage. +Dynamic render extents remain rejected, as in the cited Linux reference's RR +adapter. Optional guides, output conversion, broader game formats/encodings, +concurrency, game integration, FSR RR and performance parity remain unfinished. + +## Corrected RR creation-flag contract (2026-10-16) + +Inspection found that the initial Windows gate accepted flagless synthetic RR +and rejected the actual HDR/render-motion flags. The production backend now +matches the Linux RR adapter: HDR and render-resolution, unjittered motion +vectors are required. Inverted depth remains supported. AutoExposure is accepted +because the D/E engine already performs its exposure reduction. Jittered motion, +high-resolution motion, non-HDR input, alpha upscaling and other unsupported +flags fail before Vulkan/model allocation. Public flag values are defined by +[NVIDIA's NGX header](https://github.com/NVIDIA/DLSS/blob/main/include/nvsdk_ngx_defs.h). + +Readiness checks and the fixture now use the required HDR/MVLowRes bits. Five +additional negative creation cases cover absent flags, high-resolution motion, +non-HDR input, jittered motion and alpha upscaling, bringing the contract gate +to thirteen rejections. Both the required-flags run and the AutoExposure run +pass all six camera/reset outputs exactly against standalone. The AutoExposure +run also alternates float guide formats, uses enhanced/inherited states, and +has no configured SR dependencies. Evidence: +`build/rr-ngx-hdr-render-motion-v1/summary.json` and +`build/rr-ngx-hdr-auto-exposure-v1/summary.json`. + +Earlier flagless results remain synthetic bridge/lifetime evidence; they did +not prove a valid game-facing HDR/motion contract. These new runs correct that +gap. They do not establish game quality, high-resolution/jittered motion support, +FSR execution or performance parity. + +## Optional native RR guides (2026-10-16) + +The production packet and recorder now carry `DLSSD.SpecularHitDistance`, +`DLSS.DisocclusionMask`, `DLSSD.ScreenSpaceSubsurfaceScatteringGuide`, and +`DLSSD.ColorBeforeParticles` into the existing RR engine. Bound optional guides +receive the same device/format/subrect/access validation and GPU texture copies +as required guides. Snapshots retain optional COM resources and subrect origins; +submission resolves their inherited/enhanced states. Binding can change between +frames without recreating the model or resetting temporal history. Exposure +textures remain unsupported. Previous optional-guide rejection notes describe +the earlier backend and are superseded by this section. + +Two six-frame sequences alternate all four optional guides between present and +absent, using R32F hit distance, R16F disocclusion/subsurface and RGBA16F +pre-particle color. Every output is finite/nonuniform and matches standalone +engine replay byte-for-byte. The second sequence keeps all optional guides +bound on the final frame, when the feature, parameters and fixture texture +ownership are released before submission. Both sequences also alternate +required guide formats, use enhanced/inherited access, set valid HDR/motion/ +AutoExposure flags, run thirteen negative contracts and omit SR dependencies. +Evidence: `build/rr-ngx-optional-toggle-v2/summary.json` and +`build/rr-ngx-optional-final-bound-v1/summary.json`. Reports verify actual per-frame +optional binding masks as well as independent output bytes. + +The first toggle attempt (`build/rr-ngx-optional-toggle-v1/`) matched five +frames, then encountered device removal. The harness had recorded uploads and +transitions for unbound optional textures and dropped their ownership before +the final submission. Fixture commands now skip unbound guides. The backend +quarantined incomplete work as designed. No driver, TDR, security or GPU setting +was changed. Fixed toggle and final-bound lifetime gates pass. + +These are synthetic same-engine API/transfer/lifetime comparisons. They do not +validate NVIDIA reference quality, additional optional format/encoding cases, +nonzero optional GPU subrects, dynamic geometry, concurrency, game integration, +FSR execution, or performance parity. + +## Native depth-plane formats and stencil preservation (2026-10-16) + +The backend now accepts R32 typeless, D32 float, and typed/typeless D32S8 depth +resources in addition to ordinary float depth textures. It queries the actual +D3D12 subresource-0 footprint, validates the depth row size, and imports only +those float depth bytes into Vulkan. The stencil plane is not part of the RR +packet or resource transition. Depth-stencil copies require the complete depth +rectangle with zero origin; cropped depth-stencil input fails Evaluate before +recording a boundary. The whole-rectangle rule follows +[Microsoft's CopyTextureRegion contract](https://learn.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12graphicscommandlist-copytextureregion). +Earlier depth-stencil rejection notes are superseded for these tested formats. + +Four six-frame real-shim runs cover D32 float, R32 typeless, D32S8 typed and +D32S8 typeless. All outputs remain finite/nonuniform and byte-identical to +standalone replay. D32S8 fixtures upload changing stencil sentinels to plane 1 +and independently read them back after RR; every stencil byte is preserved. +The runs retain optional-guide toggles, inherited access and final-bound +Release-before-submit coverage; D32S8 also exercises enhanced access. +Evidence: `build/rr-ngx-depth-{d32,r32-typeless,d32s8,d32s8-typeless}-v1/summary.json`. + +A further normalized, inverted hardware-depth sequence passes six exact frames +through typeless D32S8, with optional guides, enhanced/inherited access, changing +required formats, AutoExposure and no configured SR dependencies. Stencil +sentinels remain exact. Final report verifies all six hardware-depth/inversion +settings and records creation flags 75. Evidence: +`build/rr-ngx-inverted-hardware-depth-v2/summary.json` and logs. The final harness +also checks that cropped depth-stencil evaluation is rejected. + +These are same-engine synthetic comparisons, not a game or NVIDIA quality +reference. D24 conversion, MSAA/array depth, cropped depth-stencil processing, +output conversion, broader encodings, dynamic geometry/concurrency/game +integration, FSR execution and performance parity remain incomplete. + +## Player configuration without launcher overrides (2026-10-16) + +`d4r.ini` now accepts `[RayReconstruction] Backend = off|native|fsr` and +`ModelDir = auto|PATH`. Off is the default and clears stale RR selection in +player mode. Native resolves relative model paths beside d4r.ini; auto selects +`engine/rr-d`. FSR selection remains explicit but unavailable, with a diagnostic +note and rejected RR requests. The existing readiness check still loads the +configured model before advertising native RR. The source package README/INI +describe these experimental settings. Existing delivered ZIP artifacts have +not been rebuilt or changed; install.bat does not generate RR models yet. + +Pre-Init feature-13 requirements now establish player configuration before +checking readiness. An isolated staged player-folder test removes all launcher +path/RR overrides, selects the backend/model through the actual INI, and passes +six exact native RR hardware-depth frames. It also verifies capability contracts, +optional-guide toggling, enhanced/inherited state, inverted D32S8 and stencil +preservation, with final Release-before-submit. Evidence: +`build/rr-ngx-player-config-v1/summary.json` and the staged player's log/INI. +No game folder was read or modified. + +The player parser/environment/pin probe passes all checks, including relative RR +paths, invalid backend fallback, FSR unavailability and stale-environment cleanup. +Evidence fixtures: `build/player-config-rr-v2/`. The PowerShell checker recognizes +the new keys and passes static parser syntax validation; its fixture suite was +not rerun under the current script execution policy. No policy bypass was used. + +## Local package v4 architecture-loader gate (2026-10-16) + +A new development ZIP refreshes the previously verified v3 runtime with the +current shim and INI/checker/installer documentation. The base and all output +manifest hashes verify; local modified provenance remains explicit. No NVIDIA +binaries, RR models or private optimized kernels are bundled. Existing ZIPs +remain unchanged. See `windows-local-package.md` for its hash and size. + +The actual packaged architecture loader and refreshed target shim pass six +exact native RR hardware-depth frames with INI-only selection, optional guides, +enhanced/inherited states, stencil preservation and final Release-before-submit. +Pinned SR/core dependencies were staged separately for the test, and the local +RR model remains outside the ZIP. Evidence: +`build/rr-ngx-local-v4-loader-v1/summary.json`. No game, installer execution, +system change, commit or publishing occurred. Automatic RR model provisioning, +game integration, FSR execution and performance parity remain open. + +The native interop probe rebuilt successfully after these changes. The requested +camera/reset regression wrapper was blocked by the current PowerShell execution +policy before running. No policy change, bypass, alternate launcher, or probe +retry followed. Runtime regression validation of this refactor remains pending; +the earlier results below describe the preceding build. + +The RX 7700 XT now passes cross-API memory/fence transfers and actual RR model-D +inference through native D3D12 textures and the existing Vulkan engine. The NGX +feature-13 game adapter remains unfinished. The probe loads locally extracted +model files, not NVIDIA runtime DLLs, and does not touch a game. + +## What is verified + +`d4r_rr_interop_probe` matches the D3D12 adapter and Vulkan device by LUID. It +creates a committed shared D3D12 buffer, imports it into a dedicated Vulkan +allocation, and imports a shared D3D12 fence as a Vulkan timeline semaphore. +Each iteration queues this sequence: + +1. D3D12 uploads a new deterministic pattern and signals the shared fence. +2. Vulkan waits on that GPU fence, reads the buffer, writes new output, and + signals the same fence at a greater value. +3. D3D12 queues its own wait for Vulkan, copies the output for validation and + signals completion. Only then does the CPU validate both directions. + +The internal API handoff uses GPU synchronization and shared memory. CPU uploads +initialize synthetic inputs; CPU readbacks validate results. No tensor passes +through CPU memory between the two APIs. + +The image cases also copy the input buffer into a sampled/storage-capable +RGBA16F Vulkan image, preserve its exact input pixels through image readback, +clear it to known half-float values, and copy that output back to the shared +buffer for D3D12 consumption. The padded case verifies untouched row-padding +sentinels separately from image pixels. + +| Case | Shared bytes | Iterations | +|---|---:|---:| +| Buffer-only smoke | 1,048,576 | 8 | +| 1712x960 RGBA16F, 13,824-byte row pitch | 13,271,040 | 3 | +| 2560x1440 RGBA16F | 29,491,200 | 3 | + +All 14 iterations pass exact comparisons in both directions on native Windows. +The last two cases exercise Vulkan texture transfers. The probe uses explicit +external queue ownership transitions and transfer/host memory barriers. +The imported resource requires dedicated allocation on this driver. + +The timeline import follows the [Vulkan D3D12 fence guidance](https://docs.vulkan.org/refpages/latest/refpages/source/VkD3D12FenceSubmitInfoKHR.html). + +## Reproduce + +```powershell +cmake --build build/windows-rdna4-therock-gfx1101 --target d4r_rr_interop_probe +./scripts/windows/test-rr-interop.ps1 ` + -Probe build/windows-rdna4-therock-gfx1101/d4r_rr_interop_probe.exe ` + -OutputDirectory build/my-rr-interop-check +``` + +Use a new output directory under ignored `build/`. Each case has a 30-second +process limit. GPU completion waits have five-second limits. No driver, TDR, +security, or tuning setting is changed. + +Evidence: `build/rr-interop-canonical-images-v2/summary.json` and per-case logs. +Earlier buffer-only evidence remains under `build/rr-interop-realistic/`. + +## Bridged model inference + +`rr_bridge_replay.h` packs all seven canonical inputs into one shared GPU packet. +The harness uploads synthetic data into real D3D12 guide textures, copies them to +the shared buffer, and queues its producer fence. Vulkan imports that memory, +copies each guide into its sampled image and runs `RModel`/`REngine` with the +fixture's matrices, jitter, exposure and reset settings. It copies the RGBA16F +result back to the packet and signals the shared timeline. D3D12 waits on the +GPU, copies the result into its UAV-capable output texture, then reads that +texture back for QA. There is no CPU tensor transfer between APIs. + +Actual model-D results, all byte-identical to standalone Vulkan replay: + +| Fixture | Render/output | Frames | +|---|---|---:| +| Initial history/reset | 64x64 / 128x128 | 3 | +| Camera translation, jitter, exposure, reset at frames 0 and 3 | 64x64 / 128x128 | 6 | +| Full output size | 853x480 / 2560x1440 | 2 | + +All 11 textured frames are finite and nonuniform. The bridge wrapper also +compares output SHA256 independently after the executable's byte comparison. +Reference images come from the same existing RR engine; this proves bridge +consistency, not correctness against NVIDIA or image quality in a game. + +```powershell +./scripts/windows/test-rr-bridge-model.ps1 ` + -Probe build/windows-rdna4-therock-gfx1101/d4r_rr_interop_probe.exe ` + -ModelDirectory build/native-rr-d-windows-gfx1101-final ` + -InputDirectory build/rr-1440-inputs ` + -ReferenceDirectory build/rr-1440-reference ` + -OutputDirectory build/my-rr-model-bridge +``` + +The process limit is 180 seconds, including pipeline creation. Evidence is under +`build/rr-bridge-d-texture-inference/`, `build/rr-bridge-camera-reset/`, and +`build/rr-bridge-1440/`. The original 14-iteration transfer gate also passes after +the model-mode changes (`build/rr-interop-after-model-mode/`). + +The two standalone 1440p reference frames took 29.0 and 38.6 ms of GPU time. These +are two synthetic samples, not a steady-state measurement or Linux parity proof. +No inference timing is attributed to the bridge itself yet. + +The harness accepts canonical D/E gfx11 models and the seven required guides. +It rejects optional guide files, duplicate frame IDs and nonfinite settings; +support for optional hit distances, masks, particles and game format conversion +still needs implementation. Feature-13 creation/evaluation/lifetime integration, +game-facing resource state contracts, FSR RR and performance parity remain open. diff --git a/docs/windows-rr-model-cache.md b/docs/windows-rr-model-cache.md new file mode 100644 index 0000000..1861c8f --- /dev/null +++ b/docs/windows-rr-model-cache.md @@ -0,0 +1,162 @@ +# Local Windows RR model cache + +## Native Python builder without Git Bash + +`tools/windows/build_rr_model.py` now runs the extraction, template generation, +weight packing/widening, glslang compilation and exact-conversion passes directly +on Windows. It uses the same existing model scripts and shader recipe as the +Linux shell, with pinned RR DLL/glslang hashes and exact gfx11 arithmetic. +Python, NumPy and glslang must already be provisioned; automatic dependency +download and install.bat integration remain unfinished. + +```powershell +python tools/windows/build_rr_model.py ` + --dll build/install-bat-cache/nvidia/nvngx_dlssd.dll ` + --preset D --output build/my-native-rr-d +``` + +Use a fresh ignored build/ directory. `--reuse` verifies the DLL, compiler, +Python, NumPy version, source hashes and every top-level model product before +returning. Missing, modified or wrong-preset caches fail without rebuilding in +place. Each child step has a 600-second limit; a timed-out Windows process tree +is terminated. The caller's environment is copied rather than changed. No Bash, +PowerShell build wrapper, game access, driver change or policy bypass is used. +Derived shader/weight products stay local and must not be bundled. + +Actual preset-D build evidence: `build/native-rr-d-python-native-v2/`. +65 of 66 common top-level artifacts match the prior validated Windows model +byte-for-byte, including every shader, weight and argument template. The sole +manifest difference selects the Linux recipe's 64-wide output subgroup instead +of the prior Windows model's 32. Six native NGX hardware-depth frames still +match the old standalone reference exactly, with optional guides, enhanced/ +inherited access, format changes, stencil preservation and no SR dependencies. +No speed improvement is claimed for that subgroup setting. + +Cache reuse took approximately 0.26 seconds. Wrong-preset reuse and a modified +weight in a separate copied fixture were rejected. The valid model remained +unchanged. Evidence: `build/rr-native-python-builder-validation.json` and +`build/rr-ngx-python-native-model-v1/summary.json`. Preset E validation is recorded +below. Earlier v1/v2 artifacts +are preserved; v1 also differed in manifest line endings, corrected in v2. + +## Preset E build and verified local deployment + +The native Python E build completed all 48 steps, including its 4096-byte noise +prefix. As with D, 65/66 common top-level artifacts match the prior E model; +the manifest selects the Linux output subgroup width. Six NGX hardware-depth +frames match the prior E standalone engine reference exactly, with optional +guides, format switching, enhanced/inherited access, stencil preservation and +no configured SR dependencies. E cache reuse also passes. +Evidence: `build/rr-native-python-e-comparison.json` and +`build/rr-ngx-python-native-e-model-v1/summary.json`. + +`tools/windows/deploy_rr_model.py` verifies the native Python cache's product +hashes and complete D/E manifest, copies a private model into a versioned runtime +`engine/rr--` directory, and verifies every copied file. +Existing models are preserved. Repeated deployment reuses identical products; +changed products fail instead of replacing an existing model. No compiler or +NVIDIA DLL is copied. With `--enable`, it backs up d4r.ini outside the game/runtime +parent, then selects native RR and the relative model path. Comments, BOM, +line endings, SR settings and unrelated sections are preserved. + +```powershell +python tools/windows/deploy_rr_model.py --model build/my-native-rr-d ` + --runtime C:/Games/Example/d4r --enable +``` + +Only ignored mock-runtime paths were used in validation. An actual E deployment +verified 66 products, preserved an exact INI backup, and repeated without further +configuration changes/backups. A tampered model was rejected with every runtime +file unchanged. Three CPU tests cover BOM/CRLF/comments, absent/duplicate RR +sections and idempotence. The deployed model then passed six exact RR frames +through the packaged architecture loader using the preserved, deployment-written +relative INI path. Evidence: `build/rr-model-deploy-validation.json`, +`build/rr-model-deploy-negative-validation.json`, and +`build/rr-ngx-deployed-e-ini-v1/summary.json`. + +This automates local model deployment and selection. Dependency provisioning and +install.bat integration remain unfinished; the tools are not added to v4 ZIP. +No game was accessed, source committed, release published or system policy changed. + +## Portable dependency bundle + +`tools/windows/prepare_rr_tools.py` downloads and verifies pinned archives for +[Python 3.12.10 embeddable x64](https://www.python.org/downloads/release/python-31210/), +[NumPy 2.4.6 cp312 Windows x64](https://pypi.org/project/numpy/2.4.6/), and +glslang 16.6.0. It copies the tracked model-build sources, the kernel allowlist, +and license texts into a fresh local bundle. Python runs isolated with explicit +bundle-relative imports; system Python, pip and Git Bash are not needed to build +or deploy models from the prepared bundle. No system Python installation, PATH, +driver, security policy or game folder is changed. + +```powershell +python tools/windows/prepare_rr_tools.py --output build/my-rr-tools ` + --archive build/my-rr-tools.zip +build/my-rr-tools/python/python.exe ` + build/my-rr-tools/recipe/tools/windows/build_rr_model.py ` + --dll build/install-bat-cache/nvidia/nvngx_dlssd.dll --preset D ` + --output build/my-rr-tools/recipe/build/rr-d +``` + +Prepared local archive: `build/rr-portable-tools-v2.zip`, 40,154,515 bytes; +SHA256 `297289a57a82142eb952479c99112b1c352a6753eb15bc6b2431bf686aed9b22`. +All 1,111 recorded files verify. The archive is created from the pristine tool +manifest before model generation and contains no NVIDIA DLL, extracted PTX, +SPIR-V model shader or generated model. Building inside the extracted tool +directory later creates private products there; those products must not be +added to an archive. The recorded clean tools ZIP remains unchanged. + +Actual isolated-bundle D build completed all 48 steps. All 66 top-level model +artifacts match the already executed native Python D model byte-for-byte. +Bundled NumPy loaded from the bundle's own vendor directory, and cache reuse +passes. Bundled Python also deployed the verified 66-product model into a fresh +ignored mock runtime, selected it through INI and preserved an exact external +configuration backup. Evidence: `build/rr-portable-tools-validation.json` and +`build/rr-portable-deployment-validation.json`. + +The first bundle lacked `native_kernels.txt`; its build failed before weight +extraction and remains preserved separately. V2 includes that allowlist. Both +cache implementations now fingerprint source `.txt` inputs too. Existing cache +stamps made before this change may reject reuse; their artifacts are preserved, +and rebuilding uses a fresh output directory. No cache was silently restamped. + +Dependency preparation and portable model build/deployment are verified. +Connecting the tool bundle to install.bat and the main runtime ZIP remains open, +along with game integration, FSR execution and performance parity. + +## Existing PowerShell/Git Bash workflow + +The native D/E builder can reuse a verified model directory instead of rebuilding +all extracted weights and shaders. This is local build automation; it does not +capture game inputs or implement the Windows RR game adapter. + +```powershell +./scripts/windows/build-native-rr-model.ps1 ` + -DlssdDll build/install-bat-cache/nvidia/nvngx_dlssd.dll ` + -Preset D -OutputDirectory build/native-rr-d-cache-verified -ReuseCache +``` + +Use the path to your own installer-staged, pinned DLL. On a new output directory, +the builder compiles the model and writes `windows-rr-cache.json`. On an existing +directory, `-ReuseCache` checks the manifest and returns only if every input and +product hash still matches. Missing, modified or stale caches fail; select a new +directory to rebuild. Legacy directories without a cache manifest are not +silently trusted or overwritten. + +The cache records the DLL, Python, Git Bash and glslang hashes; NumPy version; +source hashes; preset; gfx1101 architecture; exact arithmetic; and hashes of all +top-level generated model artifacts. It also checks the RR manifest preset, +arithmetic and complete 12-stage shader/weight references. All derived model data +stays under ignored `build/`. The cache is not a public package artifact. + +Validation on the real locally built preset D model: + +- Full build completed and stamped 66 artifacts. +- Verified reuse took approximately 0.64 seconds and did not rewrite the shader. +- Flipping a byte in a weight file caused rejection; the original file was + restored and its SHA256 rechecked before a final successful cache hit. +- Requesting E against the D model was rejected. +- The builder restored the caller's `D4R_RR_GFX11` and `D4R_RR_RELAXED` settings. + +Evidence: `build/rr-cache-validation.json`. These checks establish cache behavior, +not RR quality, game support, or a performance improvement in inference. diff --git a/packaging/windows/WINDOWS_README.txt b/packaging/windows/WINDOWS_README.txt index 7c98b75..b6e625d 100644 --- a/packaging/windows/WINDOWS_README.txt +++ b/packaging/windows/WINDOWS_README.txt @@ -4,9 +4,10 @@ d4r for Windows: NVIDIA DLSS on AMD Radeon RDNA3 and RDNA4 d4r runs NVIDIA's own DLSS (DLSS 4 by default) on a Radeon GPU in DirectX 12 games. OptiScaler (included) catches the game's upscaler calls and hands them to d4r. -This is an early release. Only the Radeon RX 9070 XT has been tested on real hardware; every other -GPU in this release is compile-tested. SUPPORTED_GAMES.md in the source repository lists the -tested games. Expect problems. +This is an early release. RX 7700 XT has passed native Windows synthetic checks and limited +game-frame tests. RX 9070 XT also has recorded hardware tests; other targets are compile-tested. +These checks do not establish broad game support or Linux performance parity. +SUPPORTED_GAMES.md in the source repository lists the tested games. Expect problems. What you need ------------- @@ -28,7 +29,8 @@ Install 2. Run install.bat and accept the download prompt. Existing d4r DLLs are backed up outside the game folder with their original paths and SHA256 hashes. Verified downloads are cached in %LOCALAPPDATA%\d4r\cache. - The Ray Reconstruction DLL is local preparation only; this Windows game backend does not run RR yet. + The Ray Reconstruction DLL alone does not enable RR. Experimental native RR requires a locally + generated D/E model and explicit d4r.ini selection; game compatibility remains unverified. 3. Optional: check the install. In the game folder, open PowerShell and run powershell -ExecutionPolicy Bypass -File d4r\d4r-check.ps1 4. Start the game from Steam, Epic or a shortcut as usual. In its graphics settings choose DLSS @@ -44,6 +46,10 @@ Edit d4r\d4r.ini (it is commented) and restart the game. Each game has its own c - Model: E (preset 5), K (11, DLSS 4), L (12) or M (13, DLSS 4.5). E and L set NGX hints only; the standalone engine and L texture kernels are not integrated. Select quality mode in the game. - Kernels/NativeFp8: experimental RDNA4 setting. Requires a matching gfx12 native-FP8 M bundle; keep false with the standard FP16 release. Token-lane and hardware-pack builds remain unvalidated on GPU. - AsyncInterop, ValidateOutput, Log: for testing and bug reports; the defaults are the tested setting. +- RayReconstruction/Backend: off by default. native selects experimental native D3D12/Vulkan RR; + ModelDir selects your locally generated D/E model (auto: d4r\engine\rr-d). Relative paths resolve + beside d4r.ini. No model is bundled or automatically generated by install.bat yet. + fsr currently rejects RR requests because native Windows FSR RR execution is unavailable. OptiScaler's own settings (overlay, render ratios) are in OptiScaler.ini. If something goes wrong @@ -53,7 +59,9 @@ If something goes wrong - DLSS missing in the menu and no d4r_nvngx.log: the files are not next to the game's main .exe. - For a bug report run d4r\d4r-check.ps1 -Report and send the ZIP it puts on your Desktop, with your GPU, the game, the model and what the image looked like. Logs can contain folder names. -- Not supported: frame generation, standalone inference engine, DLSS Ray Reconstruction, DirectX 11, Vulkan. E/L preset hints do not establish full Windows feature parity. +- Not supported: frame generation, standalone inference engine selection in the game, DirectX 11, + Vulkan game integration, or FSR RR. Native DLSS RR has synthetic feature-13 validation only; + it does not establish game compatibility or NVIDIA reference quality. E/L hints do not establish full parity. Uninstall --------- diff --git a/packaging/windows/d4r.ini b/packaging/windows/d4r.ini index d6aa58d..70d3468 100644 --- a/packaging/windows/d4r.ini +++ b/packaging/windows/d4r.ini @@ -2,7 +2,7 @@ ; this game only. Edit it with Notepad, save, and restart the game. Mistakes are reported in ; d4r\d4r_nvngx.log and by d4r-check.ps1; an invalid value falls back to the default shown here. ; -; Engine inference and Ray Reconstruction are not yet integrated in this Windows build. +; Native Ray Reconstruction is experimental and requires a locally generated D/E model. [DLSS] ; DLSS model: @@ -40,8 +40,19 @@ Log = normal ; Folder for the compiled DLSS kernels. auto = %LOCALAPPDATA%\d4r\cache. The first launch fills it ; and can take several minutes; later launches are quick. CacheDir = auto +; Optional complete private native kernel directory, generated locally from your DLLs. +; auto uses the packaged kernels. Relative paths resolve beside this d4r.ini. +NativeDir = auto [Kernels] ; Experimental RDNA4 only. Requires a matching token-lane FP8 M bundle; startup refuses this ; setting if d4r/native//d4r-native-fp8.txt is absent. Default keeps the FP16 path. NativeFp8 = false + +[RayReconstruction] +; off is the default. native uses the local Vulkan RR engine through native D3D12. +; fsr is currently unavailable and rejects RR requests. No fallback to noisy upscaling. +Backend = off +; auto selects d4r/engine/rr-d. Relative paths resolve beside this d4r.ini. +; Generate the D/E model locally; model data is not bundled in the ZIP. +ModelDir = auto diff --git a/scripts/windows/build-native-k-experiment.ps1 b/scripts/windows/build-native-k-experiment.ps1 index 49a380e..cac3799 100644 --- a/scripts/windows/build-native-k-experiment.ps1 +++ b/scripts/windows/build-native-k-experiment.ps1 @@ -4,12 +4,17 @@ param([ValidateSet('enc0','enc1','enc2','enc3','enc4','dec5','dec4','dec3','dec2 [ValidateSet('baseline','load','store','both')][string]$NonTemporal='baseline', [ValidateSet(0,1,2,4)][int]$PosTiles=0, [switch]$ShareValues, [switch]$PrivateValues, [switch]$PackedAccumulator, + [ValidateSet('gfx1100','gfx1101','gfx1102','gfx1103','gfx1150','gfx1151','gfx1152','gfx1153','gfx1154','gfx1200','gfx1201')] + [string]$GpuArch='gfx1201', [string]$HipRoot, [string]$OutputDirectory) $ErrorActionPreference='Stop' $repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..')) if (!$HipRoot) { $HipRoot=Join-Path $repo '.tools/therock-10.2.0a20260929/_rocm_sdk_core' } if ($ShareValues -and $PrivateValues) { throw 'Choose shared or private V storage.' } -if (!$OutputDirectory) { $OutputDirectory=Join-Path $repo "build/native-k-experiment-$Layer-$Mode-$NonTemporal-pos$PosTiles-share$([int][bool]$ShareValues)-private$([int][bool]$PrivateValues)-packed$([int][bool]$PackedAccumulator)" } +if ($GpuArch -notmatch '^gfx12' -and ($PosTiles -or $ShareValues -or $PrivateValues -or $PackedAccumulator)) { + throw 'Token tiling and accumulator/storage experiments require gfx12.' +} +if (!$OutputDirectory) { $OutputDirectory=Join-Path $repo "build/native-k-experiment-$GpuArch-$Layer-$Mode-$NonTemporal-pos$PosTiles-share$([int][bool]$ShareValues)-private$([int][bool]$PrivateValues)-packed$([int][bool]$PackedAccumulator)" } $OutputDirectory=[IO.Path]::GetFullPath($OutputDirectory) foreach ($baseline in @('build/native-k-gfx1201','build/windows-rdna4-therock','dist/windows-rdna4-command-list')) { if ($OutputDirectory.StartsWith([IO.Path]::GetFullPath((Join-Path $repo $baseline)), [StringComparison]::OrdinalIgnoreCase)) { @@ -40,22 +45,23 @@ if ($ShareValues) { } if ($PackedAccumulator) { $flags+='-DD4R_K_PACKED_ACC' } if ($PrivateValues) { $flags+='-DD4R_K_PRIVATE_V' } +if ($GpuArch -match '^gfx11') { $flags+='-DD4R_WINDOWS_GFX11_LANE_EXCHANGE' } New-Item -ItemType Directory -Force $OutputDirectory | Out-Null $object=Join-Path $OutputDirectory "$name.hsaco" -$arguments=@('-x','hip','-std=c++17','--offload-arch=gfx1201','--offload-device-only', +$arguments=@('-x','hip','-std=c++17',"--offload-arch=$GpuArch",'--offload-device-only', '--no-gpu-bundle-output','-mno-wavefrontsize64','-nogpuinc','-nogpulib','-O3', '-DD4R_DEVICE_ONLY_MINIMAL','-DD4R_K_FP16_BASELINE')+$flags+@($source,'-o',$object) $ErrorActionPreference='Continue' & $compiler @arguments > (Join-Path $OutputDirectory "$name.build.stdout.log") 2> (Join-Path $OutputDirectory "$name.build.stderr.log") $ErrorActionPreference='Stop' if ($LASTEXITCODE) { throw "Experimental K compile failed: $Layer" } -& (Join-Path (Split-Path $compiler) 'llvm-objdump.exe') --disassemble --mcpu=gfx1201 $object ` +& (Join-Path (Split-Path $compiler) 'llvm-objdump.exe') --disassemble "--mcpu=$GpuArch" $object ` > (Join-Path $OutputDirectory "$name.isa.txt") if ($LASTEXITCODE) { throw 'Native object ISA extraction failed.' } & (Join-Path (Split-Path $compiler) 'llvm-readobj.exe') --notes $object ` > (Join-Path $OutputDirectory "$name.metadata.txt") if ($LASTEXITCODE) { throw 'Native object metadata extraction failed.' } -@{layer=$Layer; architecture='gfx1201'; experimental=$true; numericalValidation='pending'; +@{layer=$Layer; architecture=$GpuArch; experimental=$true; numericalValidation='pending'; mode=$Mode; nonTemporal=$NonTemporal; tokenTilesPerWave=$PosTiles; shareValues=[bool]$ShareValues; privateValues=[bool]$PrivateValues; packedAccumulator=[bool]$PackedAccumulator; @@ -64,5 +70,5 @@ if ($LASTEXITCODE) { throw 'Native object metadata extraction failed.' } compilerVersion=(& $compiler --version | Out-String).Trim(); sha256=(Get-FileHash -LiteralPath $object -Algorithm SHA256).Hash} | ConvertTo-Json -Depth 4 | Set-Content -LiteralPath (Join-Path $OutputDirectory "$name.build-info.json") -Encoding UTF8 -Write-Host "Compiled gfx1201 K experiment: $Layer mode=$Mode nonTemporal=$NonTemporal posTiles=$PosTiles shareValues=$([bool]$ShareValues). Validate before installing." +Write-Host "Compiled $GpuArch K experiment: $Layer mode=$Mode nonTemporal=$NonTemporal posTiles=$PosTiles shareValues=$([bool]$ShareValues). Validate before installing." # No override manifest or game installation is produced by this script. diff --git a/scripts/windows/build-native-rr-model.ps1 b/scripts/windows/build-native-rr-model.ps1 index 9a280af..9eb9084 100644 --- a/scripts/windows/build-native-rr-model.ps1 +++ b/scripts/windows/build-native-rr-model.ps1 @@ -3,7 +3,8 @@ param( [Parameter(Mandatory=$true)][string]$DlssdDll, [ValidateSet('D','E')][string]$Preset='D', [string]$OutputDirectory, - [string]$GitBash='C:\Program Files\Git\bin\bash.exe' + [string]$GitBash='C:\Program Files\Git\bin\bash.exe', + [switch]$ReuseCache ) $ErrorActionPreference='Stop' $repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..')) @@ -18,7 +19,7 @@ $buildRoot=[IO.Path]::GetFullPath((Join-Path $repo 'build')) if(!$OutputDirectory.StartsWith($buildRoot+'\',[StringComparison]::OrdinalIgnoreCase)){ throw "RR model output must stay under the ignored build directory: $OutputDirectory" } -if(Test-Path -LiteralPath $OutputDirectory){throw "Use a new RR model output directory: $OutputDirectory"} +if((Test-Path -LiteralPath $OutputDirectory) -and !$ReuseCache){throw "Use a new RR model output directory or -ReuseCache: $OutputDirectory"} $glslang=Join-Path $repo '.tools/glslang-16.6.0/bin' $pythonHome=Split-Path (Get-Command python.exe -ErrorAction Stop).Source $pythonShim=Join-Path $repo '.tools/rr-build-bin' @@ -35,6 +36,8 @@ $unixOut=(& $cygpath -u $OutputDirectory).Trim() if(!$unixRepo -or !$unixDll -or !$unixOut){throw 'Git Bash path conversion failed.'} $oldPath=$env:PATH $oldPythonPath=$env:PYTHONPATH +$oldGfx11=$env:D4R_RR_GFX11 +$oldRelaxed=$env:D4R_RR_RELAXED $env:PATH="$pythonShim;$pythonHome;$glslang;$(Split-Path $GitBash -Parent);$oldPath" $env:PYTHONPATH=$pythonVendor $env:D4R_RR_GFX11='1' @@ -43,7 +46,16 @@ $log=Join-Path $buildRoot ("native-rr-$($Preset.ToLower())-windows-build.log") try{ & $python3 -c 'import numpy; print("numpy", numpy.__version__)' if($LASTEXITCODE){throw 'Pinned NumPy could not load in the Windows RR build environment.'} - $command="cd '$unixRepo' && D4R_RR_GFX11=1 D4R_RR_RELAXED=0 bash engine/rr/build_native_model.sh --dll '$unixDll' '$Preset' '$unixOut'" + $cacheArguments=@('--model',$OutputDirectory,'--dll',$DlssdDll,'--preset',$Preset, + '--glslang',(Join-Path $glslang 'glslangValidator.exe'),'--bash',$GitBash) + $cacheTool=Join-Path $PSScriptRoot 'rr-model-cache.py' + if(Test-Path -LiteralPath $OutputDirectory){ + & $python3 $cacheTool check @cacheArguments + if($LASTEXITCODE){throw 'RR model cache is absent, stale or changed. Use a new output directory.'} + return + } + function Quote-Bash([string]$Value){return "'"+$Value.Replace("'","'\''")+"'"} + $command="cd $(Quote-Bash $unixRepo) && D4R_RR_GFX11=1 D4R_RR_RELAXED=0 bash engine/rr/build_native_model.sh --dll $(Quote-Bash $unixDll) '$Preset' $(Quote-Bash $unixOut)" $previousPreference=$ErrorActionPreference try{ $ErrorActionPreference='Continue' @@ -54,6 +66,8 @@ try{ foreach($required in @('rr.txt','model.json','enc0_m.spv','dec0_m.spv','hkpn.spv','enc0.args','hkpn.args')){ if(!(Test-Path -LiteralPath (Join-Path $OutputDirectory $required))){throw "RR build incomplete; missing $required"} } + & $python3 $cacheTool write @cacheArguments + if($LASTEXITCODE){throw 'RR build completed but cache manifest could not be written.'} Write-Host "Built local preset $Preset native RR model: $OutputDirectory" Write-Host "DLL SHA256: $hash. Build log: $log" -}finally{$env:PATH=$oldPath;$env:PYTHONPATH=$oldPythonPath} +}finally{$env:PATH=$oldPath;$env:PYTHONPATH=$oldPythonPath;$env:D4R_RR_GFX11=$oldGfx11;$env:D4R_RR_RELAXED=$oldRelaxed} diff --git a/scripts/windows/build-zluda-helpers.ps1 b/scripts/windows/build-zluda-helpers.ps1 index 16e8bea..f195d12 100644 --- a/scripts/windows/build-zluda-helpers.ps1 +++ b/scripts/windows/build-zluda-helpers.ps1 @@ -1,14 +1,26 @@ [CmdletBinding()] -param([string]$SourceRoot, [string]$HipRoot = 'C:\Program Files\AMD\ROCm\7.2', [string]$WorkRoot) +param([string]$SourceRoot, [string]$HipRoot = 'C:\Program Files\AMD\ROCm\7.2', [string]$WorkRoot, [string]$LlvmBuildRoot) $ErrorActionPreference = 'Stop' $repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..')) if (!$SourceRoot) { $SourceRoot = Join-Path $repo 'external/ZLUDA' } if (!$WorkRoot) { $WorkRoot = Join-Path $repo 'build/zluda-helpers-windows' } $toolchain = Join-Path $repo '.tools/llvm-mingw-20260922-ucrt-x86_64' -$compiler = Join-Path $HipRoot 'bin/clang++.exe' -$dis = Join-Path $HipRoot 'bin/llvm-dis.exe' -$assembler = Join-Path $HipRoot 'bin/llvm-as.exe' -$ocml = Join-Path $HipRoot 'amdgcn/bitcode/ocml.bc' +function Find-HipHelperTool([string]$Name) { + foreach ($folder in @('lib/llvm/bin','bin')) { + $candidate=Join-Path $HipRoot "$folder/$Name.exe" + if(Test-Path -LiteralPath $candidate){return $candidate} + } + throw "HIP helper tool missing: $Name under $HipRoot" +} +$compiler = Find-HipHelperTool 'clang++' +$dis = Find-HipHelperTool 'llvm-dis' +$assembler = Find-HipHelperTool 'llvm-as' +if(!$LlvmBuildRoot){$LlvmBuildRoot=Join-Path $repo 'build/zluda-llvm-windows-gnu'} +$pinnedAssembler=Join-Path $LlvmBuildRoot 'bin/llvm-as.exe' +if(!(Test-Path -LiteralPath $pinnedAssembler)){throw 'Build the pinned LLVM llvm-as target before the PTX helpers.'} +$assembler=$pinnedAssembler +$ocml = Join-Path $HipRoot 'lib/llvm/amdgcn/bitcode/ocml.bc' +if(!(Test-Path -LiteralPath $ocml)){$ocml=Join-Path $HipRoot 'amdgcn/bitcode/ocml.bc'} foreach ($file in @($compiler,$dis,$assembler,$ocml)) { if (!(Test-Path $file)) { throw "HIP helper dependency missing: $file" } } @@ -58,13 +70,24 @@ foreach ($variant in $variants) { if ($LASTEXITCODE) { throw "Disassemble failed: $raw" } $clean = [Collections.Generic.List[string]]::new() foreach ($line in [IO.File]::ReadLines($ir)) { + # Directly linked helpers do not need a ThinLTO index, which may retain + # references to the stripped HIP/LLVM globals. + if ($line -match '^\^\d+\s*=') { continue } if ($line -match '@llvm.used|wchar_size|llvm.module.flags|__hip_cuid') { continue } $line = $line -replace 'optnone','' -replace 'define hidden','define linkonce_odr' $line = $line -replace '"target-cpu"="gfx1030"','' -replace '"target-features"="[^"]+"','' $clean.Add($line) } [IO.File]::WriteAllLines($ir,$clean,[Text.UTF8Encoding]::new($false)) + if($assembler -eq $pinnedAssembler){ + & python (Join-Path $repo 'tools/windows/llvm22_ir.py') $ir $ir + if($LASTEXITCODE){throw 'LLVM 22 helper IR compatibility conversion failed.'} + } + $previousPath=$env:PATH + $env:PATH="$(Join-Path $toolchain 'bin');$previousPath" + try { & $assembler $ir -o $output if ($LASTEXITCODE) { throw "Assemble failed: $ir" } + } finally {$env:PATH=$previousPath} Write-Host "Built $output ($((Get-Item $output).Length) bytes)" } diff --git a/scripts/windows/build-zluda-llvm.ps1 b/scripts/windows/build-zluda-llvm.ps1 index f7f9121..cd3a6cc 100644 --- a/scripts/windows/build-zluda-llvm.ps1 +++ b/scripts/windows/build-zluda-llvm.ps1 @@ -31,7 +31,7 @@ try { $ErrorActionPreference = 'Stop' if ($LASTEXITCODE) { throw "LLVM configure failed ($LASTEXITCODE)" } $ErrorActionPreference = 'Continue' - & $cmake --build $BuildRoot --parallel $Jobs --target llvm-config llvm-libraries lldCommon lldELF ` + & $cmake --build $BuildRoot --parallel $Jobs --target llvm-config llvm-libraries lldCommon lldELF llvm-as ` 2>&1 | Tee-Object (Join-Path $BuildRoot 'build.log') $ErrorActionPreference = 'Stop' if ($LASTEXITCODE) { throw "LLVM build failed ($LASTEXITCODE)" } diff --git a/scripts/windows/build-zluda-windows.ps1 b/scripts/windows/build-zluda-windows.ps1 index 7485339..e923eba 100644 --- a/scripts/windows/build-zluda-windows.ps1 +++ b/scripts/windows/build-zluda-windows.ps1 @@ -1,10 +1,10 @@ [CmdletBinding()] -param([string]$SourceRoot, [string]$LlvmBuildRoot, [string]$InstallRoot, [switch]$FetchOnly, [switch]$CacheTestsOnly, [switch]$CompilerTestsOnly, [int]$Jobs = 4) +param([string]$SourceRoot, [string]$LlvmBuildRoot, [string]$InstallRoot, [switch]$FetchOnly, [switch]$CacheTestsOnly, [switch]$CompilerTestsOnly, [switch]$EmitterOnly, [int]$Jobs = 4) $ErrorActionPreference = 'Stop' $repo = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..')) if (!$SourceRoot) { $SourceRoot = Join-Path $repo 'external/ZLUDA' } if (!$LlvmBuildRoot) { $LlvmBuildRoot = Join-Path $repo 'build/zluda-llvm-windows-gnu' } -if (!$InstallRoot) { $InstallRoot = Join-Path $repo 'dist/zluda-windows-final' } +if (!$InstallRoot) { $InstallRoot = Join-Path $repo $(if ($EmitterOnly) { 'dist/zluda-windows-emitter' } else { 'dist/zluda-windows-final' }) } $rust = Join-Path $repo '.tools/rust-1.98.1-gnu' $toolchain = Join-Path $repo '.tools/llvm-mingw-20260922-ucrt-x86_64' $target = Join-Path $repo 'build/zluda-rust-windows-gnu' @@ -60,28 +60,41 @@ try { foreach ($variant in @('','_constrained','_w64','_constrained_w64')) { if (!(Test-Path "ptx/lib/zluda_ptx_impl$variant.bc")) { throw 'Run build-zluda-helpers.ps1 first.' } } - $ErrorActionPreference = 'Continue' - & $cargo build --locked --release --target x86_64-pc-windows-gnu -p zluda -p nvapi -p zluda_trace ` - 2>&1 | Tee-Object (Join-Path $target 'build.log') - $ErrorActionPreference = 'Stop' - if ($LASTEXITCODE) { throw "ZLUDA build failed ($LASTEXITCODE)" } + if (!$EmitterOnly) { + $ErrorActionPreference = 'Continue' + & $cargo build --locked --release --target x86_64-pc-windows-gnu -p zluda -p nvapi -p zluda_trace ` + 2>&1 | Tee-Object (Join-Path $target 'build.log') + $ErrorActionPreference = 'Stop' + if ($LASTEXITCODE) { throw "ZLUDA build failed ($LASTEXITCODE)" } + } $ErrorActionPreference = 'Continue' & $cargo build --locked --release --target x86_64-pc-windows-gnu -p ptx --example d4r_emit ` 2>&1 | Tee-Object (Join-Path $target 'emit-build.log') $ErrorActionPreference = 'Stop' if ($LASTEXITCODE) { throw "d4r_emit build failed ($LASTEXITCODE)" } $release = Join-Path $target 'x86_64-pc-windows-gnu/release' - Copy-Item -LiteralPath (Join-Path $release 'nvcuda.dll') -Destination $InstallRoot -Force - Copy-Item -LiteralPath (Join-Path $release 'nvapi64.dll') -Destination $InstallRoot -Force + if (!$EmitterOnly) { + Copy-Item -LiteralPath (Join-Path $release 'nvcuda.dll') -Destination $InstallRoot -Force + Copy-Item -LiteralPath (Join-Path $release 'nvapi64.dll') -Destination $InstallRoot -Force + } # The C++ dependencies select libc++ dynamically even when Rust requests # static GNU support libraries. Keep these portable runtime DLLs local. foreach ($runtime in @('libc++.dll', 'libunwind.dll')) { Copy-Item -LiteralPath (Join-Path $toolchain "bin/$runtime") -Destination $InstallRoot -Force } - New-Item -ItemType Directory -Force (Join-Path $InstallRoot 'trace') | Out-Null - Copy-Item -LiteralPath (Join-Path $release 'zluda_trace.dll') -Destination (Join-Path $InstallRoot 'trace/nvcuda.dll') -Force + if (!$EmitterOnly) { + New-Item -ItemType Directory -Force (Join-Path $InstallRoot 'trace') | Out-Null + Copy-Item -LiteralPath (Join-Path $release 'zluda_trace.dll') -Destination (Join-Path $InstallRoot 'trace/nvcuda.dll') -Force + } Copy-Item -LiteralPath (Join-Path $release 'examples/d4r_emit.exe') -Destination $InstallRoot -Force - @{base='ee2f25a180099fa42f36b2346732e1f2470a03ad'; target='x86_64-pc-windows-gnu'; + if(Test-Path -LiteralPath (Join-Path $LlvmBuildRoot 'bin/llvm-as.exe')){ + Copy-Item -LiteralPath (Join-Path $LlvmBuildRoot 'bin/llvm-as.exe') -Destination $InstallRoot -Force + } + @{base='ee2f25a180099fa42f36b2346732e1f2470a03ad'; target='x86_64-pc-windows-gnu'; emitterOnly=[bool]$EmitterOnly; + emitterSha256=(Get-FileHash -LiteralPath (Join-Path $InstallRoot 'd4r_emit.exe') -Algorithm SHA256).Hash; + assemblerSha256=$(if(Test-Path -LiteralPath (Join-Path $InstallRoot 'llvm-as.exe')){ + (Get-FileHash -LiteralPath (Join-Path $InstallRoot 'llvm-as.exe') -Algorithm SHA256).Hash + }else{$null}); sourceCommit=(& git rev-parse HEAD); workingTreeDirty=[bool](& git status --porcelain); rust='1.98.1'; llvm=(& (Join-Path $LlvmBuildRoot 'bin/llvm-config.exe') --version); llvmSource=$(if (Test-Path (Join-Path $LlvmBuildRoot 'd4r-llvm-build-info.json')) { @@ -89,7 +102,7 @@ try { } else { $null }); files=@(Get-ChildItem -LiteralPath $InstallRoot -Filter '*.dll' | Get-FileHash -Algorithm SHA256)} | ConvertTo-Json -Depth 5 | Set-Content -LiteralPath (Join-Path $InstallRoot 'build-info.json') -Encoding UTF8 - Write-Host "Native Windows d4r ZLUDA runtime: $InstallRoot" + Write-Host "Native Windows d4r ZLUDA $(if ($EmitterOnly) { 'offline emitter' } else { 'runtime' }): $InstallRoot" } finally { Pop-Location foreach ($name in $previous.Keys) { [Environment]::SetEnvironmentVariable($name,$previous[$name],'Process') } diff --git a/scripts/windows/d4r-check.ps1 b/scripts/windows/d4r-check.ps1 index 96ee58f..f61e8f7 100644 --- a/scripts/windows/d4r-check.ps1 +++ b/scripts/windows/d4r-check.ps1 @@ -158,7 +158,8 @@ else { Ok "GPU $($device.name) ($a): build present, $native native kernels" if (!$arch) { $arch = $a } } - if ($a -ne 'gfx1201') { Note "only the RX 9070 XT (gfx1201) has been tested on real hardware; $a is compile-tested" } + if ($a -eq 'gfx1101') { Note 'RX 7700 XT has passed native Windows synthetic checks and limited game-frame tests; broad game validation remains incomplete' } + elseif ($a -ne 'gfx1201') { Note "$a is compile-tested; no native Windows hardware validation is recorded for this target" } } } if (@($inventory.devices | Where-Object { $_.wavefrontSize -eq 32 }).Count -gt 1) { Note 'several GPUs found; d4r uses the one the game renders on' } @@ -197,7 +198,7 @@ $iniPath = Join-Path $d4r 'd4r.ini' $model = 'K' if (Test-Path -LiteralPath $iniPath) { $section = ''; $iniProblems = 0 - $known = @{ 'dlss.model' = 1; 'dlss.showwatermark' = 1; 'interop.asyncinterop' = 1; 'debug.validateoutput' = 1; 'debug.log' = 1; 'paths.cachedir' = 1; 'kernels.nativefp8' = 1 } + $known = @{ 'dlss.model' = 1; 'dlss.showwatermark' = 1; 'interop.asyncinterop' = 1; 'debug.validateoutput' = 1; 'debug.log' = 1; 'paths.cachedir' = 1; 'paths.nativedir' = 1; 'kernels.nativefp8' = 1; 'rayreconstruction.backend' = 1; 'rayreconstruction.modeldir' = 1 } $boolean = @('dlss.showwatermark', 'interop.asyncinterop', 'debug.validateoutput', 'kernels.nativefp8') foreach ($raw in (Read-TextFile $iniPath).TrimStart([char]0xFEFF) -split "`n") { $line = $raw.Trim() @@ -212,11 +213,41 @@ if (Test-Path -LiteralPath $iniPath) { elseif ($name -eq 'dlss.model') { if (@('', 'auto', 'k', 'dlss4', '11') -contains $v) { $model = 'K' } elseif (@('m', 'dlss4.5', '13') -contains $v) { $model = 'M' } - else { Note "d4r.ini: [DLSS] Model '$value' is not available on Windows (use K or M); K will be used"; $iniProblems++ } + elseif (@('e', '5') -contains $v) { $model = 'E' } + elseif (@('l', '12') -contains $v) { $model = 'L' } + else { Note "d4r.ini: [DLSS] Model '$value' is not available on Windows (use E, K, L or M); K will be used"; $iniProblems++ } } elseif ($boolean -contains $name) { if (@('', 'auto', '1', 'true', 'yes', 'on', '0', 'false', 'no', 'off') -notcontains $v) { Note "d4r.ini: [$section] $key must be true or false, not '$value'; the default will be used"; $iniProblems++ } } + elseif ($name -eq 'rayreconstruction.backend') { + if ($v -notin @('', 'auto', 'off', 'native', 'fsr')) { Note 'd4r.ini: [RayReconstruction] Backend must be off, native or fsr; off will be used'; $iniProblems++ } + elseif ($v -eq 'fsr') { Note 'Native Windows FSR RR is unavailable; RR requests will be rejected' } + } + elseif ($name -eq 'paths.nativedir' -and $v -notin @('', 'auto')) { + $privateNative=if([IO.Path]::IsPathRooted($value)){$value}else{Join-Path $d4r $value} + if($arch -and (Test-Path -LiteralPath (Join-Path $privateNative $arch))){$privateNative=Join-Path $privateNative $arch} + $privateObjects=@(Get-ChildItem -LiteralPath $privateNative -Filter '*.hsaco' -ErrorAction SilentlyContinue) + if(!$privateObjects.Count -or !(Test-Path -LiteralPath (Join-Path $privateNative 'd4r-kernels.txt'))){ + Bad '[Paths] NativeDir must contain the complete native kernel set and d4r-kernels.txt';$iniProblems++ + }else{ + foreach($requiredNative in @(Get-ChildItem -LiteralPath (Join-Path $d4r "native\$arch") -Filter '*.hsaco' -ErrorAction SilentlyContinue)){ + if(!(Test-Path -LiteralPath (Join-Path $privateNative $requiredNative.Name))){ + Bad "NativeDir is incomplete; missing $($requiredNative.Name)";$iniProblems++ + } + } + $privateTarget=@($registry | Where-Object architecture -eq $arch) | Select-Object -First 1 + foreach($object in $privateObjects){ + $stream=[IO.File]::OpenRead($object.FullName) + try{$header=New-Object byte[] 64;$read=$stream.Read($header,0,64)}finally{$stream.Dispose()} + if($privateTarget -and ($read -ne 64 -or $header[0] -ne 127 -or $header[1] -ne 69 -or + $header[2] -ne 76 -or $header[3] -ne 70 -or $header[48] -ne $privateTarget.elfMachine)){ + Bad "NativeDir $($object.Name) is not built for $arch";$iniProblems++ + } + } + if(!$iniProblems){Ok "private native kernel directory: $privateNative"} + } + } elseif ($name -eq 'debug.log' -and @('', 'auto', 'normal', 'verbose') -notcontains $v) { Note "d4r.ini: [Debug] Log must be normal or verbose, not '$value'; normal will be used"; $iniProblems++ } } if (!$iniProblems) { Ok "d4r.ini is valid (model $model)" } diff --git a/scripts/windows/package-windows-release.ps1 b/scripts/windows/package-windows-release.ps1 index bddd66c..e1a6efa 100644 --- a/scripts/windows/package-windows-release.ps1 +++ b/scripts/windows/package-windows-release.ps1 @@ -1,6 +1,6 @@ -# Builds the Windows drag-in release: extract it into the game folder, copy -# the two NVIDIA DLLs, edit d4r\d4r.ini. Like the Linux release, no installer -# or launcher is involved. Inputs are the per-target game packages that +# Builds the Windows drag-in release: extract it into the game folder and run +# install.bat for the pinned local NVIDIA dependencies. No game launcher is +# required. Inputs are the per-target game packages that # package-windows-game.ps1 produces (the same inputs as the quick test). [CmdletBinding()] param( @@ -8,17 +8,27 @@ param( [Parameter(Mandatory=$true)][string]$LoaderDll, [Parameter(Mandatory=$true)][string]$PackageRoot, [string[]]$Architectures, # default: every target in gpu-targets.json; a subset makes a smaller release - [string]$ArchivePath + [string]$ArchivePath, + [switch]$LocalDevelopment ) $ErrorActionPreference='Stop' . (Join-Path $PSScriptRoot 'gpu-target.ps1') $repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..')) if (!$GamePackagePrefix) { $GamePackagePrefix=Join-Path $repo 'dist/windows-gpu-coverage-game' } $PackageRoot=[IO.Path]::GetFullPath($PackageRoot) +if($LocalDevelopment){ + $buildRoot=[IO.Path]::GetFullPath((Join-Path $repo 'build'))+'\' + foreach($candidate in @($PackageRoot,$ArchivePath) | Where-Object { $_ }){ + if(!([IO.Path]::GetFullPath($candidate)).StartsWith($buildRoot,[StringComparison]::OrdinalIgnoreCase)){ + throw 'Local development packages and ZIPs must stay under ignored build/.' + } + } +} if (Test-Path -LiteralPath $PackageRoot) { throw 'Use a new output directory to avoid mixing releases.' } $git=Get-Command git -ErrorAction SilentlyContinue +$workingTreeDirty=(!$git -or [bool](& git -C $repo status --porcelain)) $commit=if ($git) { (& git -C $repo rev-parse HEAD).Trim() } else { $null } -if ($ArchivePath -and (!$git -or [bool](& git -C $repo status --porcelain))) { throw 'A public ZIP needs git and committed sources.' } +if ($ArchivePath -and !$LocalDevelopment -and (!$git -or [bool](& git -C $repo status --porcelain))) { throw 'A public ZIP needs git and committed sources.' } New-Item -ItemType Directory -Force $PackageRoot | Out-Null $files=[Collections.Generic.List[object]]::new() function Stage([string]$Source,[string]$Relative) { @@ -35,7 +45,7 @@ if (!$selected.Count -or ($Architectures -and $selected.Count -ne @($Architectur foreach ($gpu in $selected) { $arch=$gpu.architecture; $source="$GamePackagePrefix-$arch" $metadata=Get-Content -LiteralPath (Join-Path $source 'package.json') -Raw | ConvertFrom-Json - if ($metadata.architecture -ne $arch -or $metadata.d4rWorkingTreeDirty) { throw "Uncommitted or wrong-target input: $source" } + if ($metadata.architecture -ne $arch -or ($metadata.d4rWorkingTreeDirty -and !$LocalDevelopment)) { throw "Uncommitted or wrong-target input: $source" } if (!$baseline) { $baseline=$metadata } if ($metadata.dlssSha256 -ne $baseline.dlssSha256 -or $metadata.zludaBuild.sourceCommit -ne $baseline.zludaBuild.sourceCommit) { throw 'Input packages do not use the same validated dependencies.' } $objects=0 @@ -83,11 +93,12 @@ $placeholder=Join-Path $PackageRoot 'd4r/ngx/PUT _nvngx.dll HERE.txt' New-Item -ItemType Directory -Force (Split-Path $placeholder) | Out-Null "Copy NVIDIA's _nvngx.dll into this folder. See WINDOWS_README.txt." | Set-Content -LiteralPath $placeholder -Encoding ASCII $files.Add(@{path='d4r/ngx/PUT _nvngx.dll HERE.txt'; sha256=(Get-FileHash -LiteralPath $placeholder -Algorithm SHA256).Hash; version=$null}) -if (Get-ChildItem -LiteralPath $PackageRoot -Recurse -File | Where-Object { $_.Name -eq 'nvngx_dlss.dll' -or ($_.Name -eq '_nvngx.dll' -and $_.DirectoryName -ne (Join-Path $PackageRoot 'd4r')) }) { +if (Get-ChildItem -LiteralPath $PackageRoot -Recurse -File | Where-Object { $_.Name -in @('nvngx_dlss.dll','nvngx_dlssd.dll') -or ($_.Name -eq '_nvngx.dll' -and $_.DirectoryName -ne (Join-Path $PackageRoot 'd4r')) }) { throw 'Proprietary NVIDIA binaries must not be in the release.' } # Read by d4r-check.ps1: every shipped file's hash, so a damaged or mixed install is reported. -$manifest=[ordered]@{schema=1; kind='windows-drag-in'; packageCommit=$commit; binarySourceCommit=$baseline.d4rCommit; +$manifest=[ordered]@{schema=1; kind='windows-drag-in'; localDevelopment=[bool]$LocalDevelopment; + packageWorkingTreeDirty=[bool]$workingTreeDirty; packageCommit=$commit; binarySourceCommit=$baseline.d4rCommit; dependencies=@{optiScalerSourceCommit=$baseline.optiScaler.sourceCommit; zludaSourceCommit=$baseline.zludaBuild.sourceCommit; hipRuntime=$baseline.hipRuntime}; targets=$targets; files=$files} $manifest | ConvertTo-Json -Depth 8 | Set-Content -LiteralPath (Join-Path $PackageRoot 'd4r/package.json') -Encoding UTF8 diff --git a/scripts/windows/prepare-k-native-cache.ps1 b/scripts/windows/prepare-k-native-cache.ps1 new file mode 100644 index 0000000..e80d4c0 --- /dev/null +++ b/scripts/windows/prepare-k-native-cache.ps1 @@ -0,0 +1,57 @@ +[CmdletBinding()] +param( + [Parameter(Mandatory=$true)][string]$DlssDll, + [Parameter(Mandatory=$true)][string]$NativeDirectory, + [Parameter(Mandatory=$true)][string]$OutputDirectory, + [string]$HipRoot, + [string]$EmitterRoot, + [string]$GpuArch='gfx1101', + [string]$Kernel='hiluma_engine_output_depthreg_mvhi_ldr_max_v2_rel' +) +$ErrorActionPreference='Stop' +. (Join-Path $PSScriptRoot 'gpu-target.ps1') +$repo=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '../..')) +[void](Get-D4RGpuTargetInfo $GpuArch) +$DlssDll=(Get-Item -LiteralPath $DlssDll).FullName +$NativeDirectory=(Get-Item -LiteralPath $NativeDirectory).FullName +$OutputDirectory=[IO.Path]::GetFullPath($OutputDirectory) +$buildRoot=[IO.Path]::GetFullPath((Join-Path $repo 'build'))+'\' +if(!$OutputDirectory.StartsWith($buildRoot,[StringComparison]::OrdinalIgnoreCase)){ + throw 'Private generated kernels must stay under ignored build/.' +} +if(Test-Path -LiteralPath $OutputDirectory){throw 'Use a new private cache directory.'} +$expected='3975567b8943c53acce397f2b72380092f84f162d00b0d2c7d08a1025c563983' +if((Get-FileHash -LiteralPath $DlssDll).Hash.ToLowerInvariant() -ne $expected){throw 'Expected pinned DLSS SR 310.9.1.'} +if(!$HipRoot){$HipRoot=Join-Path $repo '.tools/therock-10.2.0a20260929/_rocm_sdk_core'} +if(!$EmitterRoot){$EmitterRoot=Join-Path $repo 'dist/zluda-windows-emitter'} +$objects=@(Get-ChildItem -LiteralPath $NativeDirectory -Filter '*.hsaco' -File) +if($objects.Count -ne 16){throw 'NativeDirectory must contain the baseline 11 K and 5 M objects.'} +foreach($family in @('k','m')){ + foreach($source in Get-ChildItem -LiteralPath (Join-Path $repo "kernels/$family") -Filter '*.hip' -File){ + if(!(Test-Path -LiteralPath (Join-Path $NativeDirectory ($source.BaseName+'.hsaco')))){ + throw "Baseline native directory is incomplete: $($source.BaseName)" + } + } +} +foreach($object in $objects){Assert-D4RCodeObjectTarget $object.FullName $GpuArch} +& (Join-Path $PSScriptRoot 'build-native-texture.ps1') -DlssDll $DlssDll -Kernel $Kernel ` + -HipRoot $HipRoot -ZludaRoot $EmitterRoot -GpuArch $GpuArch -OutputDirectory (Join-Path $OutputDirectory 'texture') +if($LASTEXITCODE){throw 'Private texture build failed.'} +$native=Join-Path $OutputDirectory 'native' +New-Item -ItemType Directory -Path $native | Out-Null +foreach($object in $objects){Copy-Item -LiteralPath $object.FullName -Destination $native} +foreach($marker in @('d4r-native-fp8.txt')){ + if(Test-Path -LiteralPath (Join-Path $NativeDirectory $marker)){ + Copy-Item -LiteralPath (Join-Path $NativeDirectory $marker) -Destination $native + } +} +Copy-Item -LiteralPath (Join-Path $OutputDirectory "texture/$Kernel.hsaco") -Destination $native +& python (Join-Path $repo 'kernels/tools/kernel_manifest.py') $native $DlssDll +if($LASTEXITCODE){throw 'Private native manifest generation failed.'} +@{schema=1; architecture=$GpuArch; privateNvidiaDerivedCode=$true; nativeDirectory=$native; + dlssSha256=$expected; kernel=$Kernel; validation='built only; validate complete frames before game use'; + files=@(Get-ChildItem -LiteralPath $native -File | ForEach-Object { + @{name=$_.Name; sha256=(Get-FileHash -LiteralPath $_.FullName).Hash} + })} | ConvertTo-Json -Depth 5 | Set-Content -LiteralPath (Join-Path $OutputDirectory 'cache.json') -Encoding UTF8 +Write-Host 'Private cache built; no game or existing configuration changed.' +Write-Host "After validation, set [Paths] NativeDir = $native" diff --git a/scripts/windows/rr-model-cache.py b/scripts/windows/rr-model-cache.py new file mode 100644 index 0000000..f6cae96 --- /dev/null +++ b/scripts/windows/rr-model-cache.py @@ -0,0 +1,72 @@ +"""Stamp or verify local RR build artifacts against sources, tools and DLL identity.""" +import argparse +import hashlib +import json +from pathlib import Path +import sys + + +def sha(path): + return hashlib.sha256(path.read_bytes()).hexdigest() + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('action', choices=('write', 'check')) + parser.add_argument('--model', type=Path, required=True) + parser.add_argument('--dll', type=Path, required=True) + parser.add_argument('--preset', choices=('D', 'E'), required=True) + parser.add_argument('--glslang', type=Path, required=True) + parser.add_argument('--bash', type=Path, required=True) + args = parser.parse_args() + repo = Path(__file__).resolve().parents[2] + model = args.model.resolve() + if not model.is_relative_to((repo / 'build').resolve()): + parser.error('model cache must stay under ignored build/') + import numpy + sources = {} + for directory in ('engine', 'vulkan', 'kernels/tools', 'scripts/windows'): + for path in sorted((repo / directory).rglob('*')): + if path.is_file() and path.suffix in ('.py', '.ps1', '.sh', '.comp', '.glsl', '.h', '.inc', '.txt'): + sources[path.relative_to(repo).as_posix()] = sha(path) + identity = dict(schema=1, preset=args.preset, architecture='gfx1101', arithmetic='exact-gfx11', + numpyVersion=numpy.__version__, sources=sources, + tools={name: sha(path) for name, path in ( + ('dll', args.dll), ('glslang', args.glslang), + ('bash', args.bash), ('python', Path(sys.executable)))}) + stamp = model / 'windows-rr-cache.json' + products = {path.name: sha(path) for path in sorted(model.iterdir()) + if path.is_file() and path.name not in (stamp.name, stamp.name + '.tmp')} + for name in ('rr.txt', 'model.json', 'enc0_m.spv', 'dec0_m.spv', 'hkpn.spv', 'enc0.args', 'hkpn.args'): + if name not in products: + raise RuntimeError(f'incomplete model: {name}') + manifest = (model / 'rr.txt').read_text().splitlines() + if (not manifest or manifest[0] != 'D4RR0001' or + f'preset {4 if args.preset == "D" else 5}' not in manifest or + 'arithmetic gfx11' not in manifest): + raise RuntimeError('RR manifest preset/arithmetic does not match requested cache identity') + stages = [line.split() for line in manifest if line.startswith('stage ')] + expected_stages = {'enc0', 'enc1', 'enc2', 'enc3', 'enc4', 'enc5', + 'dec4', 'dec3', 'dec2', 'dec1', 'dec0', 'hkpn'} + if len(stages) != 12 or {fields[1] for fields in stages} != expected_stages: + raise RuntimeError('RR stage list is incomplete or duplicated') + for fields in stages: + for name in (fields[2], fields[4]): + if name != '-' and name not in products: + raise RuntimeError(f'RR stage artifact missing or outside model directory: {name}') + if args.action == 'check': + cached = json.loads(stamp.read_text()) + if cached.get('identity') != identity: + raise RuntimeError('RR cache identity changed; use a new output directory to rebuild') + if cached.get('products') != products: + raise RuntimeError('RR cache artifacts changed; use a new output directory to rebuild') + print(f'RR_CACHE_HIT preset={args.preset} artifacts={len(products)} model={model}') + else: + temporary = stamp.with_name(stamp.name + '.tmp') + temporary.write_text(json.dumps(dict(identity=identity, products=products), indent=2) + '\n') + temporary.replace(stamp) + print(f'RR_CACHE_WRITTEN preset={args.preset} artifacts={len(products)} model={model}') + + +if __name__ == '__main__': + main() diff --git a/scripts/windows/rr-synthetic-inputs.py b/scripts/windows/rr-synthetic-inputs.py new file mode 100644 index 0000000..d57fd33 --- /dev/null +++ b/scripts/windows/rr-synthetic-inputs.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +"""Generate deterministic RR replay inputs. This is a dispatch smoke, not a quality reference.""" +import argparse +import json +import math +from pathlib import Path +import struct + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('output', type=Path) + parser.add_argument('--width', type=int, default=64) + parser.add_argument('--height', type=int, default=64) + parser.add_argument('--frames', type=int, default=3) + parser.add_argument('--output-width', type=int) + parser.add_argument('--output-height', type=int) + args = parser.parse_args() + if not (32 <= args.width <= 1024 and 32 <= args.height <= 1024 and 1 <= args.frames <= 32): + parser.error('width/height must be 32..1024; frames must be 1..32') + if bool(args.output_width) != bool(args.output_height): + parser.error('supply both output dimensions') + ow, oh = args.output_width or args.width * 2, args.output_height or args.height * 2 + if not (1 <= ow <= 2560 and 1 <= oh <= 1440): + parser.error('output must fit 2560x1440') + args.output.mkdir(parents=True, exist_ok=False) + identity = '1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1' + lines = [f'size {args.width} {args.height} {ow} {oh}'] + for frame in range(args.frames): + data = {name: bytearray() for name in ('color', 'motion', 'depth', 'normals', 'roughness', 'diffuse', 'specular')} + for y in range(args.height): + for x in range(args.width): + u, v = x / (args.width - 1), y / (args.height - 1) + noise = math.sin(x * 1.7 + y * 2.3 + frame) * 0.025 + data['color'] += struct.pack('<4e', 0.1 + u + noise, 0.1 + v + noise, 0.2 + u * v, 1) + data['motion'] += struct.pack('<2e', 0, 0) + data['depth'] += struct.pack('