Clear windows branch; preserve previous contents in win-old
This commit is contained in:
1 parent
f0c881985b
commit
73994d4634
311 files changed
-57018
No files matched your search
@@ -1,98 +0,0 @@
|
||||
# Architecture
|
||||
|
||||
d4r keeps NVIDIA's DLSS library unmodified and gives it what it expects: an NGX D3D12 entry point in the game process, a CUDA driver underneath, and CUDA kernels that run. Everything between those points is translation.
|
||||
|
||||
## Components
|
||||
|
||||
| Piece | Where | Role |
|
||||
|---|---|---|
|
||||
| OptiScaler (in GE-Proton) | external | Hooks the game's upscaler call and forwards DLSS requests to an NGX DLL (`NvngxPath`) |
|
||||
| NGX shim `d4r_nvngx.dll` | `tools/d4r_nvngx_shim.cpp` | Implements the NGX D3D12 API. Moves inputs and output between the game's D3D12 resources and CUDA, and drives the official NGX core through its CUDA API |
|
||||
| NGX core + `nvngx_dlss.dll` | NVIDIA, supplied by you | The real DLSS: parameter handling, network selection, the CUDA kernels |
|
||||
| CUDA bridge `nvcuda.dll` | `tools/wine_nvcuda_bridge.c` | A Wine builtin whose Windows exports forward to ZLUDA's Linux `libcuda.so`, plus d4r helpers (Vulkan memory import, asynchronous 2D copies, GPU-side waits, output redirect, linear textures) |
|
||||
| ZLUDA | `patches/zluda` | CUDA driver API on HIP; compiles NVIDIA's PTX to AMDGPU code; serves native kernels in place of PTX kernels |
|
||||
| Native kernels | `kernels/` | RDNA3 implementations of the DLSS network layers and parts of texture kernels |
|
||||
| vkd3d-proton patch | `patches/vkd3d-proton` | Splits a D3D12 command list around DLSS and retains external resources through command allocator completion |
|
||||
| NVAPI identity | `tools/d4r_nvapi_identity.c` | Reports an Ada (sm_89) GPU so NGX selects the network weights matching the PTX ZLUDA compiles |
|
||||
|
||||
## One frame
|
||||
|
||||
With VRAM interop and split frames (the defaults when the patched vkd3d-proton is present):
|
||||
|
||||
1. **The game records DLSS.** Its `EvaluateFeature` call reaches the shim with the game's command list. Into that list the shim records:
|
||||
- Vulkan commands (vkd3d-proton interop) that copy colour, depth, motion vectors and optional exposure into buffers exported to HIP. Linear R11G11B10, RGB10A2, and RGBA8/BGRA8 colour inputs are blitted to RGBA16F; multichannel float exposure is blitted to R32F using its first component when the device supports the conversion.
|
||||
- A frame marker.
|
||||
- A split. vkd3d-proton submits everything the game records after the DLSS call separately, gated on a timeline semaphore reaching this frame's number.
|
||||
- At the start of that second part, a copy of the DLSS result into the game's output texture. Linear R11G11B10, RGB10A2, and RGBA8/BGRA8 outputs are converted from RGBA16F on the GPU. sRGB formats continue through host staging to preserve their existing byte interpretation.
|
||||
2. **The CUDA worker queues DLSS.** The prep thread checks the GPU-written input marker with short CPU sleeps. It drops recorded-but-unsubmitted frames when they time out or their feature retires, before any DLSS work is queued. The CUDA worker then queues:
|
||||
- the input copies into CUDA arrays, or none when NGX samples the buffers in place (`LinearInputs`);
|
||||
- NGX's evaluation (NGX's own CPU synchronisations are elided with `ElideNgxSync`);
|
||||
- the result, written straight into the output buffer by the native output kernel (`DirectOutput`, preset K) or copied there.
|
||||
3. **Release.** When the GPU finishes, the worker signals the timeline semaphore and the rest of the game's frame runs, now with this frame's result.
|
||||
|
||||
The watchdog reports delayed output but never signals an unfinished producer as ready. Retiring features remain registered until their CPU/CUDA jobs drain. The lifetime-aware vkd3d extension retains their staging buffers, imported buffers, conversion images and split semaphore through command-allocator reset or destruction after GPU completion. Discarded recordings are covered too; cleanup no longer relies on a 50 ms delay.
|
||||
|
||||
The shim requires the matching lifetime-aware d3d12.dll and d3d12core.dll, even for host staging. It rejects older runtimes rather than recording references whose lifetime it cannot protect. FrameAge > 0 shows the newest finished result; without VRAM interop, inputs and output are staged through host memory.
|
||||
|
||||
## Why each piece exists
|
||||
|
||||
- **CUDA NGX instead of D3D12 NGX.** NVIDIA's D3D12 path needs NVIDIA's driver. The CUDA path only needs a CUDA driver API, which ZLUDA provides.
|
||||
- **The Ada identity.** NGX picks network weights by GPU architecture. The weights have to match the PTX that ZLUDA compiles, which is sm_89 for DLSS 310.
|
||||
- **Native kernels.** Translating NVIDIA's warp-level matrix code is slow (register pressure, lane shuffles, per-instruction mode switches). Earlier translated K layers also produced non-finite outputs that the final kernel masked. Native layers avoid that path; the compiler now preserves FP16 denormal requirements too, which fixes the translated failure in recorded captures. Numerical and image-quality parity with RTX hardware remains unverified.
|
||||
- **Sleeping readiness checks.** Waiting for input submission before queueing DLSS avoids an uncancellable GPU wait. Explicit output event queries with short sleeps avoid HIP event/context waits that can consume a CPU core. Submillisecond waits use NtDelayExecution because MinGW std::sleep_for can truncate them to zero. Linear inputs and direct output remain available.
|
||||
|
||||
## Configuration
|
||||
|
||||
`config/d4r.ini.default` documents every setting. `scripts/d4r_config.py` turns the file into environment variables for `scripts/run_game_d4r_optiscaler_proton.sh`, and an environment variable that is already set wins. The most useful switches:
|
||||
|
||||
| d4r.ini | Environment | Effect |
|
||||
|---|---|---|
|
||||
| `[DLSS] Model` | `D4R_DLSS_PRESET` | DLSS network: `E` (CNN), `K` (DLSS 4), `M` (DLSS 4.5) |
|
||||
| `[Latency] FrameAge` | `D4R_SHIM_SPLIT_FRAME`, `D4R_SHIM_MAX_IN_FLIGHT` | 0 = same-frame results; higher values pipeline frames |
|
||||
| `[Kernels] NativeKernels` | `D4R_ZLUDA_NATIVE_DIR` | native kernel directory (`fast` / `exact` / `off`) |
|
||||
| `[Kernels] PreferAccuracy` | `D4R_PREFER_ACCURACY` | default off; accuracy variants for every native family and conservative translation/synchronization settings |
|
||||
| `[Interop] VramInterop` | `D4R_SHIM_VRAM_INTEROP` | keep inputs and output in VRAM |
|
||||
| `[Interop] LinearInputs` | `D4R_SHIM_LINEAR_INPUTS` | NGX samples the input buffers in place |
|
||||
| `[Interop] DirectOutput` | `D4R_SHIM_OUTPUT_DIRECT` | the output kernel writes the game-side buffer directly (preset K) |
|
||||
| `[Interop] ElideNgxSync` | `D4R_ELIDE_NGX_SYNC` | skip NGX's internal CPU waits |
|
||||
| `[Paths] JitCacheDir` | `XDG_CACHE_HOME` | where ZLUDA caches compiled kernels |
|
||||
|
||||
## Portable installs (the release zip)
|
||||
|
||||
The release zip (`scripts/package_release.sh`) is unpacked into the folder that holds a game's main `.exe`, like an OptiScaler release. Nothing in the Proton prefix or the system is changed.
|
||||
|
||||
| File | Role |
|
||||
|---|---|
|
||||
| `dxgi.dll`, `OptiScaler.ini` | OptiScaler 0.9.4. Its INI sets DLSS as the DX12 upscaler and `OptiDllPath=d4r`, so OptiScaler loads the shim as `d4r\nvngx.dll`. |
|
||||
| `d3d12.dll`, `d3d12core.dll` | the d4r-patched vkd3d-proton. Proton loads DLLs from the game folder before `system32`. |
|
||||
| `d4r\nvngx.dll`, `d4r\nvcuda.dll` | the shim and the CUDA bridge |
|
||||
| `d4r\zluda\libcuda.so` | ZLUDA |
|
||||
| `d4r\kernels\<gfx target>\` | native kernels and their manifest `d4r-kernels.txt` |
|
||||
| `d4r\d4r.ini` | this game's settings |
|
||||
| `d4r\nvngx_dlss.dll`, `d4r\ngx\_nvngx.dll` | NVIDIA's files (the packager's `D4R_BUNDLE_NVIDIA=0` leaves them for the user to add) |
|
||||
|
||||
**Settings.** When an `d4r.ini` sits next to the shim, the shim turns it into the same environment variables the developer launcher sets, with the release's defaults. A variable that is already set, for example in the launch options, wins. Settings for the Linux side (ZLUDA's and the bridge's) are handed to the bridge through `d4rSetEnv` right after it is loaded, before its first CUDA call.
|
||||
|
||||
**Loading ROCm.** Steam runs GE-Proton 11 inside its container runtime (SteamLinuxRuntime_4), whose library search path has no ROCm. The bridge therefore:
|
||||
- loads HIP, HSA and comgr by path, from `RocmDir` (default: the release's bundled `d4r/rocm`, else `/opt/rocm`);
|
||||
- looks up any dependency they lack in the host's library directories, which the container mounts under `/run/host`;
|
||||
- sets `XDG_CACHE_HOME` only while ZLUDA initialises, so ZLUDA's kernel cache goes to `~/.cache/d4r` without affecting the rest of the game.
|
||||
|
||||
**Native kernel checks.** For each kernel, `d4r-kernels.txt` lists the hash of the DLSS PTX module it was written for. ZLUDA is pointed at a per-process directory, and the bridge adds a kernel to it only when NGX loads a module with a matching hash. A DLSS version whose kernel changed therefore gets ZLUDA's compile of that kernel: slower, but correct. The bridge picks the `gfx` folder from the GPU's KFD topology entry. `DirectOutput` takes effect only while the bridge reports that NGX uses a native `hiluma_engine_output_*` kernel. That kernel is one of the texture kernels built from NVIDIA's PTX, and it is worth about 3 fps for DLSS 4 at Quality.
|
||||
|
||||
**NGX identity and watermark.** A game that initialises NGX with a project ID (Unreal's DLSS plugin does) is passed to the NGX core's `NVSDK_NGX_CUDA_Init_ProjectID` with that ID. In this setup the DLSS library still stamps "DLSS SDK - DO NOT DISTRIBUTE" over its output. The shim sets the SDK's `Disable.Watermark` evaluation parameter unless `[DLSS] ShowWatermark = true` (`D4R_SHIM_WATERMARK=1`).
|
||||
|
||||
**NVAPI.** The launch option `PROTON_FORCE_NVAPI=1` makes Proton enable dxvk-nvapi on the AMD driver and set `WINE_HIDE_AMD_GPU`, so Windows sees an NVIDIA PCI ID. OptiScaler's NVIDIA check accepts that, so the NVAPI identity bridge is only needed by the developer launcher. `DXVK_NVAPI_GPU_ARCH=AD100` is still required, because NGX picks its weights by GPU architecture.
|
||||
|
||||
## Logs
|
||||
|
||||
The launcher writes each run's logs to `~/.cache/d4r-dlss-captures/game-<exe>-<time>/`. `d4r_nvngx.log` holds the shim's log. With `[Debug] Profile = true` it also records one `D4R_PROFILE` line per frame, with the stage timings.
|
||||
|
||||
Output completion uses event queries with 200 us NtDelayExecution sleeps by default. `D4R_SHIM_BLOCKING_SYNC = 0`
|
||||
under `[Env]` restores context synchronization for an A/B check. The profile records
|
||||
`output_sync_wall`, `output_sync_cpu`, and `output_sync_method=event_query_sleep` for the new path.
|
||||
An unavailable or failed event falls back to context synchronization. The old `GpuWait` setting
|
||||
is no longer used: input readiness is checked on the CPU before CUDA work is queued.
|
||||
|
||||
The `d2h` field on this path includes the output synchronization wait, even when direct output
|
||||
skips the array-to-buffer copy.
|
||||
@@ -1,148 +0,0 @@
|
||||
# Building d4r
|
||||
|
||||
These steps produce the pieces the launcher needs: a patched ZLUDA, a patched vkd3d-proton, the NGX shim and CUDA bridge, a staged runtime directory with your NVIDIA files, and the native kernels. The versions below are the ones that were tested; others may need changes.
|
||||
|
||||
| Component | Tested version |
|
||||
|---|---|
|
||||
| ZLUDA | `ee2f25a` (upstream), plus `patches/zluda/0002` through `0007` in order |
|
||||
| vkd3d-proton | `3dfc6f07` (the base GE-Proton11-3 ships), plus `patches/vkd3d-proton/0001` and `0002` |
|
||||
| ROCm | 7.2 (HIP runtime, clang, device libraries) |
|
||||
| Proton | GE-Proton11-3 (with its OptiScaler integration) |
|
||||
| DLSS | `nvngx_dlss.dll` 310.7.0 |
|
||||
|
||||
## 1. ZLUDA
|
||||
|
||||
```sh
|
||||
git clone https://github.com/vosen/ZLUDA zluda && cd zluda
|
||||
git checkout ee2f25a
|
||||
git submodule update --init --recursive
|
||||
git lfs pull
|
||||
for p in 0002 0003 0004 0005 0006 0007; do git apply /path/to/d4r/patches/zluda/$p-*.patch; done
|
||||
# rebuild the device helpers the patches changed (ptx/lib/zluda_ptx_impl*.bc)
|
||||
ZLUDA_SOURCE_ROOT=$PWD ROCM_ROOT=/opt/rocm /path/to/d4r/scripts/build_zluda_ptx_helpers.sh
|
||||
LIBRARY_PATH=/opt/rocm/lib cargo build --release -p zluda
|
||||
LIBRARY_PATH=/opt/rocm/lib cargo build --release -p ptx --example d4r_emit
|
||||
mkdir -p ~/.cache/d4r-zluda-current
|
||||
cp target/release/libnvcuda.so ~/.cache/d4r-zluda-current/
|
||||
ln -sf libnvcuda.so ~/.cache/d4r-zluda-current/libcuda.so
|
||||
```
|
||||
|
||||
Build the release ZLUDA library on a system or in a container with GLIBC 2.41 or older. A binary
|
||||
linked on a newer system can require newer GLIBC symbols even when the ZLUDA source does not need new
|
||||
GLIBC features. Before packaging, check it with
|
||||
`scripts/check_glibc_compat.sh 2.41 /path/to/libnvcuda.so`. The release packager runs the same
|
||||
check on ZLUDA, the Wine CUDA bridge, and every bundled ROCm library. Test the rebuilt library
|
||||
with the D3D12 harness and in a game before publishing a release.
|
||||
|
||||
The launcher looks for ZLUDA in `D4R_ZLUDA_DIR` (default `~/.cache/d4r-zluda-current`, or `ZludaDir` in d4r.ini).
|
||||
|
||||
What the patches add:
|
||||
|
||||
- **0002**: the CUDA driver API surface NGX and DLSS use (arrays, textures, surfaces, 1010102 formats, launch parameter buffers), the PTX features DLSS kernels need, and module dumps for debugging (`D4R_ZLUDA_DUMP_DIR`).
|
||||
- **0003**: an implicit 256-thread launch bound for kernels without PTX bounds (removes massive register spilling, `D4R_ZLUDA_IMPLICIT_MAX_BLOCK`) and f16 tensor-core MMA on RDNA3 WMMA (`D4R_ZLUDA_WMMA`).
|
||||
- **0004**: the native kernel override hook (`D4R_ZLUDA_NATIVE_DIR`, see [native-kernels.md](native-kernels.md)), FP8 MMA on WMMA (`D4R_ZLUDA_WMMA_FP8`), optional elision of per-instruction denormal mode switches (`D4R_ZLUDA_IGNORE_DENORMAL`), inlined image helpers, and linking extra bitcode into a PTX module (`D4R_ZLUDA_EXTRA_BC`, used by the texture-kernel build).
|
||||
- **0005**: a null texture object (CUDA handle 0) reads as zeros, as on NVIDIA GPUs, instead of faulting the GPU. DLSS samples absent optional inputs that way in some configurations (low-resolution motion vectors without HDR, as in Ghost of Tsushima).
|
||||
- **0006**: `m16n8k8` f16 MMAs (DLSS 3 CNN, presets E/F) on RDNA3 WMMA like the k16 ones (`D4R_ZLUDA_WMMA_K8=0` disables it); weight-image slots for native prep kernels (`d4r_prep_key_at`, `d4r_prep_key_slots`); and wave64 compilation for offline texture-kernel builds (`D4R_ZLUDA_WAVE64=1`, with wave64 builds of the helper bitcode). `scripts/build_zluda_ptx_helpers.sh` now writes the `_w64` helper variants too.
|
||||
- **0007**: gfx12 WMMA layout lowering, optional native e4m3 FP8 WMMA (`D4R_ZLUDA_WMMA_FP8_NATIVE=1`), and an architecture argument for `d4r_emit`. `D4R_ZLUDA_WMMA_LAYOUT=12` on gfx11 is a validation shim, not a release setting.
|
||||
|
||||
When linking on a system with ROCm libraries outside the default search path, include their library directory in `LIBRARY_PATH`. The build also needs the appropriate ROCm link libraries. `CARGO_BUILD_JOBS=8` caps parallel Rust compilation if memory is limited.
|
||||
|
||||
## 2. vkd3d-proton
|
||||
|
||||
```sh
|
||||
scripts/build_vkd3d_proton_d4r.sh ~/.cache/d4r-vkd3d-d4r
|
||||
```
|
||||
|
||||
The patch lets the shim split the game's command list at the DLSS call, so the rest of the frame waits (at queue level) for DLSS instead of showing the previous frame's result. Point `D4R_VKD3D_DIR` (or `VkD3DDir` in d4r.ini) at the output. Without it the shim falls back to showing a one-frame-old result.
|
||||
|
||||
## 3. Shim, bridge and NVAPI identity
|
||||
|
||||
```sh
|
||||
scripts/build_d4r_nvngx_shim.sh # build/d4r_nvngx.dll (needs x86_64-w64-mingw32-g++ and clang-cl)
|
||||
scripts/build_wine_nvcuda_bridge.sh # build/wine-nvcuda/ (needs winegcc and winebuild)
|
||||
```
|
||||
|
||||
The launcher builds the small NVAPI identity bridge (`scripts/build_d4r_nvapi_identity.sh`) itself.
|
||||
|
||||
## 4. Runtime directory
|
||||
|
||||
```sh
|
||||
scripts/install_d4r_runtime.sh /path/to/_nvngx.dll /path/to/nvngx_dlss.dll
|
||||
```
|
||||
|
||||
This stages the shim, the bridge, the NGX core and the DLSS feature library in `D4R_RUNTIME_DIR` (default `~/.local/share/d4r-dlss`, or `RuntimeDir` in d4r.ini). The NVIDIA files come from your own sources, for example an NVIDIA driver package (NGX core) and a game or the DLSS SDK (feature library).
|
||||
|
||||
## 5. Native kernels
|
||||
|
||||
```sh
|
||||
D4R_ROCM_DIR=/opt/rocm \
|
||||
D4R_DLSS_DLL=/path/to/nvngx_dlss.dll \
|
||||
D4R_ZLUDA_EMIT=/path/to/zluda/target/release/examples/d4r_emit \
|
||||
kernels/build.sh all kernels/out/native
|
||||
```
|
||||
|
||||
`kernels/out/native` then holds one code object per replaced DLSS kernel; set `NativeKernelDirFast` in d4r.ini (or `D4R_ZLUDA_NATIVE_DIR`) to it. `kernels/build.sh k` or `m` builds only the network layers and needs neither the DLL nor ZLUDA. `kernels/build.sh l` builds L's shared network layers and unfolded texture variants; it needs the DLL and emitter. The texture kernels (`tex`, including L) extract PTX from your DLL into `kernels/extracted/` and compile it offline for `D4R_GPU_ARCH` through `D4R_ZLUDA_EMIT`; that directory and the build output are git-ignored and must not be redistributed. On gfx12, build a second variant with `D4R_NATIVE_FP8=1` and place it in an `<arch>-fp8` folder.
|
||||
|
||||
To add the accuracy option to a developer set, repeat the build with `D4R_PREFER_ACCURACY=1` and output `kernels/out/native/accuracy` (multi-target builds: `kernels/accuracy/<arch>` and `<arch>-fp8`). Use a separate empty directory; successfully built accuracy sets receive `d4r-accuracy.txt`. Enable `[Kernels] PreferAccuracy = true` and restart. The option defaults to false and never substitutes the fast set when accuracy binaries are absent.
|
||||
|
||||
## 6. Configure and play
|
||||
|
||||
The first launch copies `config/d4r.ini.default` to `~/.config/d4r/d4r.ini`. Set the `[Launch]` paths (Proton, the game's compatdata prefix and the game executable), the `[Paths]` above, and the model in `[DLSS]`, then run:
|
||||
|
||||
```sh
|
||||
scripts/d4r_play.sh
|
||||
```
|
||||
|
||||
In the game, pick DLSS as the upscaler (OptiScaler intercepts it). Every setting in the file can also be given as an environment variable, which takes precedence; `D4R_NO_CONFIG=1` ignores the file.
|
||||
|
||||
## 7. Package a release
|
||||
|
||||
```sh
|
||||
scripts/fetch_rocm_runtime.sh # -> ~/.cache/d4r-rocm-runtime (AMD's ROCm 7.2.4 runtime, checksummed)
|
||||
D4R_OPTISCALER=/path/to/OptiScaler_0.9.4.7z \
|
||||
D4R_DLSS_DLLS=/path/to/310.7/nvngx_dlss.dll:/path/to/310.9/nvngx_dlss.dll \
|
||||
D4R_BUNDLE_DLSS=/path/to/nvngx_dlss.dll D4R_BUNDLE_NGX=/path/to/_nvngx.dll D4R_BUNDLE_TEX=kernels/out/native \
|
||||
D4R_ZLUDA_DIR=~/.cache/d4r-zluda-current D4R_VKD3D_DIR=~/.cache/d4r-vkd3d-d4r D4R_ROCM_DIR=/opt/rocm \
|
||||
D4R_ZLUDA_EMIT=/path/to/zluda/target/release/examples/d4r_emit \
|
||||
scripts/package_release.sh # -> dist/d4r-<version>.zip
|
||||
```
|
||||
|
||||
The script:
|
||||
- builds the shim, the bridge and both fast and accuracy network-layer kernels for gfx1100–gfx1103 and gfx1200–gfx1201 by default (`D4R_GPU_ARCHS` can select fewer targets); each gfx12 target also gets an `<arch>-fp8` variant;
|
||||
- writes the kernel manifest from the DLLs you list (it records hashes of their PTX, nothing else);
|
||||
- stages OptiScaler as `dxgi.dll` with the settings in `packaging/optiscaler.settings`;
|
||||
- adds NVIDIA's two DLLs and any supplied texture kernels (built from NVIDIA's PTX by `kernels/build.sh tex`); builds accuracy texture sets with `D4R_ZLUDA_EMIT` unless marked prebuilt sets are supplied in `D4R_BUNDLE_TEX/accuracy/<target>`;
|
||||
- zips the result together with the ZLUDA and vkd3d-proton builds, the ROCm runtime (as `d4r/rocm`), `packaging/d4r.ini`, the licenses and the patches.
|
||||
|
||||
The NVIDIA files are not covered by d4r's license; redistributing them is up to whoever publishes the zip. `D4R_BUNDLE_NVIDIA=0` builds `d4r-<version>-nonvidia.zip` without them and without the texture kernels. [architecture.md](architecture.md#portable-installs-the-release-zip) describes how the installed files work together.
|
||||
|
||||
### GLIBC 2.41 release builds
|
||||
|
||||
Build the pinned environment with:
|
||||
|
||||
```sh
|
||||
docker build -f packaging/build/Dockerfile.glibc241 -t d4r-build:glibc241 packaging/build
|
||||
```
|
||||
|
||||
Inside that image, `scripts/build_release_glibc241.sh` rebuilds the GPU device helpers, ZLUDA and its LLVM, `d4r_emit`, the NGX shim, Wine CUDA bridge, patched vkd3d-proton, and performance/accuracy texture sets for every release target. Packaging then builds both network sets, checks all bundled Linux libraries against 2.41, and records the toolchain in `d4r/source/BUILD_INFO.txt`.
|
||||
|
||||
Mount the repository at `/work`, ROCm's compiler/headers/device libraries at `/opt/rocm`, and an official Rust toolchain (1.98.0 used for 0.1.3) at `/opt/rust`, with `/opt/rust/bin` on `PATH`. Keep toolchain and third-party runtime inputs read-only. Supply the normal package inputs listed above and these build settings:
|
||||
|
||||
| Variable | Input |
|
||||
|---|---|
|
||||
| `D4R_RELEASE_BUILD_ROOT` | writable directory under `/work/build/` |
|
||||
| `D4R_ZLUDA_SRC` | isolated checkout inside that directory, with both pinned LLVM and HiGHS submodules, the real OCKL LFS payload, and patches `0002`–`0007` applied |
|
||||
| `D4R_VKD3D_SRC` | isolated vkd3d-proton checkout inside that directory, with its submodules and patches `0001` and `0002` applied |
|
||||
| `CARGO_HOME` | writable build-local Cargo cache; prefetch the locked dependencies for an offline build |
|
||||
| `D4R_ROCM_DIR` | `/opt/rocm` |
|
||||
| `D4R_ROCM_LINK_STUBS` | optional directory for additional ROCm link libraries |
|
||||
|
||||
Run `bash scripts/build_release_glibc241.sh` inside the container. The script checks that the build system actually reports `glibc 2.41`, rejects external source-cache checkouts, builds with the locked Cargo dependencies offline, and runs the configuration tests before packaging. The ZIP and checksum go in `$D4R_RELEASE_BUILD_ROOT/dist/`; logs and `toolchain.txt` remain in the build directory. AMD's bundled ROCm runtime, OptiScaler and NVIDIA's libraries remain supplied binaries; the Linux ABI check covers the bundled ROCm libraries too.
|
||||
|
||||
`D4R_BUNDLE_TEX` accepts the older flat directory for gfx1101, or a directory with per-target subdirectories (`gfx1100/`–`gfx1103/`, `gfx1200/`, `gfx1201/`, plus `gfx1200-fp8/` and `gfx1201-fp8/`). Build each texture set with `D4R_GPU_ARCH` and `D4R_ZLUDA_EMIT`; the `-fp8` sets also need `D4R_NATIVE_FP8=1`. `d4r_emit` targets those GPUs offline. Missing texture kernels fall back to ZLUDA on that target; the network-layer kernels are still included. Only the RX 7700 XT has been tested on real hardware.
|
||||
|
||||
## Checks
|
||||
|
||||
- `scripts/check_environment.sh` lists the tools, GPU and Proton builds it finds.
|
||||
- The D3D12 harness (`scripts/run_d3d12_dlss_harness_proton.sh`) drives DLSS outside a game.
|
||||
- Native kernels have their own validation path; see [native-kernels.md](native-kernels.md).
|
||||
@@ -1,136 +0,0 @@
|
||||
# Native kernels
|
||||
|
||||
The native kernels are RDNA3 (gfx11) and RDNA4 (gfx12) code objects that ZLUDA runs in place of specific DLSS kernels. Each one has the same name, launch shape and parameter block as the PTX kernel it replaces, and reads the same buffers, including the network weights inside NVIDIA's DLL. No weights or NVIDIA code are stored here.
|
||||
|
||||
## The override hook (patches/zluda/0004)
|
||||
|
||||
With `D4R_ZLUDA_NATIVE_DIR=DIR`, whenever NGX loads a PTX module and asks for kernel `NAME`, ZLUDA looks for `DIR/NAME.hsaco` and uses its kernel `NAME` instead. The code object can export:
|
||||
|
||||
| Symbol | Meaning |
|
||||
|---|---|
|
||||
| `NAME_prep` kernel | launched first on the same stream, with the same parameters (typically re-lays out weights) |
|
||||
| `u32 d4r_prep_blocks` | grid size of the prep kernel (128 threads per block) |
|
||||
| `u32 d4r_prep_key_offset` | byte offset of a u64 in the parameter block; the prep is skipped while that value (the weights pointer) repeats (0 = no key) |
|
||||
| `u32 d4r_prep_key_at` | the same as offset + 1, so a key at offset 0 can be named (M's layers keep their weights pointer there) |
|
||||
| `u32 d4r_prep_key_slots` | N > 0: the kernel keeps one prepared image per key for up to N keys, so the prep runs once per weight set (the six enc3 tube blocks); keys beyond N share an overflow image and are prepared on every launch |
|
||||
| `u32 d4r_block_z` | replaces the launch's block z dimension (more waves per window) |
|
||||
| `u32 d4r_grid_x` | replaces the grid (persistent kernels) |
|
||||
|
||||
Kernels without a file in `DIR` are compiled from PTX as usual, so a partial set works.
|
||||
|
||||
**Release directories.** A directory that holds `d4r-kernels.txt` (or `<gfx target>/d4r-kernels.txt`) is checked before use:
|
||||
- `kernels/tools/kernel_manifest.py DIR nvngx_dlss.dll...` writes the manifest. For each `NAME.hsaco` it records the FNV-1a 64 hash of the PTX module that defines `.entry NAME`, taken from each DLL given.
|
||||
- The CUDA bridge serves a kernel only after NGX has loaded a module with one of the listed hashes.
|
||||
- It picks the KFD GPU with the most SIMDs, then selects that GPU's target folder. `D4R_GPU_ARCH` overrides the choice. On gfx12, `D4R_ZLUDA_WMMA_FP8_NATIVE=1` selects the `<arch>-fp8` folder.
|
||||
|
||||
The release is built this way, with hashes from DLSS 310.7.0 and 310.9.1. The PTX of every replaced kernel is identical in those two versions.
|
||||
|
||||
## Families
|
||||
|
||||
**DLSS 4, preset K (`kernels/k`, `dltss_pwin_*`).**
|
||||
- **Network:** a Swin-style U-Net of eleven layers over 8×8 token windows. There are encoders enc0–enc4 with 2×2 patch merging, a bottleneck dec5, and decoders dec4–dec0 with patch expansion and skip inputs. The window attention is either learned (query × key plus a bias table) or position-only (a fixed table times the values).
|
||||
- **Templates:**
|
||||
- `pwin_layer.h`: four waves per window, each owning a 16-token tile.
|
||||
- `pwin_pos.h`: position-only layers with two token tiles per wave, which halves weight traffic.
|
||||
- `pwin_wide.h`: the deep layers, which have only 6–77 windows per frame. It uses 4·NG waves per window, split by token tile and channel group, so the GPU stays busy.
|
||||
- **Weights:** prep kernels expand the weights into WMMA operand images once.
|
||||
|
||||
**DLSS 4.5, presets L/M (`kernels/m`, `rrlite_*`).**
|
||||
- **Network:** the Swin blocks of DLSS 4.5, whose weights are FP8. Their prep kernels expand the weights to f16 WMMA operands, once per weight set.
|
||||
- **Template:** `swin_block.h` covers encoders, the tube-shaped enc3 and decoders.
|
||||
- **Output encoding:** the FP8 output is encoded two values at a time with packed 16-bit operations (`enc8x2`, exhaustively equal to the scalar encoder), and the 2×2 patch merge reads the rounded f16 values the codes decode to, from a row layout without LDS bank conflicts, instead of decoding the bytes again in every wave.
|
||||
- **Weight loads:** enc1 forms each weight tile's address in scalar registers (`SWIN_SCALAR_BLOAD`); the 8-wave layers are faster without it.
|
||||
|
||||
**Preset L texture variants.** L uses unfolded `rrlite_enc0_4x4_*`, `rrlite_dec0_4x4`, and `rrlite_post_3_*` kernels. The L build keeps their full neural arithmetic and replaces surface stores with the existing native format-conversion functions. M's folded enc0 tail and dec0 head cannot be used for these variants. All four input flag combinations and all eight post variants are built, along with the shared downsample kernels. `all` and `tex` include these variants; `l` builds the shared Swin layers plus only the L texture set. L remains experimental; these replacements do not establish RTX parity or game performance.
|
||||
|
||||
**Motion mitigation.** `[Kernels] NativeSwinEncoders = false` (`D4R_NATIVE_SWIN_ENCODERS=0`) bypasses only `rrlite_enc1_4x4` and `rrlite_enc2_4x4` in the native manifest. L/M then use the original translated PTX for those encoders, retaining native tube, decoder and texture kernels. Keep `PreferAccuracy = true` for the tested conservative path. It reduced the extra building-edge trails in a 64-frame moving Townfall capture at 853×480 → 2560×1440 on gfx1101; it does not recover detail absent from the low-resolution input or establish RTX parity. The default remains `true` for speed. Flat developer sets without manifests fall back entirely when this switch is off; add a manifest to keep selective acceleration.
|
||||
|
||||
Initial validation: a gfx1101 fast L build completed two Ultra Performance harness frames (192×108 → 576×324, DLSS 310.7). Its finite, nonzero RGBA16F output matched the original translated L texture kernels byte for byte with the same native Swin layers. A gfx1201 FP8 accuracy L set compiled successfully; RDNA4 hardware and 4K game output have not been tested. Full packaging rebuilds missing L variants when given an older texture bundle.
|
||||
|
||||
## RDNA4
|
||||
|
||||
`kernels/common/wmma_layout.h` selects the WMMA operand and accumulator layout. gfx12 uses eight f16 values per lane in each K half; the accumulator rows are `i + 8·half`. The gfx11 path retains its original layout. `D4R_WMMA_LAYOUT=12` on gfx11 is a test shim: it exercises gfx12 indexing but executes gfx11 WMMA, so its replay output can be compared byte for byte with the existing gfx11 build.
|
||||
|
||||
The gfx12 M variant can use native e4m3 FP8 WMMA with `D4R_NATIVE_FP8=1`. Its activations are requantized to e4m3 at operand load, and its prepared weights remain bytes. The matching ZLUDA and texture-tail variant uses `D4R_ZLUDA_WMMA_FP8_NATIVE=1` / `D4R_TEX_FP8=1`; the release bridge chooses the `-fp8` kernel folder. `NativeFp8` in d4r.ini controls that choice and defaults to on. The f16 widening path remains available.
|
||||
|
||||
The gfx11 refactor and gfx12-layout shim matched the recorded gfx11 replays and 88-frame K/M harness images byte for byte on the RX 7700 XT. rocjitsu gfx1201 replay comparisons put the native K layers within 96–109 dB PSNR of gfx11, and M differed in 0.001–0.3% of e4m3 bytes. These are emulator results, not RDNA4 hardware results. rocjitsu's FP8 arithmetic is not hardware-checked; bit-exactness, speed and driver stability on an RDNA4 GPU remain unverified.
|
||||
|
||||
For ZLUDA-compiled code, compare rocjitsu runs with other rocjitsu runs: the emulator does not reproduce the denormal-flush mode of those code objects, so a GPU byte comparison is not a valid arithmetic check. Captures with texture or surface objects must not be sent to the replay tools; the standalone `tail_check.hip` and the full D3D12 harness cover those tails.
|
||||
|
||||
**Texture kernels (`kernels/tex`).**
|
||||
- **The problem:** some DLSS kernels are mostly texture sampling and scalar maths that ZLUDA already compiles well, apart from a few slow parts.
|
||||
- **The approach:** for those, `make_ptx.py` edits NVIDIA's PTX (extracted from your DLL at build time):
|
||||
- surface stores become calls into `tex_common.h`;
|
||||
- the `roundf` idiom that forces ZLUDA into strict-FP mode is rewritten exactly;
|
||||
- for M's enc0 and dec0, a range of the kernel is replaced by a native tail or head.
|
||||
- **Build:** ZLUDA's `d4r_emit` compiles the edited PTX for `D4R_GPU_ARCH` with the HIP bitcode linked in (`D4R_ZLUDA_EXTRA_BC`), and the resulting code object is saved. This is an offline per-target build.
|
||||
- **Every flag combination:** DLSS picks kernel variants by the game's settings (motion vectors at render or display resolution, HDR or LDR input, inverted or regular depth, ...). `kernels/build.sh` builds all of them: 24 K output kernels, 8 M post, 4 M downsample and 4 M enc0 kernels. enc0's native tail is spliced into each variant at its own line, with the registers read off the variant's PTX (`make_ptx.py` checks that the code after the cut matches the reference variant line for line).
|
||||
- **Wave64:** kernels without MMAs can be compiled as wave64 (`D4R_ZLUDA_WAVE64=1`, ZLUDA patch 0006): each wave runs two CUDA warps, and RDNA3 issues FP32 work for all 64 lanes at once. The post and K output kernels are built this way (post 0.89 → 0.77 ms), with bit-identical results.
|
||||
- **Output redirect:** the kernel that writes a preset's result can write it straight into the shim's output buffer instead of a CUDA array: `hiluma_engine_output_*` for K, `rrlite_downsample_kernel_*` for M (M's post kernel works at 3840×2160; the downsample produces the output). See `D4R_SHIM_OUTPUT_DIRECT` in [architecture.md](architecture.md).
|
||||
|
||||
## Numerics
|
||||
|
||||
The conservative kernels round their f16 accumulator after each MMA step (k16 for K, k32 for M). The fast kernels keep f32 accumulators through a chain (`PWIN_F32ACC`, `SWIN_F32ACC`); RDNA3 M also skips intermediate FP8 re-quantization (`SWIN_NO_Q8`). Wider arithmetic changes the network's intermediate values; it does not establish better image quality. Recorded fast-versus-conservative replays were close (about 66 dB PSNR), but that is not an RTX reference comparison or a guarantee for all scenes.
|
||||
|
||||
The installed K set uses f32 accumulation for enc0–enc2 and dec0–dec2 and exact rounding for the deep layers. The M set uses the fast numerics throughout.
|
||||
|
||||
**`[Kernels] PreferAccuracy = true`** (default `false`, environment `D4R_PREFER_ACCURACY=1`) selects a separate accuracy set for all K/M network layers and all texture/output variants, on every supported target, including gfx12 FP8. K disables `PWIN_F32ACC`; M restores FP8 quantization and rounds each k32 accumulator to f16. Texture builds use wave32 and retain the original denormal requirements; the existing exact round-half-away rewrite is retained. Native texture heads/tails already round their accumulators per k32 step. The bridge also disables `IgnoreDenormals`, translated f32 accumulator shadows, wave64 translation and NGX synchronization elision before ZLUDA loads, including when native kernels are off or fail their PTX hash check. Other interop and latency settings remain independent.
|
||||
|
||||
The bridge selects `kernels/accuracy/<target>` (or `<target>-fp8`). Accuracy directories carry a `d4r-accuracy.txt` marker written only after a successful build. A marked flat developer directory also works. Missing accuracy variants fall back to translated PTX and are logged; the bridge never substitutes fast native binaries. Restart the game when changing the setting. The mode uses a separate `d4r-accuracy` JIT cache under the configured cache directory so older runtimes cannot reuse experimental fast-math results. The first accuracy run may compile new kernels.
|
||||
|
||||
This mode aims to preserve NVIDIA's arithmetic, not to promise bit-identical RTX output: matrix accumulation order differs across hardware, and the shim still canonicalizes input formats and does not forward the optional transparency/current-color-bias masks. RTX parity requires identical captured inputs, library version, preset and temporal sequence on NVIDIA hardware.
|
||||
|
||||
## Building
|
||||
|
||||
```sh
|
||||
kernels/build.sh k # DLSS 4 layers (ROCm clang only)
|
||||
kernels/build.sh m # DLSS 4.5 layers
|
||||
kernels/build.sh l # L shared layers + unfolded textures (needs DLL and D4R_ZLUDA_EMIT)
|
||||
kernels/build.sh tex # texture kernels (needs D4R_DLSS_DLL and D4R_ZLUDA_BUILD)
|
||||
kernels/build.sh all DIR # everything into DIR (default kernels/out/native)
|
||||
D4R_PREFER_ACCURACY=1 kernels/build.sh all DIR/accuracy # conservative versions of every family
|
||||
```
|
||||
|
||||
`D4R_GPU_ARCH` selects one target for this standalone build (default gfx1101). The release script builds the network layers for gfx1100–gfx1103 and gfx1200–gfx1201 by default and puts each set in its own directory. The network kernels need gfx11 or gfx12 WMMA. Texture-kernel builds use `D4R_ZLUDA_EMIT` to generate code objects for the selected target without that GPU. Set `D4R_NATIVE_FP8=1` on gfx12 for the matching FP8 M and texture variants.
|
||||
|
||||
The release includes both fast and accuracy network sets. Full releases also include accuracy texture sets: supply them in `D4R_BUNDLE_TEX/accuracy/<target>` or set `D4R_ZLUDA_EMIT` so packaging builds them. Build accuracy sets into a separate directory; the builder refuses to mark a directory containing unmarked older binaries as accurate.
|
||||
|
||||
## Validating a kernel
|
||||
|
||||
1. **Capture launches.** Set `D4R_CUDA_REPLAY_DUMP_DIR` (with `D4R_CUDA_REPLAY_DUMP_FILTER=<kernel name>`) while running the D3D12 harness or a game. The bridge then writes each matching launch as `manifest.txt`, `args.bin` and one `alloc-N.bin` per buffer.
|
||||
2. **Run the native kernel on a capture.** Build `kernels/tools/dump_runner.cpp` with hipcc. Then run:
|
||||
|
||||
```sh
|
||||
PREP_GRID=<d4r_prep_blocks> dump_runner NAME.hsaco NAME <capture> <out> 30
|
||||
```
|
||||
|
||||
It runs the prep and main kernels, saves every buffer after the first launch, and times 30 launches. The replay tool refuses captures with texture or surface objects; use the full harness for those kernels.
|
||||
3. **Compare against a reference.** `kernels/tools/pwin_model.py` (K) and `swin_model.py` (M) are numpy models of the layers, written stage by stage against `ptxsim.py`, a small vectorised PTX interpreter that runs NVIDIA's kernels on the CPU. A bit-exact variant should match the model within f16 rounding; after any change, compare the new build's buffers with the previous build's.
|
||||
4. **Check the whole pipeline.** Replay captured frames through the harness with both kernel sets and compare the outputs with `kernels/tools/psnr.py`. `D4R_CUDA_KERNEL_PROFILE=1` makes the bridge time every kernel; `kernels/tools/kprof.py` summarises the log per frame.
|
||||
|
||||
## Per-kernel cost
|
||||
|
||||
Median GPU time per frame at Quality (1706×960 → 2560×1440, RX 7700 XT), from `D4R_CUDA_KERNEL_PROFILE` in the D3D12 harness (flags as in Townfall; frames 21–40). The profiler's per-launch events add a little to every kernel, so totals are slightly above the in-game cost. "Before" is release 0.1.1.
|
||||
|
||||
| DLSS 4 (K) | before | now | DLSS 4.5 (M) | before | now |
|
||||
|---|---|---|---|---|---|
|
||||
| hiluma output (texture kernel) | 0.92 | 0.89 | enc3 tube (6 launches) | 1.62 | 1.57 |
|
||||
| dec0 | 0.33 | 0.32 | enc1 | 1.41 | 1.27 |
|
||||
| enc0 | 0.31 | 0.31 | dec1 | 1.44 | 1.43 |
|
||||
| dec1 | 0.26 | 0.26 | enc2 | 0.87 | 0.77 |
|
||||
| hiluma input (ZLUDA) | 0.25 | 0.24 | post (texture kernel) | 0.88 | 0.77 |
|
||||
| enc1 | 0.23 | 0.22 | dec2 | 0.84 | 0.82 |
|
||||
| enc2, dec2 | 0.12, 0.10 | 0.12, 0.10 | enc0 (texture kernel) | 0.64 | 0.63 |
|
||||
| enc3, dec3, enc4, dec4, dec5 | 0.07–0.09 each | 0.07–0.09 each | dec0 (texture kernel) | 0.64 | 0.63 |
|
||||
| NGX exposure and misc | 0.1 | 0.1 | downsample, NGX misc | 0.32 | 0.33 |
|
||||
| **total** | **3.10** | **2.97** | **total** | **9.04** | **8.23** |
|
||||
|
||||
Runs of the same build vary by about ±3% per kernel. M additionally skips its output copy now (direct output through the downsample kernel), which is not a kernel and not in the table. Games whose flags differ from Townfall's (motion vectors at render resolution, LDR input, regular depth) gain more: those kernel variants used to run as plain ZLUDA compiles (K 3.6–4.6 ms → 2.8–3.0 ms, M −0.5 to −0.7 ms per frame).
|
||||
|
||||
## Experimental thin-feature motion coverage
|
||||
|
||||
`[Interop] MotionVectorDilation = 1` or `2` (`D4R_MOTION_DILATION`) extends nearby foreground motion into pixels whose depth otherwise belongs to the background. The value selects the opaque-surface radius in render pixels. Both enabled values also fill sky gaps using the nearest foreground pixel within an eight-render-pixel circle (far depth 0 for reversed Z, 1 for normal Z). This is the wider sky fill from the comparison; it can strengthen trails in some frames and remains opt-in through `MotionVectorDilation`. This is a depth-guided approximation to better thin-feature motion coverage, not engine-side conservative rasterization. It improved the captured Townfall rooftop where the earlier native-encoder fallback did not resolve the artifact.
|
||||
|
||||
The d4r-owned GPU kernel preserves the original depth/motion buffers and writes a separate RG16F velocity texture. The worker waits for its completion before NGX evaluates. No per-frame CPU readback is needed. It requires same-frame linear VRAM inputs, full-resolution unjittered motion vectors and zero subrect bases. Unsupported features or unavailable kernels keep the original vectors. The default is `0` (off); larger radii can affect disocclusion and unrelated foreground edges. The method does not recreate geometry missing from every input frame or establish RTX parity.
|
||||
|
||||
`scripts/build_wine_nvcuda_bridge.sh` embeds the support kernels when `D4R_ROCM_DIR` points to ROCm clang. All six gfx110x/gfx120x targets compile; physical validation is currently gfx1101 only. A bridge built without the support kernels reports the feature unavailable rather than changing inputs. Optional GPU regressions cover forward/reversed depth, two radii, jitter, padded rows and preservation of input buffers; see `tests/test_motion_kernel_gpu.py`.
|
||||
@@ -1,63 +0,0 @@
|
||||
# Performance
|
||||
|
||||
All frame rates and kernel timings on this page were measured on an RX 7700 XT (gfx1101). RDNA4 (gfx1200/gfx1201) has compile and emulator validation only; no RDNA4 frame rate, latency, or kernel timing has been measured. Native FP8 may change both arithmetic and cost, so the gfx11 results cannot be projected to it.
|
||||
|
||||
## Method
|
||||
|
||||
- **Hardware and settings:** Radeon RX 7700 XT (RDNA3, 54 CUs), Ryzen 9 5900XT, Linux 6.18. SILENT HILL Townfall at 2560×1440 output.
|
||||
- **Route:** every run plays the same scripted 62-second walk through a street, with fog, wires, fences and signage.
|
||||
- **Frame rate:** from MangoHud's per-frame log over the walk, as frames divided by the sum of frame times.
|
||||
- **Pairing:** runs are compared back-to-back in one session, because repeated runs of an identical setup vary by about 1%.
|
||||
- **Screen recording:** it costs a few fps, so recorded videos show slightly lower numbers than the table.
|
||||
- **Latency:** all DLSS numbers are same-frame (frame age 0). Every frame shows its own DLSS result, as with a native upscaler.
|
||||
- **Upscaler modes:** every mode uses OptiScaler's render-ratio override (1.5, 1.72, 2.0, 3.0), so the result does not depend on the DLSS mode chosen in the game.
|
||||
|
||||
## Results
|
||||
|
||||
| Mode (render resolution) | DLSS 3 CNN (E) | DLSS 4 (K) | DLSS 4.5 (M) | FSR 4\* |
|
||||
|---|---|---|---|---|
|
||||
| Quality (1705×960) | **71.7** | 67.9 | 49.3 | 76.0 |
|
||||
| Balanced (1488×837) | **80.8** | 75.9 | 58.0 | 84.5 |
|
||||
| Performance (1280×720) | **89.7** | 84.1 | 69.0 | 94.0 |
|
||||
| Ultra Performance (853×480) | 89.1 | **95.5** | 92.2 | 107.3 |
|
||||
| Native 2560×1440, no upscaling (TSR at 100%) | | 49.1 | | |
|
||||
|
||||
\* FSR 4 and the native row are from 2026-09-27; the DLSS columns from 2026-09-29, when the machine ran about 2–4% slower overall (release 0.1.1 at Quality that day: E 71.2, K 67.9, M 48.4 fps, against 72.4, 69.4 and 51.5 two days earlier). The render resolution of every mode is set with OptiScaler's ratio override for whichever DLSS mode the game is set to (ratios 1.5, 1.72, 2.0 and 3.0).
|
||||
|
||||
DLSS 4's cost is almost constant across modes (about 2.8 ms of GPU time per frame). Its network runs on a grid set by the output resolution, not the render resolution, so the gap to FSR 4 widens as the render resolution drops. The CNN gets more expensive at the 3× ratio, so K is the better choice at Ultra Performance.
|
||||
|
||||
## What each step contributed
|
||||
|
||||
DLSS 4 (K) at Quality, frames per second on the walk:
|
||||
|
||||
| Step | fps |
|
||||
|---|---|
|
||||
| ZLUDA only: the transformer's outputs were non-finite, so the network had no effect | 58.5\* |
|
||||
| All eleven K layers native | 65.0\* |
|
||||
| Wide deep layers, f32 accumulation, cheaper operand transposes | 66.0 |
|
||||
| NGX's CPU syncs removed, faster marker polling, no sync before the output copy | 66.7 |
|
||||
| DLSS queued behind a GPU-side wait for the inputs (GPU busy 95% → 99%) | 68.0 |
|
||||
| Native output kernel writes the game-side buffer directly | 68.4 |
|
||||
| NGX samples the input buffers in place (no array copies) | 69.4 |
|
||||
|
||||
\* Measured from the shim's frame log on a similar stretch, before the MangoHud method was in use.
|
||||
|
||||
DLSS 4.5 (M) at Quality went from 28 fps (ZLUDA only) to 42 with the first native Swin layers, 46 with more waves per window, 50 with fast numerics and the texture-kernel tails, and 51.5 with the hand-off changes.
|
||||
|
||||
## What did not help
|
||||
|
||||
- **Accumulating in f16 on the WMMA units.** The error grows about 20× and the image degrades.
|
||||
- **Occupancy tweaks** (VGPR caps, waves-per-EU hints) and **persistent work-groups.**
|
||||
- **Non-temporal hints** for activation traffic.
|
||||
- **Splitting the position-only layers by channel** instead of by token. It halves weight traffic but serialises the compute.
|
||||
- **Mapping the Vulkan buffers directly as HIP arrays.** ROCm 7.2 does not export `hipExternalMemoryGetMappedMipmappedArray`.
|
||||
- **Signalling the game's Vulkan timeline semaphore from HIP.** HIP does not import timeline semaphores, so the end of DLSS is still signalled from the CPU.
|
||||
|
||||
## Where the time goes now
|
||||
|
||||
For DLSS 4 at Quality the GPU spends about 2.8 ms per frame in DLSS kernels:
|
||||
- NVIDIA's output kernel: 0.82 ms. It is ALU-bound at close to the GPU's instruction rate.
|
||||
- The eleven network layers: 1.6 ms.
|
||||
- The input kernel, exposure and miscellaneous kernels: about 0.35 ms.
|
||||
|
||||
The game-side input and output copies add about 0.3 ms. [native-kernels.md](native-kernels.md) lists every kernel.
|
||||
@@ -1,143 +0,0 @@
|
||||
# Native Windows RDNA3 / RDNA4 game development package
|
||||
|
||||
Validated hardware: Windows 11 x64 / Radeon RX 9070 XT / gfx1201. Native K and
|
||||
M transformer kernels pass standalone D3D12 + OptiScaler checks. Silent Hill 2
|
||||
K now renders real menu frames and M renders a saved gameplay level with
|
||||
GPU NaN/Inf checks. Both K and M pass 3840x2160 output on this machine.
|
||||
Cyberpunk 2077 2.31 also reaches saved gameplay with K and M at 3840x2160:
|
||||
all required native transformer layers execute and output checks pass.
|
||||
The [port notes](windows-rdna4-port.md) record session counts and limitations.
|
||||
Performance measurements and their controls are recorded in
|
||||
[windows-performance.md](windows-performance.md). This is a
|
||||
development package; no NVIDIA proprietary DLL is included.
|
||||
|
||||
Experimental builds also accept gfx1100..gfx1103 (RDNA3), gfx1150..gfx1154
|
||||
(RDNA3.5) and gfx1200 (for example RX 9060/9060 XT). These targets are
|
||||
**compile-tested only**; no physical validation here has been performed.
|
||||
RX 9070 and other gfx1201 cards also remain untested. Use a package built for
|
||||
the GPU's actual HIP architecture: its `gpu-target.json`, host shim and ELF
|
||||
code objects must agree. Installation/runtime reject mixed targets. See
|
||||
[windows-gpu-support.md](windows-gpu-support.md) for separate-target build
|
||||
commands, the fork review and the first hardware diagnostic gate.
|
||||
|
||||
Before changing game files, the runner inventories HIP devices without
|
||||
executing kernels. It rejects another architecture's package and a local
|
||||
D3D12 proxy identifying itself as vkd3d/Wine, producing one diagnostic ZIP.
|
||||
RX 9060 XT needs gfx1200: the old gfx1201-only package fails before DLSS
|
||||
initialization on it. Use native D3D12. On an untested GPU, start with
|
||||
synchronous K and output diagnostics. The ordinary launcher does not attach
|
||||
a debugger. `-CaptureExceptions` is an explicit developer option; games with
|
||||
anti-debug protection can refuse it.
|
||||
|
||||
Numeric CUDA driver NGX initialization searches for `nvngx_dlss.dll` beside
|
||||
the calling d4r shim. The installer stages your local feature DLL in `d4r/`
|
||||
and the original NVIDIA core in `d4r/vendor/`. `Libraries.NvngxDlssPath` is
|
||||
the feature directory. Keeping the feature DLL only in `vendor/` causes
|
||||
`BAD00004` (FeatureNotFound) in numeric-ID games such as Cyberpunk.
|
||||
|
||||
Build the shim/diagnostics, corrected ZLUDA, K/M native objects and patched
|
||||
OptiScaler using the scripts in `scripts/windows`, then run:
|
||||
|
||||
```powershell
|
||||
.\scripts\windows\package-windows-game.ps1 -ArchivePath "$PWD\dist\windows-rdna4-game.zip"
|
||||
```
|
||||
|
||||
The package pins TheRock 10.2.0a20260929 because its Windows external-memory
|
||||
mapping lifetime passes the repeated import/release test. Stable HIP 7.2 has
|
||||
a reproduced mapped-view leak; see `docs/windows-rdna4-port.md` for the source
|
||||
fix, exact dependency versions, validation and complete build commands.
|
||||
The ZIP contains only manifest-listed files, including a snapshot of committed
|
||||
d4r source. Private NVIDIA-derived objects, caches and diagnostic captures are
|
||||
excluded. Original FP8 M and the optional hardware-packing variant pass strict
|
||||
replay/network tests but do not establish a full-network speedup, so the game
|
||||
package retains its FP16-equivalent M baseline.
|
||||
|
||||
Run a D3D12 game without anti-cheat using your locally supplied NVIDIA DLLs:
|
||||
|
||||
```powershell
|
||||
.\dist\windows-rdna4-game\windows-game.ps1 -GameExe "D:\Games\SILENT HILL 2\SHProto\Binaries\Win64\SHProto-Win64-Shipping.exe" -NgxCore "C:\Users\Administrator\d4r\_nvngx.dll" -DlssDll "C:\Users\Administrator\d4r\nvngx_dlss.dll" -Preset 11
|
||||
```
|
||||
|
||||
Use `-Preset 13` for M. The validated manifest requires DLSS 310.9.1 with the
|
||||
recorded SHA256; other feature DLLs require regenerating and validating the
|
||||
native manifest. Select an upscaler supported by OptiScaler in the game.
|
||||
The script installs `dxgi.dll`, an explicit DLSS configuration and a private
|
||||
`d4r` runtime directory, and captures stdout/stderr, exit code, loaded DLL paths,
|
||||
driver information and OptiScaler logs. Ordinary runs use a process job without
|
||||
an attached debugger. Add `-CaptureExceptions` to capture exception events and
|
||||
minidumps when reproducing a crash. A local
|
||||
ZIP bundle is printed at exit. `-RunSeconds 120` bounds a diagnostic run;
|
||||
the normal default allows you to play until you close the game.
|
||||
|
||||
For the Silent Hill 2 startup black-screen investigation, add
|
||||
`-DiagnosticResolution 1280x720`. This backs up its two graphics configuration
|
||||
files, temporarily selects a window at that resolution, and restores the
|
||||
original bytes after the test. It does not change progression saves. First-use
|
||||
PTX compilation can be slow; `-CacheDirectory <existing-ZLUDA-cache>` reuses
|
||||
modules with matching GPU, codegen switches and ZLUDA binary fingerprint.
|
||||
|
||||
Add `-ValidateOutput` to scan the entire RGBA16F DLSS output for NaN/Inf on
|
||||
the GPU before returning it to D3D12. Only two diagnostic counters (8 bytes)
|
||||
are read by the CPU; image data remains in VRAM. Validation failures are
|
||||
reported explicitly. Disable this diagnostic when measuring production speed.
|
||||
|
||||
`-ProfileStages` records CPU completion time for seven interop/NGX stages,
|
||||
command-list split/replay, submitted state publication and suffix completion.
|
||||
The recording interval measures NGX calls on the recording thread, not Present.
|
||||
`-ProfileKernels` enables synchronizing HIP-event kernel profiling and changes
|
||||
frame scheduling; use it separately from a production FPS measurement.
|
||||
`-ProfileCommandHooks` samples one in 64 D3D12 interceptions to distinguish
|
||||
tracking/lock waits from driver calls. It is disabled in ordinary runs.
|
||||
`-ProfileCudaApi` aggregates existing CUDA API host durations without adding
|
||||
HIP events or synchronization. `-UncachedInteropLists` restores per-frame
|
||||
copy-list allocation for comparison with the normal safely reused lists.
|
||||
`-ProfileGpuBoundary` requires `-AsyncInterop` and measures D3D12 GPU intervals
|
||||
around the input/output copies and external fence. It reads 32 timestamp bytes
|
||||
only after existing completion, with no extra CPU wait. Its external interval
|
||||
includes HIP and scheduling; it is not an isolated transformer kernel time.
|
||||
The runner drains stdout/stderr concurrently as raw bytes; the earlier
|
||||
line-oriented PowerShell collector imposed large per-frame delays. The optional
|
||||
ZLUDA kernel profiler is for diagnostics only. Measurements and reproduction
|
||||
commands are in [windows-performance.md](windows-performance.md).
|
||||
|
||||
`-AsyncInterop` enables the experimental K scheduling path. Submission queues
|
||||
the current frame's input/output dependencies and returns while a CUDA worker
|
||||
executes DLSS. Owned command memory is retained until GPU completion; feature
|
||||
release and resource reconfiguration wait for pending consumers. It passes
|
||||
the standalone queued-frame and Release/CreateFeature exact-output regression,
|
||||
but remains opt-in while game stability and performance are checked. It
|
||||
currently requires one D3D12 command queue. This switch is independent of
|
||||
profiling and output scans; omit those diagnostics for a production FPS run.
|
||||
|
||||
Ordinary runs use OptiScaler info logging and suppress successful HIP/CUDA API
|
||||
messages. Errors, GPU identity, imports, frame records and native/translated
|
||||
kernel launches remain logged. `-VerboseRuntime` enables all API and frontend
|
||||
trace messages when investigating a failure. Numerical relaxation flags are
|
||||
cleared in the child process; FP16 rounding and subnormals stay enabled.
|
||||
|
||||
The optional K output-store optimization is built locally from your NVIDIA DLL
|
||||
with `build-native-texture.ps1` and checked by `test-native-texture.ps1`;
|
||||
commands and measurements are in [windows-performance.md](windows-performance.md).
|
||||
Add `-LocalTextureKernels "C:\Users\Administrator\d4r\build\private-textures-gfx1201"`
|
||||
to the game command to install it. The object/manifest hashes and DLSS identity
|
||||
must match validation. These generated objects contain NVIDIA code, remain
|
||||
private, and are excluded from the distributable package. Ordinary launches
|
||||
inherit the game's resolution/window settings; the default argument is `-dx12`.
|
||||
|
||||
Original files are backed up before replacement. Restore with:
|
||||
|
||||
```powershell
|
||||
.\dist\windows-rdna4-game\windows-game.ps1 -Action restore -GameExe "D:\Games\SILENT HILL 2\SHProto\Binaries\Win64\SHProto-Win64-Shipping.exe"
|
||||
```
|
||||
|
||||
Restore refuses to overwrite files changed since installation. Backups and
|
||||
diagnostic results are retained. The script does not change progression saves,
|
||||
system DLLs, driver settings or security settings. All runtime work is native
|
||||
Windows. Colour, depth, motion, exposure and output cross APIs through VRAM
|
||||
and shared D3D12 fences; the backend waits for the current frame and never
|
||||
uses a previous-frame fallback.
|
||||
|
||||
OptiScaler source modifications are GPL-3.0 and exported under
|
||||
`source-patches/optiscaler`. ZLUDA source modifications are exported under
|
||||
`source-patches/zluda`; the LLVM gfx1154 backport is under
|
||||
`source-patches/zluda-llvm`. Dependency license texts and build hashes are included.
|
||||
@@ -1,189 +0,0 @@
|
||||
# Experimental Windows RDNA3 / RDNA4 coverage
|
||||
|
||||
The shim, diagnostics, native K/M kernels and game installer accept the
|
||||
targets below, with one package per actual ISA. **Only RX 9070 XT has physical
|
||||
validation here.** Community RX 9060 XT / gfx1200 logs now show K/M backend
|
||||
execution in Cyberpunk and Dawnwalker with all required native layers and
|
||||
finite output. Visual issues remain reported and are not resolved by those
|
||||
checks. All other targets are experimental and compile-tested; their DLSS,
|
||||
interop and performance remain unverified.
|
||||
|
||||
| Family | Target | Examples / scope |
|
||||
| --- | --- | --- |
|
||||
| RDNA3 | gfx1100 | RX 7900 family; same-target workstation GPUs |
|
||||
| RDNA3 | gfx1101 | RX 7700 / 7700 XT / 7800 XT; same-target mobile/workstation GPUs |
|
||||
| RDNA3 | gfx1102 | RX 7600 / 7600 XT; same-target mobile/workstation GPUs |
|
||||
| RDNA3 | gfx1103 | RDNA3 integrated graphics |
|
||||
| RDNA3.5 | gfx1150, gfx1151, gfx1152, gfx1153, gfx1154 | Corresponding integrated graphics targets |
|
||||
| RDNA4 | gfx1200 | RX 9060 / 9060 XT; same-target GPUs |
|
||||
| RDNA4 | gfx1201 | RX 9070 / 9070 XT / 9070 GRE; same-target GPUs |
|
||||
|
||||
Names and IDs follow [LLVM processors](https://llvm.org/docs/AMDGPUUsage.html#processors)
|
||||
and [ELF ABI](https://llvm.org/docs/AMDGPUUsage.html#amdgpu-elf-header-e-flags).
|
||||
`tools/windows/gpu-targets.json` supplies CMake-generated C++, PowerShell and
|
||||
the private texture builder. Selection uses HIP's real `gcnArchName` and the
|
||||
D3D12 adapter LUID, including systems with several GPUs sharing a target.
|
||||
Marketing names do not control eligibility.
|
||||
|
||||
All listed RDNA3/RDNA3.5/RDNA4 targets with existing gfx11/gfx12 WMMA contracts
|
||||
are included. TBD RDNA4m gfx1170..gfx1172 and gfx12.5 gfx1250/gfx1251 are
|
||||
different ISA groups and excluded. Unknown future targets need explicit review.
|
||||
Check [AMD's Windows matrix](https://rocm.docs.amd.com/projects/radeon-ryzen/en/latest/docs/compatibility/compatibilityrad/windows/windows_compatibility.html)
|
||||
for driver/runtime eligibility. Compiler support cannot supply missing Windows
|
||||
driver support or external-memory APIs, especially on APUs.
|
||||
|
||||
## Installation and diagnostics
|
||||
|
||||
Use the actual target's archive: **gfx1200 for RX 9060 XT**, for example.
|
||||
Metadata, host target and every ELF target must agree. Runtime/scripts reject
|
||||
mixed targets and never rename targets, rewrite ELF IDs or set
|
||||
`HSA_OVERRIDE_GFX_VERSION`. Legacy metadata-free packages remain gfx1201 only.
|
||||
|
||||
Before changing game files, `windows-game.ps1` now runs a read-only HIP
|
||||
inventory and checks the target and wave32. Inventory allocates no GPU buffers
|
||||
and runs no kernels; success is discovery, not validation. Failure prints one
|
||||
ZIP containing stdout/stderr, exit code, runtime/DLL and driver details. A local
|
||||
`d3d12.dll` identifying itself as vkd3d/Wine is rejected before install. Restore
|
||||
the game's native D3D12 installation; the script never loads or removes that
|
||||
proxy itself. Begin synchronously on an untested GPU:
|
||||
|
||||
```powershell
|
||||
.\windows-game.ps1 -GameExe "D:\Games\Example\Game.exe" -NgxCore "C:\LocalDLLs\_nvngx.dll" -DlssDll "C:\LocalDLLs\nvngx_dlss.dll" -Preset 11 -ValidateOutput -CaptureExceptions
|
||||
```
|
||||
|
||||
The local DLLs must match the documented NGX version and DLSS 310.9.1 SHA256
|
||||
in `package.json`. NVIDIA DLLs are never distributed. Retain the printed ZIP
|
||||
on failure. Async K and performance are subsequent gates; gfx1201-specific
|
||||
FP8, arithmetic and tuning experiments remain separate.
|
||||
|
||||
## Issue #10 review, 2026-10-02
|
||||
|
||||
Reviewed [comment 5952822115](https://github.com/countervolts/d4r/issues/10#issuecomment-5952822115),
|
||||
including all 32 attached text logs from eight attempts. HIP discovers
|
||||
**RX 9060 XT / gfx1200** successfully. Every attempt fails with the old shim's
|
||||
**"No selected gfx1201 device"** rejection; OptiScaler reports `support=false`
|
||||
/ `BAD00002`. None reaches `D4R_RUNTIME` initialization or native transformer
|
||||
execution. These logs do not demonstrate a K/M kernel crash. Use the gfx1200
|
||||
package instead of overriding architecture. Three attempts also load
|
||||
vkd3d-proton 3.1.0 from a local D3D12 proxy, outside this Windows backend.
|
||||
|
||||
The new packages/preflight address the identified failures. They do not prove
|
||||
those games work on RX 9060 XT; a new native-D3D12 run on that GPU is required.
|
||||
Raw community logs and personal directory paths stay local.
|
||||
|
||||
## Community retest, 2026-10-03
|
||||
|
||||
[Comment 5962444244](https://github.com/countervolts/d4r/issues/10#issuecomment-5962444244)
|
||||
uses the corrected `52d9872` package / `3d62b98` binaries on RX 9060 XT
|
||||
(`gfx1200`, 16 GB). Cyberpunk K/M complete 4,365 / 1,751 session frames;
|
||||
Dawnwalker K/M complete 6,713 / 1,690. Every frame has a finite-output GPU
|
||||
check, all required native layers execute and all four sessions exit normally.
|
||||
The logs record zero backend failures, previous-frame outputs and CPU image
|
||||
copies. This is community backend coverage, not a reference-image comparison:
|
||||
the tester reports texture/LOD and motion-related artifacts. All four runs use
|
||||
the HDR network input/output path, unlike the local Cyberpunk LDR validation.
|
||||
|
||||
Spider-Man 2 crashes with `0xc0000005` before any completed DLSS frame;
|
||||
its nonstandard launch is not evidence of a transformer kernel failure.
|
||||
Assassin's Creed exits with zero frames and Streamline logs repeated internal
|
||||
minidumps; its clean process exit is still inconclusive. Their causes remain
|
||||
open without a stack trace. The Witcher 3 log in
|
||||
[comment 5962808629](https://github.com/countervolts/d4r/issues/10#issuecomment-5962808629)
|
||||
selects the gfx1200 d4r shim instead of the original NGX core (its SHA256
|
||||
matches the shipped shim exactly), and the installer correctly refuses
|
||||
before modifying the game. It does not establish a Witcher runtime failure.
|
||||
|
||||
## Build
|
||||
|
||||
Prepare dependencies following `windows-rdna4-port.md`. Default: gfx1201.
|
||||
Select another target explicitly and keep separate directories:
|
||||
|
||||
```powershell
|
||||
$arch = 'gfx1101' # for example RX 7800 XT
|
||||
$diag = "$PWD\dist\windows-$arch-diagnostics"
|
||||
.\scripts\windows\build-windows-rdna4.ps1 -RuntimeProfile therock -GpuArch $arch -ZludaRoot "$PWD\dist\zluda-windows-final" -BuildDirectory "$PWD\build\windows-$arch" -InstallDirectory $diag
|
||||
.\scripts\windows\stage-native-k.ps1 -DlssDll "$PWD\nvngx_dlss.dll" -PackageRoot $diag
|
||||
.\scripts\windows\stage-native-m.ps1 -DlssDll "$PWD\nvngx_dlss.dll" -PackageRoot $diag
|
||||
.\scripts\windows\package-windows-game.ps1 -DiagnosticRoot $diag -GpuArch $arch -PackageRoot "$PWD\dist\windows-$arch-game" -ArchivePath "$PWD\dist\windows-$arch-game.zip"
|
||||
```
|
||||
|
||||
Rebuild diagnostics for the new inventory executable. The package keeps strict
|
||||
K FP16 and M FP16-equivalent baselines; native M FP8 remains disabled. CMake:
|
||||
`-DD4R_GPU_ARCH=gfx1101`. Some source/executable names retain gfx1201/gfx12 for
|
||||
compatibility; actual targets follow the selected architecture.
|
||||
|
||||
One command compiles all eleven targets without GPU workloads:
|
||||
|
||||
```powershell
|
||||
.\scripts\windows\build-windows-gpu-matrix.ps1 -ZludaRoot "$PWD\dist\zluda-windows-final"
|
||||
```
|
||||
|
||||
Add `-PackageGames -DlssDll "$PWD\nvngx_dlss.dll" -ArchiveDirectory "$PWD\dist\windows-gpu-archives"`
|
||||
to stage/archive all packages after committing source and preparing OptiScaler.
|
||||
Use `-GpuArchitectures gfx1100,gfx1101,gfx1102,gfx1200,gfx1201` for a subset.
|
||||
Per-target logs and `matrix-build.json` distinguish compilation from execution.
|
||||
The supplied DLL generates manifests locally and is never copied into archives.
|
||||
|
||||
Rebuild LLVM/ZLUDA when updating from an older package: the old LLVM 22 backend
|
||||
does not recognize gfx1154 even though Clang 24 compiles native objects for it.
|
||||
`build-zluda-llvm.ps1` now applies the source backport in `patches/zluda-llvm`
|
||||
automatically; relink with `build-zluda-windows.ps1` afterward. Compiler base
|
||||
and patch hashes are recorded in the ZLUDA build metadata and included in game
|
||||
packages. The expected patched LLVM submodule appears modified in its parent
|
||||
checkout; its complete source delta is exported, not a binary target override.
|
||||
|
||||
For a compilation gate requiring neither a GPU nor NVIDIA DLLs, run:
|
||||
|
||||
```powershell
|
||||
.\scripts\windows\test-zluda-target-compilation.ps1 -ZludaRoot "$PWD\dist\zluda-windows-final"
|
||||
```
|
||||
|
||||
All 33 public PTX compilations pass for the eleven targets: Driver API pattern,
|
||||
FP16 MMA strict reference and explicit WMMA modes, with correct ELF targets
|
||||
and wave32. The gfx12 strict F16 reference intentionally retains its existing
|
||||
double-precision helper; the separate WMMA mode checks code generation only.
|
||||
It does not enable relaxed arithmetic in game packages or validate numerical
|
||||
results on other GPUs. The original gfx1154 compiler abort is preserved locally
|
||||
in `build/llvm-gfx1154/before.log`; the regression results are in
|
||||
`test-results/windows-gpu-coverage/zluda-offline`.
|
||||
|
||||
## Fork adaptation
|
||||
|
||||
Reviewed [realdody's branch](https://github.com/realdody/d4r/tree/windows-rdna3)
|
||||
at `ae530b0f53ed5c0bb87558dd7c20f619e014e4fd` and the newer
|
||||
[`1897b4a` correction](https://github.com/realdody/d4r/commit/1897b4afa79832bd879234cfb37e7c1468db5cde).
|
||||
Earlier MSVC binary16 and generated `BOOL` fixes remain. The earlier forced
|
||||
gfx12 fragment layout is not used.
|
||||
|
||||
The newer fork reports Windows gfx1101 `permlanex16` returning its own lane,
|
||||
duplicating even K values into odd slots. This port adapts that finding into
|
||||
`kernels/common/wave32_exchange.h`: a Windows/gfx11-only per-wave LDS exchange,
|
||||
with native gfx11 layout, generic x/y/z indexing, 2 KiB scratch (512 threads
|
||||
maximum), volatile accesses and wave fences/barriers protecting scratch reuse.
|
||||
It covers K/M fragment conversions and other K half-wave exchanges. gfx12 and
|
||||
Linux keep the original instruction path. The raw gfx11 probe uses its actual
|
||||
intrinsic/layout, without a forced gfx12 shim.
|
||||
|
||||
The fork reports RX 7800 XT enc1/enc2 identity/nonzero/reference checks. Those
|
||||
are **the author's results**, not validation of this adaptation or full K/M
|
||||
here. LDS exchange, full network, translated CUDA, accuracy, interop and speed
|
||||
still need physical gfx11 testing. Credit: realdody <dodobozicek@gmail.com>.
|
||||
|
||||
## Results and next hardware gate
|
||||
|
||||
All eleven targets compile the complete MinGW host build and 19 device objects
|
||||
with TheRock `10.2.0a20260929`, HIP `7.17.26386`, Clang 24. Software target
|
||||
contracts inspect actual ELF objects without other-target GPU launches.
|
||||
RX 9070 XT passes all 20 CTest gates after these changes. K/M full-frame and
|
||||
package checks are recorded in `windows-rdna4-port.md`. Local logs are in
|
||||
`build/windows-gpu-coverage` and `test-results/windows-gpu-coverage`.
|
||||
|
||||
The first hardware gate on another GPU needs no NVIDIA DLL:
|
||||
|
||||
```powershell
|
||||
.\scripts\windows\test-windows-rdna4.ps1 -RuntimeProfile therock -PackageRoot "$PWD\dist\windows-gfx1101-diagnostics" -ZludaRoot "$PWD\dist\zluda-windows-final"
|
||||
```
|
||||
|
||||
Success requires exit 0, correct actual target, exact HIP/PTX/WMMA/pixel checks
|
||||
and stable interop lifetime. Failure prints one ZIP. Full K/M reference,
|
||||
temporal, DLSS and game validation remain subsequent gates.
|
||||
@@ -1,810 +0,0 @@
|
||||
# Windows RDNA4 measurements
|
||||
|
||||
Hardware: RX 9070 XT / gfx1201, Windows 11, display driver 32.0.31041.1004.
|
||||
Runtime: TheRock 10.2.0a20260929, HIP 7.17.26386; ZLUDA b0161a4 with
|
||||
`D4R_ZLUDA_WMMA=1`, FP8 widening, native FP8 disabled, f16 reference rounding.
|
||||
|
||||
The original serializing profiler uses HIP events on the actual launch stream, including
|
||||
separate measurements of one-time weight preparation. It synchronizes each
|
||||
sampled launch and changes scheduling: these numbers are not application FPS.
|
||||
HIP occupancy predictions are not measured hardware occupancy. The native
|
||||
objects' actual wave32, LDS, VGPR/SGPR and spill counts are available in
|
||||
`llvm-readobj --notes` and can be attached to the JSON report. Memory bandwidth
|
||||
and WMMA utilization were not measured; no utilization is inferred from timing.
|
||||
|
||||
The identical four-frame standalone D3D12/OptiScaler workloads output 512x288.
|
||||
Summing the measured main-kernel event times and dividing by four gives:
|
||||
|
||||
| Preset | Fully translated, ms/frame | Native FP16-equivalent, ms/frame |
|
||||
| --- | ---: | ---: |
|
||||
| K | 157.745441 | 0.684675 |
|
||||
| M | 7.428538 | 1.566500 |
|
||||
|
||||
Both rows include translated input/output tails. Native overrides cover all
|
||||
11 K layers and five M layers; M's tube layer executes six times per frame.
|
||||
M native and translated RGB are bit-exact, with max absolute/relative error 0.
|
||||
K native remains bit-exact against its independently validated native control;
|
||||
fully translated K has the previously documented arithmetic differences.
|
||||
All outputs are finite. These are reference-correct codegen settings, not
|
||||
measurements of a relaxed fast-math translated configuration.
|
||||
|
||||
M's first profiled Evaluate includes about 0.9 seconds of host initialization;
|
||||
the four-sample CPU mean must not be treated as steady-state latency. Its
|
||||
median Evaluate host completion is 4.855 ms. GPU events and prep phases are
|
||||
reported separately in the raw JSON.
|
||||
|
||||
The initial game runner used PowerShell line-oriented output redirection.
|
||||
It heavily throttled verbose stdout/stderr. The runner now concurrently drains
|
||||
raw byte streams using the same approach as the standalone diagnostics.
|
||||
|
||||
| Silent Hill 2 stage, CPU mean | Initial capture, ms | Raw-byte capture with HIP profiler, ms |
|
||||
| --- | ---: | ---: |
|
||||
| Input fence wait | 5.641 | 0.833 |
|
||||
| Input conversion and CUDA array upload | 13.196 | 0.668 |
|
||||
| NGX Evaluate host call | 25.715 | 3.350 |
|
||||
| NGX all-stream completion | 1.846 | 0.033 |
|
||||
| Output CUDA array download | 4.288 | 0.167 |
|
||||
| Output conversion and shared fence signal | 1.500 | 0.033 |
|
||||
|
||||
The first run additionally scanned every output (10.142 ms in that throttled
|
||||
capture); the kernel-profiling run disables that scan. Both use a temporary
|
||||
1280x720 window and current-frame VRAM interop. These are separate menu/game
|
||||
runs, not a controlled whole-game FPS comparison. No synchronization was
|
||||
removed to obtain the improvement. The raw-byte profiling run completed
|
||||
2345 K frames, with no d4r failure, CPU image copy or previous-frame output.
|
||||
|
||||
Reproduce native or translated measurements with locally supplied NVIDIA DLLs
|
||||
at the repository root and the separately built profiling runtime:
|
||||
|
||||
```powershell
|
||||
.\scripts\windows\profile-windows-rdna4.ps1 -Preset 11
|
||||
.\scripts\windows\profile-windows-rdna4.ps1 -Preset 11 -Translated
|
||||
.\scripts\windows\profile-windows-rdna4.ps1 -Preset 13
|
||||
.\scripts\windows\profile-windows-rdna4.ps1 -Preset 13 -Translated
|
||||
```
|
||||
|
||||
`profile_report.py <results-directory> --output profile.json` summarizes raw
|
||||
CPU stages and every kernel's event time, launch geometry, registers, private
|
||||
memory, LDS and predicted blocks per multiprocessor. Add
|
||||
`--metadata-directory <directory-of-llvm-readobj-notes>` for native wave sizes
|
||||
and compiler spill counts. Reports and proprietary workload inputs remain local.
|
||||
|
||||
Native FP8 remains a separate optional experiment; the package uses the
|
||||
validated FP16-equivalent baseline. Its later checks and timings are below.
|
||||
|
||||
## K host synchronization and asynchronous submission
|
||||
|
||||
Current priority is K performance. The user's synchronous 4K reading is
|
||||
49–51 FPS / 53% GPU utilization, versus approximately 80+ FPS / 100% with
|
||||
FSR4. These readings do not identify a CPU hardware limit or provide a
|
||||
controlled same-scene comparison. M/FP8 optimization is deferred.
|
||||
|
||||
ZLUDA candidate `a1c506f` adds `D4R_ZLUDA_PROFILE_API`, enabled by the game
|
||||
runner's `-ProfileCudaApi`. It measures existing API host durations, aggregates
|
||||
per thread and logs every two seconds without HIP events or additional waits.
|
||||
The synchronous control shows five `cuCtxSynchronize` calls per frame with
|
||||
about 3.9 ms aggregate host time. CUDA launch host overhead is approximately
|
||||
0.46 ms per frame. Cached copy-list setup is only 0.011 ms median. These host
|
||||
measurements include GPU waits and must not be added to GPU kernel times.
|
||||
|
||||
| K/4K command submission, CPU median | Synchronous | First async | Async without CUDA mutex |
|
||||
| --- | ---: | ---: | ---: |
|
||||
| Entire submission, ms | 10.512 | 2.676 | 0.181 |
|
||||
| DLSS boundary, ms | 10.083 | 2.604 | 0.124 |
|
||||
| Consumer suffix completion, ms | 0.350 | 0.005 | 0.004 |
|
||||
|
||||
The first async game run completes 9481 finite frames; the user reports
|
||||
60 FPS / 63% GPU. The mutex-free run crashes during feature recreation after
|
||||
366 finite frames, so its submission timing is not a successful gameplay
|
||||
benchmark. The standalone burst/recreate reproducer subsequently identifies
|
||||
caller-owned GPU backing freed after ReleaseFeature returns. Waiting for
|
||||
pending D3D12 consumers in ReleaseFeature fixes the reproducer: all twelve
|
||||
sync/async test frames pass, and corresponding RGB outputs are exact. Game
|
||||
stability and FPS must be checked separately on the fixed build.
|
||||
|
||||
The fixed game retest on 2026-10-02 completes 16941 K/4K frames, all finite,
|
||||
including feature recreation and color-format reimports, with zero backend
|
||||
failures. The user reports 62 FPS / 63% GPU. Median CPU submission is
|
||||
0.197 ms, NGX host completion on the worker is 4.400 ms and output validation
|
||||
is 0.380 ms. The 10.162 ms median worker input wait includes queued game
|
||||
rendering. These results establish a stable five-minute test of this fix,
|
||||
not a conclusion about the remaining GPU idle time or FSR4 performance.
|
||||
|
||||
`-AsyncInterop` is opt-in. It queues input/output fences on the submission
|
||||
thread, executes CUDA on a worker and retires owned command memory by GPU
|
||||
completion. Three copy slots bound outstanding ownership. The queue consumes
|
||||
the output of the same frame, with no CPU image copy. The worker's input wait
|
||||
includes its lead behind submitted rendering and is not a CPU submission
|
||||
stall. Neither that duration nor the NGX recording interval measures Present
|
||||
latency. Reconfiguration waits for all consumers; ordinary submission does not
|
||||
hold the CUDA mutex. The experimental runtime currently supports one queue.
|
||||
|
||||
```powershell
|
||||
.\scripts\windows\test-async-k.ps1
|
||||
```
|
||||
|
||||
The test generates fresh synchronous controls, submits three frames without
|
||||
intermediate CPU completion, and repeats while releasing/recreating the DLSS
|
||||
feature with work pending. Results include exact RGB comparisons, finite GPU
|
||||
scans, stdout/stderr, exceptions and runtime provenance. To include the local
|
||||
validated output-store optimization, pass its combined native directory with
|
||||
`-NativeRoot`; proprietary objects remain local.
|
||||
|
||||
`-ProfileGpuBoundary` (requires `-AsyncInterop`) adds D3D12 timestamps before
|
||||
and after the VRAM input/output copies. Resolved results are read only once
|
||||
the copy slot's existing fence completes; 32 diagnostic bytes per frame are
|
||||
read and no new completion wait is added. `external_span_ms` spans HIP and
|
||||
host/driver scheduling across the external fence. `between_boundaries_ms`
|
||||
also includes game rendering, and `input_interval_ms` is not Present timing.
|
||||
These queries obey the queue's timestamp ordering and add GPU commands; they
|
||||
are disabled for an ordinary FPS run. GPU clock behavior during idle can
|
||||
affect intervals; no hardware occupancy is inferred. Timestamp semantics:
|
||||
[Microsoft D3D12 timing](https://learn.microsoft.com/en-us/windows/win32/direct3d12/timing).
|
||||
|
||||
The timestamp-enabled 4K burst/recreation gate completes twelve frames, all
|
||||
finite; all six async RGB outputs still match their fresh controls exactly.
|
||||
Each async mode emits all three timing records, including the final frame
|
||||
at feature release. Results: `test-results/k-async-gpu-boundary-4k`.
|
||||
All sixteen CTest gates pass on the rebuilt shim. Reproduce with:
|
||||
|
||||
```powershell
|
||||
.\scripts\windows\test-async-k.ps1 -ProfileGpuBoundary
|
||||
```
|
||||
|
||||
The 2026-10-02 game timestamp run completes 9384 K/4K frames without backend
|
||||
errors (`test-results/silent-hill2-k-gpu-boundary-4k`). Median GPU intervals:
|
||||
input copies 0.061 ms, external span 5.586 ms, output copy 0.208 ms, entire
|
||||
boundary 5.856 ms, between boundaries 9.512 ms. Median input interval is
|
||||
15.383 ms. Output scans and serializing kernel events are off. This locates
|
||||
the remaining time outside the small D3D12 copies; it does not prove whether
|
||||
that time is game GPU work, CPU waits or context scheduling.
|
||||
|
||||
### Present and GPU-busy capture
|
||||
|
||||
`capture-presentmon.ps1` attaches the official PresentMon 2.6.0 x64 CLI to
|
||||
one running game process. It verifies SHA256
|
||||
`b2a706bc6ad475749e3b7e3409263aa1e6906d45bdcf993f6dbc0f660188f1af`,
|
||||
uses a unique ETW session and stops at its time bound/process exit, without
|
||||
replacing any existing trace or installing a service. It saves CSV, console
|
||||
output, driver version, target PID and the HWS registry setting. The default
|
||||
downloads the pinned CLI into `.tools` if needed. Run elevated when ETW access
|
||||
requires it; no driver or security setting is changed.
|
||||
|
||||
```powershell
|
||||
.\scripts\windows\capture-presentmon.ps1 -Seconds 30
|
||||
python .\tools\windows\profile_report.py <capture-directory> --output profile.json
|
||||
```
|
||||
|
||||
Keep the game foreground and use the same scene/quality setting for comparison.
|
||||
The report separates swapchains and preserves missing metrics. Present FPS
|
||||
comes from present intervals, rather than NGX recording timestamps. GPU
|
||||
busy/wait are ETW estimates, not a hardware sensor percentage; CPU busy is
|
||||
frame work/wait attribution before Present, not physical CPU utilization.
|
||||
HWS and cross-API context attribution can affect accuracy. Metric definitions:
|
||||
[PresentMon console documentation](https://github.com/GameTechDev/PresentMon/blob/v2.6.0/README-ConsoleApplication.md).
|
||||
|
||||
The initial 60-second trace captures 2172 presents during a changing
|
||||
Independent Flip / Composed Flip session, with mean present interval
|
||||
27.593 ms (36.241 FPS), mean GPU busy 18.759 ms and GPU wait 2.303 ms.
|
||||
This is not a controlled capture of the user's 62 FPS scene and is excluded
|
||||
from speedup conclusions. Its containing game run completes 9627 K/4K frames
|
||||
without backend errors; ordinary recording intervals later return to about
|
||||
16 ms. A stable foreground-scene capture is needed before optimizing from
|
||||
the ETW metrics. Raw files: `test-results/silent-hill2-k-presentmon-4k`.
|
||||
|
||||
The following 30-second capture starts after the user confirms the same
|
||||
foreground scene is ready. All 1902 presents use Hardware Independent Flip
|
||||
and SyncInterval 0; input/output resolution remains 2259x1271 -> 3840x2160.
|
||||
The mean present interval is 15.730 ms (**63.574 FPS**). PresentMon estimates
|
||||
mean GPU busy/wait at 14.504/1.110 ms, GPU time at 15.614 ms and CPU wait at
|
||||
0.052 ms. These frame-attributed metrics do not equal a hardware utilization
|
||||
sensor and do not establish a physical CPU limit. FSR4 has not been captured
|
||||
in this same scene, so its previously reported 80+ FPS remains a user reading.
|
||||
Raw files: `test-results/silent-hill2-k-steady-profile-4k`.
|
||||
|
||||
The containing ten-minute diagnostic completes 36591 K frames, with zero
|
||||
backend failures, CPU image copies, previous-frame outputs or recorded game
|
||||
crashes. It deliberately stops at its time bound. Output scans and serializing
|
||||
kernel events are off. Whole-run median boundary timestamps measure input
|
||||
copies 0.063 ms, external span 5.399 ms and output copies 0.212 ms. The external
|
||||
span includes HIP execution and host/driver scheduling, not only transformer
|
||||
arithmetic. These medians cover the whole run; the PresentMon numbers above
|
||||
come from the explicitly selected 30-second scene.
|
||||
|
||||
### Deferred kernel events and batched inputs
|
||||
|
||||
The new optional `-ProfileKernelsDeferred` samples every seventeenth launch
|
||||
by default (`-KernelProfileEvery`). Its thread-local pool is bounded to 64
|
||||
event pairs. It queries ready events before selected launches and after the
|
||||
application's existing context synchronization, reusing a pair only after
|
||||
reading its old timestamps. It adds no explicit event/stream/device completion
|
||||
wait; timestamps, queries and logging still add overhead. Stream capture and
|
||||
legacy default-stream launches are skipped by default. `-ProfileLegacyStream`
|
||||
allows the latter explicitly, retaining their legacy cross-stream ordering.
|
||||
This opt-in is necessary to profile this DLSS K binary, whose measured launches
|
||||
use the legacy default stream. `completion_ms` now denotes collection lag for
|
||||
deferred records. The report separates serializing/deferred records and retains
|
||||
invalid timestamps and skipped samples outside kernel timing statistics.
|
||||
|
||||
HIP 7.17.26386 reports some negative elapsed times in the tiny queued PTX
|
||||
diagnostic, including intervals exceeding one microsecond. These are logged as
|
||||
`D4R_KERNEL_PROFILE_INVALID`; they are not clamped or used as valid GPU samples.
|
||||
The cause is not established, and nonnegative samples alone cannot prove a
|
||||
runtime's timestamp accuracy. The diagnostic verifies all 516 PTX launches
|
||||
across primary/created contexts and individual/queued submission, checks final
|
||||
device output and guards, accounts for every collected event and verifies safe
|
||||
default-stream skipping. Results: `test-results/zluda-deferred-profile-final-ptx`.
|
||||
The same diagnostic with stable HIP SDK 7.2 also verifies all 516 outputs and
|
||||
reproduces negative intervals (`test-results/zluda-deferred-profile-stable-ptx`).
|
||||
A native K dec4 sample is negative too; this is not confined to tiny PTX kernels.
|
||||
Do not infer hardware/kernel utilization or a speedup from these event samples.
|
||||
HIP event semantics: [AMD event management](https://rocm.docs.amd.com/projects/HIP/en/latest/reference/hip_runtime_api/modules/event_management.html).
|
||||
|
||||
The opt-in `-BatchInputCopies` (`D4R_BATCH_INPUT_COPIES=1`) enqueues native
|
||||
pixel decoding and device-to-array input copies on the shared HIP/ZLUDA legacy
|
||||
default stream. One all-stream completion remains before NGX can use any input
|
||||
on its own streams. The independent D3D12 input-fence check, NGX completion and
|
||||
same-frame output dependency remain. Output transfers retain their existing
|
||||
completion. Every image stays in VRAM. The ZLUDA implementation adds
|
||||
`cuMemcpy2DAsync_v2` using `hipMemcpyParam2DAsync`; format-80 array emulation
|
||||
is explicitly rejected because its synchronous implementation uses temporary
|
||||
host storage. The Windows path supplies canonical FP16/FP32 arrays instead.
|
||||
This experiment remains disabled by default. Correctness checks pass, but the
|
||||
controlled game comparison below shows only a small frame-time difference.
|
||||
|
||||
```powershell
|
||||
.\scripts\windows\test-deferred-kernel-profile.ps1
|
||||
.\scripts\windows\test-async-k.ps1 -BatchInputCopies -ProfileGpuBoundary -ZludaRoot "$PWD\dist\zluda-windows-deferred-profile"
|
||||
```
|
||||
|
||||
The rebuilt Windows shim and new ZLUDA pass all seventeen CTest gates,
|
||||
including the added asynchronous pitched FP16/FP32 array-copy test and
|
||||
padding checks. Completed boundary timestamps are also read before reuse if
|
||||
the copy fence advances between the first completion scan and slot selection;
|
||||
this prevents diagnostic records being overwritten without adding a wait.
|
||||
|
||||
The depth/stencil and packed-format burst/recreation gates pass 24 full K/4K
|
||||
frames. All twelve candidate RGB outputs match fresh unbatched synchronous
|
||||
controls exactly, with finite RGBA. The former also enables deferred legacy
|
||||
events; invalid timestamps remain separate. These short correctness fixtures
|
||||
include initialization and do not establish steady-state FPS or a copy-stage
|
||||
speedup. Raw results: `test-results/k-batch-deferred-4k` and
|
||||
`test-results/k-batch-packed-4k`. ZLUDA candidate source is `67127dd`, isolated
|
||||
in `dist/zluda-windows-deferred-profile`; patches 0016/0017 and all preceding
|
||||
patches apply to the clean pinned base. The public prerelease is unchanged.
|
||||
After committing/rebuilding ZLUDA with a clean worktree, the twelve-frame
|
||||
four-way K/4K gate passes again with exact candidate RGB and finite RGBA
|
||||
(`test-results/k-batch-committed-source-4k`). This warms the committed runtime's
|
||||
JIT cache before the game comparison.
|
||||
|
||||
The following user-confirmed 30-second foreground-scene capture contains 1925
|
||||
presents at **64.265 FPS**, versus the previous unbatched run's 63.574 FPS.
|
||||
Both use 2259x1271 -> 3840x2160, Independent Flip and SyncInterval 0, without
|
||||
kernel-event profiling, output scans or attached debuggers. Mean present time
|
||||
is 15.561 versus 15.730 ms, a 0.169 ms difference. This single pair does not
|
||||
establish repeatability or a large performance improvement. The containing
|
||||
ten-minute candidate run completes 35673 K frames with zero backend failures,
|
||||
CPU image copies, previous-frame outputs or recorded game crashes. Whole-run
|
||||
median input preparation drops from 0.482 to 0.332 ms; median external span
|
||||
is 5.438 versus 5.399 ms. Whole-run stages are not the selected PresentMon
|
||||
window. No GPU utilization conclusion is drawn from ETW estimates. Results:
|
||||
`test-results/silent-hill2-k-batch-inputs-4k`. The K performance gate stays open.
|
||||
|
||||
### AMD driver telemetry
|
||||
|
||||
A separate read-only diagnostic polls the installed driver's ADLX base C
|
||||
interfaces for device-wide usage, core/VRAM clocks, board power and temperatures.
|
||||
It adds no work to game queues and changes no tuning setting. Build it locally
|
||||
using the official SDK pinned at `32b5a740d42295c5dfe9026b9f52683da0f3af91`:
|
||||
|
||||
```powershell
|
||||
.\scripts\windows\build-gpu-telemetry.ps1
|
||||
.\scripts\windows\capture-presentmon.ps1 -Seconds 30 -GpuTelemetry
|
||||
```
|
||||
|
||||
The SDK retains its own AMD license; SDK headers, implementations, driver DLLs
|
||||
and the SDK-dependent executable are excluded from public game packages.
|
||||
The probe is independently written and uses the documented C ABI, including
|
||||
with LLVM-MinGW. It loads `amdadlx64.dll` only from Windows System32 and
|
||||
releases acquired interfaces before ADLX termination/unload. GPU selection
|
||||
must match exactly one device (`-GpuName` selects a different name substring).
|
||||
The process exits at its bound or target process exit. The capture retains
|
||||
CSV, raw stderr, exit/timeout, driver DLL version/hash and SDK build identity.
|
||||
No optional telemetry failure is silently converted to a valid measurement.
|
||||
|
||||
CSV records independent host UTC/QPC timestamps and the driver's raw sample
|
||||
timestamp. On this installed ADLX 1.5.0.124, the latter is uptime despite the
|
||||
SDK description of epoch time; do not interpret it as UTC. Unsupported metrics
|
||||
are blank, zero utilization/clock remains valid, and the report uses each
|
||||
driver timestamp once. Device-wide usage is distinct from PresentMon's
|
||||
per-process frame attribution and is not measured WMMA occupancy. ADLX API:
|
||||
[AMD GPU metrics sample](https://gpuopen.com/manuals/adlx/adlx-c__perf_g_p_u_metrics/).
|
||||
|
||||
The initial idle-device smoke test captures six valid polls, selects the real
|
||||
RX 9070 XT and terminates ADLX successfully. Board power/core clock/usage
|
||||
and temperatures are available; `GPUPower` is unsupported and stays absent
|
||||
from the report. The first poll costs roughly 10 ms for initialization;
|
||||
subsequent polls are about 0.08 ms at 500 ms intervals. This idle smoke test
|
||||
does not establish game clocks, utilization or an overhead-free benchmark.
|
||||
Results: `test-results/gpu-telemetry-smoke`.
|
||||
|
||||
The subsequent combined-capture smoke test collects 246 presents and ten
|
||||
ADLX polls and exits cleanly (`test-results/gpu-telemetry-capture-smoke`).
|
||||
It includes startup/scene changes and is excluded from FPS comparisons.
|
||||
After the user confirms the foreground comparison scene, the 30-second run
|
||||
with detailed d4r stages/boundary timestamps disabled records **64.661 FPS**
|
||||
over 1935 presents. ADLX's sixty polls report mean usage **93.183%**, core
|
||||
clock **3124.667 MHz**, board power **316.717 W**, temperature 57 C and hotspot
|
||||
82.9 C. Mean PresentMon GPU busy/wait is 14.551/0.800 ms. All presents retain
|
||||
Independent Flip / SyncInterval 0. This records high device-wide driver usage
|
||||
in this run; the user identified the earlier 63% reading as Task Manager.
|
||||
It is not the same measurement as ADLX device-wide usage. Do not infer a physical CPU
|
||||
limit, isolated shader occupancy or a FSR4 speed comparison. Query overhead
|
||||
is median 0.094 ms per 500 ms poll, with a roughly 12 ms first query. Results:
|
||||
`test-results/silent-hill2-k-telemetry-unprofiled-4k`. The game stability
|
||||
summary completes 37187 K frames with zero backend failures, CPU image copies,
|
||||
previous-frame outputs or recorded crashes, stopping at its ten-minute bound.
|
||||
Remaining K work now prioritizes transformer/output-kernel cost; frame
|
||||
scheduling remains measured.
|
||||
|
||||
### Rejected packed FP16 accumulator experiment
|
||||
|
||||
An isolated `D4R_K_F16_WMMA` enc1 build uses gfx12's documented packed FP16
|
||||
C/D intrinsic, retaining the current operand/accumulator lane mapping. It
|
||||
removes most conversion instructions (1066 static F16/F32 conversions become
|
||||
two) and reduces main-kernel VGPRs from 218 to 201; LDS remains 24576 bytes,
|
||||
with zero spills. These are compiler/ISA counts, not GPU time or occupancy.
|
||||
The candidate is rejected before moving to another layer: its real replay
|
||||
changes 1187603 half codes in the output allocation, max absolute difference
|
||||
0.0390625 from the validated baseline. All values are finite. Against the
|
||||
current twelve-window NumPy reference, PSNR drops from baseline 93.7527 dB
|
||||
to 69.2377 dB; max absolute error rises from 0.0078125 to 0.0390625.
|
||||
The original comparison incorrectly selected a pre-normalization-fix saved
|
||||
output (78.7702 dB); a fresh replay matches `k-real-strict-dual-reference/enc1`
|
||||
exactly and supplies the corrected baseline here. The rejection still holds.
|
||||
Two independent PTX windows give 70.4022/70.08 dB. These pass the existing
|
||||
coarse reference thresholds but do not satisfy this optimization's baseline
|
||||
preservation gate. No game installation or performance claim follows.
|
||||
|
||||
A public 64-matrix primitive reproducer isolates the difference to direct
|
||||
instruction arithmetic. The packed intrinsic and the layout adapter agree
|
||||
bit-for-bit. Direct FP16 output differs from FP32 WMMA rounded once to FP16
|
||||
even after one K16 step (1674 of 4096 elements, max absolute 0.00390625).
|
||||
After eight steps, 2874 elements differ, max absolute 0.0625. This rules out
|
||||
the adapter packing as the source of this fixture's difference; the hardware
|
||||
internal accumulation/rounding cause is not established. Production K keeps
|
||||
its existing FP32-instruction/FP16-rounding baseline and the experimental flag
|
||||
is off in every normal build. Results: `test-results/k-f16-wmma-enc1` and
|
||||
`test-results/wmma-f16-arithmetic-compare-fixed`.
|
||||
The finished `test-wmma-f16.ps1` repeats the same 64-case result. Rebuilding
|
||||
every ordinary K/M object leaves all sixteen byte-identical; all seventeen
|
||||
CTest gates pass and enc1 still compiles for gfx1101 (compile-only). Logs:
|
||||
`test-results/wmma-f16-script-check` and `test-results/k-f16-baseline-ctest.log`.
|
||||
|
||||
```powershell
|
||||
.\scripts\windows\test-wmma-f16.ps1
|
||||
.\scripts\windows\build-native-k-f16-wmma.ps1 -Layer enc1
|
||||
```
|
||||
|
||||
The first command compiles and runs the public arithmetic diagnostic without
|
||||
NVIDIA inputs. Its success means the reproducer executed correctly, not that
|
||||
the two instruction paths are equivalent; JSON retains `baselineEquivalent`
|
||||
and `gameOptimizationAccepted`. The second compiles the rejected experiment
|
||||
in a separate directory and generates no override manifest. Intrinsic API:
|
||||
[Clang gfx12 FP16 WMMA](https://clang.llvm.org/docs/AMDGPUBuiltinReference.html#builtin-amdgcn-wmma-f16-16x16x16-f16-w32-gfx12).
|
||||
|
||||
### Controlled native replay timings
|
||||
|
||||
`native_replay_probe` now supports `--benchmark-timing events|dispatch` and
|
||||
`--benchmark-batch 1..256`. Dispatch mode uses the documented
|
||||
`hipExtModuleLaunchKernel` start/stop events, with work-item dimensions derived
|
||||
from each module's launch metadata and flags zero. It does not change wave
|
||||
order or arithmetic. Control/candidate can have different native block/grid
|
||||
metadata; each launch uses its own geometry. The default remains event markers.
|
||||
|
||||
Each AB/BA sample restores captured inputs outside timing, submits a series,
|
||||
waits for its end event, and logs both the event interval and independent host
|
||||
launch-to-completion interval divided by launch count. These are isolated
|
||||
diagnostics: batch intervals include dispatch/queue gaps and are not exclusive
|
||||
instruction execution times, frame latency, or game FPS. Zero, negative,
|
||||
nonfinite or event intervals exceeding the enclosing host interval are retained
|
||||
as `D4R_REPLAY_PROFILE_INVALID` and excluded. Reports keep timing sources,
|
||||
batch counts and log files separate, retaining host statistics and invalid
|
||||
samples; no partially valid pair is accepted by the benchmark runner.
|
||||
|
||||
The new runner first executes fresh ordinary control/candidate replays and
|
||||
compares every allocation's SHA256 before timing. It stops at any mismatch,
|
||||
then checks the control output again after every benchmark. A successful
|
||||
timing run does not replace the independent NumPy/PTX correctness gates.
|
||||
Captured weights/IR and GPU outputs remain private.
|
||||
|
||||
```powershell
|
||||
.\scripts\windows\benchmark-native-replay.ps1 -Module "$PWD\build\native-k-gfx1201\dltss_pwin_enc1_layer.hsaco" -Candidate "$PWD\build\native-k-gfx1201\dltss_pwin_enc1_layer.hsaco" -FixtureDirectory "$PWD\test-results\ngx-k-fp16-fenced-capture\replay\replay-000001-dltss_pwin_enc1_layer"
|
||||
```
|
||||
|
||||
The same-module enc1 control has all exact allocations and 32 valid pairs per
|
||||
mode. Median per-launch times at the captured 512x288 workload are 0.054850 ms
|
||||
with separate single-launch events and 0.089700 ms with single-launch dispatch
|
||||
events. At batch 64 they converge to 0.048213/0.048017 ms. Thus dispatch events
|
||||
alone do not remove timing overhead; use the batch/host cross-check. All eleven
|
||||
K same-module controls pass sixteen pairs at batch 64 in both modes, including
|
||||
dec4. This does not fix or explain the previously recorded negative ZLUDA
|
||||
timestamps. Results: `test-results/k-replay-timing-methods` and
|
||||
`test-results/k-all-layers-batch-profile`.
|
||||
|
||||
One-frame standalone K/4K HDR captures provide actual enc0/enc1/dec0 inputs.
|
||||
Each harness run uses the eleven validated native layers and private output
|
||||
tail, passes the finite-output scan and completes without network fallback. At this
|
||||
synthetic resolution enc1 uses a 61x35 grid; this workload is distinct from
|
||||
the game's 2259x1271 input. Experiments retain F32 WMMA instructions and strict
|
||||
FP16 rounding. `build-native-k-experiment.ps1` builds separate objects and no
|
||||
override manifest; no experimental object is installed by the game runner.
|
||||
|
||||
CU/WGP and non-temporal load/store/both on enc1 preserve every allocation but
|
||||
do not improve its paired 4K timings. Position-only token tiling also preserves
|
||||
outputs: enc1 with two tiles and shared V spills four VGPRs and is about 9%
|
||||
slower; one-tile shared V has no measured gain. The two-tile shared-V enc0 run
|
||||
initially has a roughly 4% lower median paired ratio amid scheduling variance.
|
||||
A repeat with 64 AB/BA pairs at batch 64 gives control/candidate medians
|
||||
0.297060/0.282559 ms (events) and 0.299988/0.285011 ms (dispatch), with median
|
||||
paired ratios 0.950863/0.952240. A 512x288 replay independently gives ratios
|
||||
0.950396/0.952582. Both tested dec0 shared-V variants are slower or indistinguishable.
|
||||
|
||||
Enc0 now selects shared V for the gfx12 strict baseline, preserving the existing
|
||||
two-token tiles, F32 WMMA and FP16 rounding. Gfx11 and arithmetic experiments
|
||||
retain their prior selection. `D4R_K_PRIVATE_V` restores the previous enc0 for
|
||||
comparison; the build helper exposes `-PrivateValues`. The exact CMake-produced
|
||||
object also passes a fresh 4K replay and 32 paired batch-64 samples, with ratios
|
||||
0.955418/0.948494. Its ELF hash differs from the experimental object; `.text`
|
||||
and `.rodata` match exactly, and numerical validation is repeated on the actual
|
||||
object. The other fifteen ordinary K/M objects remain byte-identical.
|
||||
Gfx1101 enc0/enc1 compile-only controls retain identical code and constant
|
||||
sections to their original sources; no RDNA3 hardware execution is claimed.
|
||||
|
||||
Full K controls/candidates complete sixteen 4K frames, and twelve more with
|
||||
the game's 2259x1271 input and 3840x2160 output. Every compared RGB half code
|
||||
matches, all RGBA scans are finite. Results: `test-results/k-enc0-shared-full-4k`,
|
||||
`k-enc0-shared-full-game-input`, `k-4k-enc0-pos2-shared-repeat`,
|
||||
`k-enc0-pos2-shared-small` and `k-enc0-default-shared-4k`. The saving is about
|
||||
0.015 ms for enc0 in the isolated 4K replay, not 5% application FPS.
|
||||
|
||||
The separate `D4R_K_PACKED_ACC` experiment stores already-rounded accumulators
|
||||
as half vectors between steps, widening for each unchanged F32 WMMA and
|
||||
rounding its F32 output back to half. The ordinary `acc8v` alias remains F32.
|
||||
Enc0/enc1/dec0 4K replays match every allocation exactly. Enc1 main VGPRs fall
|
||||
218 -> 195, LDS remains 24576 bytes and spills stay zero, but paired GPU time
|
||||
does not improve; enc0 is about 4% slower and dec0 about 1% slower. Combining
|
||||
packed storage with enc1 two-tile shared V is about 13% slower. The flag remains
|
||||
off. Smaller register counts alone are not evidence of an optimization.
|
||||
Raw results are under `test-results/k-4k-*-packed-acc` and
|
||||
`test-results/k-4k-enc1-pos2-shared-packed`.
|
||||
|
||||
A direct recompilation of the private output tail's optimized LLVM IR with
|
||||
TheRock Clang 24 fails in instruction selection with `unsupported library
|
||||
call operation` (driver exit 1, backend exit 70, exception 0xE0000046). The generated crash
|
||||
reproducer/log are retained locally; strict FP is not removed to work around
|
||||
this. The working LLVM 22 output object remains selected. The HDR tail's
|
||||
metadata is wave32, 133 VGPRs, 6912 LDS bytes and no spills; LDR uses 128 VGPRs
|
||||
with the same LDS and no spills. These are static resource counts, not actual
|
||||
occupancy. Compiler scheduling hints are documented in the
|
||||
[LLVM AMDGPU backend guide](https://llvm.org/docs/AMDGPUUsage.html#llvm-ir-attributes).
|
||||
|
||||
### Private output-tail WGP experiment
|
||||
|
||||
ZLUDA source `fb0adc8714f57647320f0601533ec50331e378b0`, patch 0018, adds
|
||||
opt-in `D4R_ZLUDA_WGP=1`. It changes only CU/WGP placement for gfx11/gfx12,
|
||||
preserving wave size and arithmetic. The ordinary runtime stays in CU mode.
|
||||
The offline texture builder accepts `-ShaderMode wgp` and verifies `-cumode`
|
||||
on the emitted kernel before accepting the object. The compiled output-tail
|
||||
objects carry this mode independently of the runtime's environment variable.
|
||||
These NVIDIA-derived objects remain private; the public package excludes them.
|
||||
|
||||
The matched K/4K comparison uses identical public network objects and the
|
||||
existing validated CU output kernels as control. Both HDR and LDR complete
|
||||
eight frames per variant; repeating with candidate-first order completes
|
||||
sixteen frames per variant. All 96 control/candidate frames are finite, and
|
||||
all 48 candidate RGB outputs exactly match their fresh controls. Every frame
|
||||
has a native output-tail hit and a valid serializing event measurement.
|
||||
|
||||
| Output-tail median, ms | CU, first run | WGP, first run | CU, reverse order | WGP, reverse order |
|
||||
| --- | ---: | ---: | ---: | ---: |
|
||||
| LDR | 1.864650 | 1.703100 | 1.840260 | 1.687500 |
|
||||
| HDR | 2.012301 | 1.883395 | 2.016020 | 1.869250 |
|
||||
|
||||
These are separate-process serializing diagnostic measurements, not paired
|
||||
resident-module timings or game FPS. Unchanged network kernels also vary
|
||||
between processes. The repeat indicates a candidate worth testing in the
|
||||
game; it does not establish a frame-rate improvement. Results:
|
||||
`test-results/k-output-wgp-reference-4k-clean-env` and
|
||||
`k-output-wgp-reference-4k-reverse`.
|
||||
The game-sized WGP async burst/recreate gate completes twelve frames, all
|
||||
finite; all six async RGB outputs match fresh sync controls exactly, with
|
||||
no CPU image copy or aged output (`k-output-wgp-async-game-input`).
|
||||
The exact CMake shared-V enc0 and WGP output tails together also pass twelve
|
||||
game-sized async/burst/recreation frames, with all six async RGB images exact
|
||||
(`k-enc0-shared-wgp-async-game-input`). Default selection of private output
|
||||
objects remains CU until a game comparison establishes the candidate's effect.
|
||||
|
||||
### Combined K game check
|
||||
|
||||
The private WGP outputs are rebuilt from clean ZLUDA source `fb0adc8`; both
|
||||
object hashes match the earlier validated experimental objects. A final
|
||||
2259x1271 -> 3840x2160 comparison completes twelve finite control/candidate
|
||||
frames, all six candidate RGB outputs exact, with all expected native hits and
|
||||
valid timings (`k-output-wgp-clean-source-final-4k`). This supplies clean build
|
||||
provenance without changing the tested binary identities.
|
||||
|
||||
The subsequent Silent Hill 2 game check combines the exact CMake shared-V enc0
|
||||
and those private WGP outputs. Package source is clean `68b551b`; the runtime
|
||||
remains the validated `67127dd` ZLUDA build with its warm cache, while the
|
||||
offline output objects carry WGP placement. DLSS is the locally provided
|
||||
310.9.1.0 DLL. Async interop and batched GPU inputs are enabled; debugger,
|
||||
serializing/deferred kernel profiling, detailed stage/boundary timestamps and
|
||||
output scans are disabled.
|
||||
|
||||
After the user confirms the stationary foreground comparison scene, thirty
|
||||
seconds capture 1954 presents: **65.250 FPS**, mean/median/p95 frame intervals
|
||||
15.326/15.318/16.306 ms. Every present uses Hardware Independent Flip with
|
||||
SyncInterval 0. PresentMon mean GPU busy/wait is 14.403/0.807 ms. Sixty unique
|
||||
ADLX polls record **93.500%** mean device usage, **3118.400 MHz** core,
|
||||
2505 MHz VRAM and **318.817 W** board power, with 57 C temperature and 82.9 C
|
||||
hotspot. Median telemetry query time is 0.083 ms per 500 ms poll.
|
||||
|
||||
The preceding accepted scene capture was 64.661 FPS: the new result is only
|
||||
0.589 FPS higher, about 0.91%, with mean frame interval 0.139 ms shorter.
|
||||
This is one historical control and one candidate capture, without a fresh
|
||||
repeated game A/B. It does not establish a reproducible gain or isolate enc0
|
||||
from output placement. WGP remains an optional experiment, and the overall
|
||||
K performance gate stays open.
|
||||
|
||||
The full bounded run completes **35664 K frames** and **427968 native
|
||||
launches**, including feature recreation and color-format reimports. There
|
||||
are zero backend errors, CPU image copies, previous-frame outputs or recorded
|
||||
crashes. `diagnostic_timeout` denotes the intentional ten-minute stop.
|
||||
Numerical game scans are off, so the game's zero reported nonfinite count is
|
||||
not a NaN/Inf validation result; use the separate finite/exact-frame gates.
|
||||
Raw capture, environment, package identities and summary remain in
|
||||
`test-results/silent-hill2-k-vshare-wgp-4k` and its diagnostic ZIP.
|
||||
|
||||
```powershell
|
||||
.\scripts\windows\build-zluda-windows.ps1 -InstallRoot "$PWD\dist\zluda-windows-wgp-experiment"
|
||||
.\scripts\windows\build-native-texture.ps1 -DlssDll "$PWD\nvngx_dlss.dll" -ZludaRoot "$PWD\dist\zluda-windows-wgp-experiment" -ShaderMode wgp -OutputDirectory "$PWD\build\private-textures-wgp-gfx1201"
|
||||
.\scripts\windows\build-native-texture.ps1 -DlssDll "$PWD\nvngx_dlss.dll" -ZludaRoot "$PWD\dist\zluda-windows-wgp-experiment" -ShaderMode wgp -Kernel hiluma_engine_output_depthreg_mvhi_ldr_max_v2_rel -OutputDirectory "$PWD\build\private-textures-wgp-gfx1201"
|
||||
.\scripts\windows\test-native-texture.ps1 -TextureRoot "$PWD\build\private-textures-wgp-gfx1201" -ControlTextureRoot "$PWD\build\private-textures-gfx1201" -ZludaRoot "$PWD\dist\zluda-windows-deferred-profile" -OutputResolution 3840x2160
|
||||
```
|
||||
|
||||
The compiler placement unit passes, all seventeen hardware/software CTest gates
|
||||
pass on the clean source build with ordinary CU defaults, and the six ZLUDA
|
||||
gates also pass with WGP explicitly enabled. All seventeen patches (0002..0018)
|
||||
apply to the clean pinned base `ee2f25a`. The numerical benchmark's rejected
|
||||
F16 candidate stops after its two ordinary reference replays with differing
|
||||
output and no timing samples (`k-replay-rejected-f16-gate-fixed`).
|
||||
|
||||
### Diagnostic environment and input dimensions
|
||||
|
||||
Some PowerShell/.NET hosts preserve removed process variables as empty strings.
|
||||
Presence-based Rust diagnostic flags then select deferred profiling, while
|
||||
empty codegen values can disable WMMA. The probe/game child environments now
|
||||
omit empty `D4R_` keys; the probe restores codegen defaults for null or empty
|
||||
values. Disabled WGP is also omitted so older runtimes keep their warm cache.
|
||||
The texture test requires valid timing records instead of silently accepting
|
||||
a profiling-free comparison. The initial candidate attempt times out during
|
||||
NGX initialization with no accepted frame; later pre-fix comparisons have
|
||||
correct RGB but no accepted GPU timings. Their logs remain in
|
||||
`k-output-wgp-reference-small`, `k-output-wgp-reference-small-fixed` and
|
||||
`k-output-wgp-reference-4k-fixed`; they are excluded from the table above.
|
||||
|
||||
The D3D12 harness now supports `--ngx-input-resolution WIDTHxHEIGHT`, exposed
|
||||
as `-NgxInputResolution` in the probe runner and `-InputResolution` in the
|
||||
texture/async gates. Output defaults and limits remain unchanged. This allows
|
||||
the game's non-aligned input dimensions without inventing a larger output.
|
||||
An initial attempt using 4518x2542 output is rejected by the harness's existing
|
||||
range guard before GPU initialization; it is not a GPU or enc0 failure.
|
||||
|
||||
### Rejected K input-rounding overrides
|
||||
|
||||
The remaining translated K input is about 0.34-0.40 ms in the earlier
|
||||
game-sized standalone profile. The private builder now exposes the existing
|
||||
surface-store/rounding recipe for both tested input variants. These inputs
|
||||
have **zero surface stores**: the actual change replaces eight round-half-away
|
||||
idioms with the existing recipe, avoiding constrained arithmetic lowering.
|
||||
It is not a native surface-store saving. Build metadata records the recipe's
|
||||
counts and refuses a no-op override.
|
||||
|
||||
CU and WGP input objects are built from the same clean `fb0adc8` ZLUDA source.
|
||||
Both retain accuracy mode and wave32; native FP8 remains disabled. The full
|
||||
pipeline control and candidate share all thirteen other code objects,
|
||||
including the same private WGP output tails. Only the two input overrides
|
||||
are added. Four frames per variant at 512x288, then eight per variant at
|
||||
2259x1271 -> 3840x2160 in CU mode, then eight in WGP mode with candidate-first
|
||||
order complete **80 finite control/candidate frames**. All forty candidate
|
||||
RGB images match exactly. Every expected input launch and valid serializing
|
||||
timing is checked; raw logs and module SHA256 values are retained.
|
||||
|
||||
| Input median, ms | Translated, CU test | Native CU | Translated, WGP test | Native WGP |
|
||||
| --- | ---: | ---: | ---: | ---: |
|
||||
| LDR / regular depth / high-resolution MV | 0.350050 | 0.359425 | 0.351000 | 0.358800 |
|
||||
| HDR / inverted depth / low-resolution MV | 0.512300 | 0.556350 | 0.412650 | 0.552100 |
|
||||
|
||||
These are separate-process diagnostic measurements with eight samples each;
|
||||
other unchanged kernels also vary between processes. Neither input candidate
|
||||
shows a saving. Both are rejected for game installation and default packaging;
|
||||
the validated game configuration keeps translated input. Results:
|
||||
`test-results/k-input-native-stores-small` (initial filename; no stores were
|
||||
replaced), `k-input-rounding-cu-game-input`,
|
||||
`k-input-rounding-wgp-game-input-reverse` and
|
||||
`k-input-rounding-experiment-summary.json`.
|
||||
|
||||
The comparison script's `-KernelStage input` selects the input hit/timing gate.
|
||||
`-CommonTextureRoot` holds output objects identical in both processes; staged
|
||||
object hashes are recorded. The ordinary output gate now accepts a translated
|
||||
control when its object is absent, while still requiring a native candidate.
|
||||
Rebuilding the two original WGP output objects preserves their SHA256 values;
|
||||
the default translated-output comparison also passes four finite frames and
|
||||
two exact candidate RGB images
|
||||
(`k-output-recipe-translated-control-regression`). Input objects remain private
|
||||
and are excluded by the game's existing output-only installation allowlist.
|
||||
|
||||
Reproduce the WGP experiment with locally built, validated output tails:
|
||||
|
||||
```powershell
|
||||
foreach ($kernel in @('hiluma_engine_input_depthinv_mvlo_hdr_v2_rel', 'hiluma_engine_input_depthreg_mvhi_ldr_v2_rel')) {
|
||||
.\scripts\windows\build-native-texture.ps1 -DlssDll "$PWD\nvngx_dlss.dll" -ZludaRoot "$PWD\dist\zluda-windows-wgp-experiment" -ShaderMode wgp -Kernel $kernel -OutputDirectory "$PWD\build\private-input-textures-wgp-gfx1201"
|
||||
}
|
||||
.\scripts\windows\test-native-texture.ps1 -KernelStage input -TextureRoot "$PWD\build\private-input-textures-wgp-gfx1201" -CommonTextureRoot "$PWD\build\private-textures-wgp-gfx1201" -ZludaRoot "$PWD\dist\zluda-windows-deferred-profile" -InputResolution 2259x1271 -OutputResolution 3840x2160 -Iterations 8 -CandidateFirst -OutputDirectory "$PWD\test-results\k-input-rounding-wgp-retest"
|
||||
```
|
||||
|
||||
Further game coverage (HIP kernel profiling disabled, GPU output checks enabled):
|
||||
M at 1920x1080 completes 4833 frames, all finite. K at 3840x2160 completes
|
||||
4685 frames, all finite. Neither has a backend failure, CPU image copy or an
|
||||
aged-frame fallback. Their mean interop/NGX CPU stages total about 13.6 and
|
||||
10.1 ms respectively; these are different scenes, not a K/M comparison.
|
||||
|
||||
The no-debugger K/4K run completes 5774 frames, with 5774 finite output scans
|
||||
and 63514 native transformer launches. The user reports 38-42 FPS. Additional
|
||||
CPU measurements exclude replay/publication as the main cause of low FPS:
|
||||
|
||||
| CPU measurement | Mean, ms | Median, ms |
|
||||
| --- | ---: | ---: |
|
||||
| Command split setup | 0.284 | 0.275 |
|
||||
| State replay within split setup | 0.025 | 0.023 |
|
||||
| Submitted texture state publication | 0.029 | 0.029 |
|
||||
| Consumer suffix completion | 0.405 | 0.409 |
|
||||
| NGX recording interval | 27.474 | 28.466 |
|
||||
|
||||
Recording intervals are between NGX recording calls on the same thread, not
|
||||
DXGI Present times. The interval includes rendering and application scheduling.
|
||||
A second K/4K run with the attached debugger completes 3567 frames without
|
||||
failure, with median recording interval 30.091 ms. The runs include different
|
||||
menu/game states; this does not establish a precise debugger FPS speedup.
|
||||
Its sparse debugger events also rule out a per-kernel OutputDebugString storm.
|
||||
An earlier control that stayed on the startup screen completed zero DLSS frames
|
||||
and is excluded. Normal game launches now omit the attached debugger; crash
|
||||
diagnostics remain available with `-CaptureExceptions`.
|
||||
|
||||
The 2961-frame 4K K profile identifies the translated output tail as its largest
|
||||
kernel: 4.401670 ms mean GPU time, versus about 2.875 ms for all eleven native
|
||||
transformer layers combined. Ported upstream's texture-store recipe to native
|
||||
Windows. It retains accuracy mode, wave32, FP16 subnormals and f16 reference
|
||||
accumulation; native FP8 remains disabled.
|
||||
|
||||
Both output variants execute on every checked frame and match the previous
|
||||
RGB output bit-exactly: eight consecutive 512x288 frames per variant, then
|
||||
three consecutive 3840x2160 frames per variant. All RGBA components are finite.
|
||||
Identical synthetic inputs and public NGX flags give these 4K event times
|
||||
(three samples each; host initialization and readback are outside the event):
|
||||
|
||||
| K output variant | Translated mean, ms | Native stores mean, ms |
|
||||
| --- | ---: | ---: |
|
||||
| LDR, regular depth, high-resolution MV | 2.907823 | 1.803233 |
|
||||
| HDR, inverted depth, low-resolution MV | 2.978547 | 2.088347 |
|
||||
|
||||
A subsequent game run executes 6221 frames with the native HDR output tail,
|
||||
zero backend failures and mean tail GPU time 1.801918 ms. The earlier game
|
||||
profile's 4.401670 ms is from a different scene/scheduling state; use the
|
||||
identical-input table for the controlled comparison, not an inferred FPS
|
||||
multiplier. This profiled game run did not enable the NaN scan.
|
||||
|
||||
Reproduce the private texture build and full-frame comparisons:
|
||||
|
||||
```powershell
|
||||
.\scripts\windows\build-native-texture.ps1 -DlssDll "$PWD\nvngx_dlss.dll"
|
||||
.\scripts\windows\build-native-texture.ps1 -DlssDll "$PWD\nvngx_dlss.dll" -Kernel hiluma_engine_output_depthreg_mvhi_ldr_max_v2_rel
|
||||
.\scripts\windows\test-native-texture.ps1 -OutputResolution 3840x2160 -Iterations 3
|
||||
```
|
||||
|
||||
These objects contain code derived from the locally supplied NVIDIA PTX. They
|
||||
stay in ignored local directories and are excluded from the public package.
|
||||
The installer accepts them with `-LocalTextureKernels` only after validation,
|
||||
checking the exact DLL identity, object and manifest hashes. M retains its
|
||||
independently validated FP16-equivalent baseline.
|
||||
|
||||
The following no-debugger K/4K run completes 9982 frames and 9982 finite GPU
|
||||
scans. Kernel event profiling is disabled; the validated private output tail
|
||||
executes natively. The user reports 43-47 FPS. Mean NGX recording interval is
|
||||
21.867 ms. No backend failure, CPU image copy or previous-frame output occurs.
|
||||
|
||||
Random one-in-64 hook samples then identify contention in the shared routing
|
||||
table used by every intercepted D3D12 command. Per-thread weak lookup caches
|
||||
now bypass that table on repeated calls to a list. Table mutations invalidate
|
||||
cache generations; Reset/address reuse cannot route to a previous suffix, and
|
||||
thread caches do not retain game resources. The per-list and submission locks
|
||||
remain. A GPU regression resets and re-splits the exact same list with changed
|
||||
root constants twice per iteration, checking both prefix and suffix results.
|
||||
|
||||
| Sampled command-hook access | Shared table | Per-thread weak cache |
|
||||
| --- | ---: | ---: |
|
||||
| Busiest recording thread, mean us/call | 0.203 | 0.066 |
|
||||
| Estimated access + capture across threads, ms/s | 977.528 | 233.606 |
|
||||
|
||||
The latter estimate includes lock waits summed across concurrently running
|
||||
threads, not CPU execution time or serial frame latency. The two game runs
|
||||
have different thread populations (31 versus 29); there is no identical frame
|
||||
trace. Generated forwarding methods have separate driver/capture markers;
|
||||
special-case hooks contribute access samples but lack those body markers.
|
||||
|
||||
With the cache, 4770 complete K/4K frames and finite GPU scans pass, with zero
|
||||
backend failures, CPU image copies or previous-frame output. Median NGX
|
||||
recording interval is 19.473 ms. The user reports 49-51 FPS and 53% GPU usage
|
||||
in the previously measured scene. These user readings are separate from the
|
||||
sampled hook estimates and do not establish isolated WMMA utilization.
|
||||
All sixteen CTest gates pass, including 64 same-object Reset/split checks in
|
||||
each physical command-backend test and the software indirect-root regression.
|
||||
Use `-ProfileCommandHooks -ProfileStages` to collect samples; the sampler is
|
||||
disabled for ordinary play.
|
||||
|
||||
Native M FP8 was subsequently compiled and tested on this gfx1201. ISA confirms
|
||||
`v_wmma_f32_16x16x16_fp8_fp8`, with packed e4m3 weight images; exact FP16
|
||||
attention/PV remains. All logical outputs and merges in forty recorded launches
|
||||
match the previously NumPy-validated FP16 baseline byte-for-byte. Full DLSS RGB
|
||||
also matches exactly: four 512x288 LDR frames and four 3840x2160 HDR frames,
|
||||
all RGBA finite. This establishes correctness for those fixtures, not a speedup.
|
||||
|
||||
The original software operand packing makes the FP8 network slower in the
|
||||
four-frame 4K test: sum of five main-kernel event means (tube weighted six times)
|
||||
is 27.789640 ms versus FP16's 23.550875 ms. A paired in-process replay confirms
|
||||
the regression without relying solely on separate process timings. Both modules
|
||||
and prepared weights remain resident, 512 launches warm the GPU, then sixty-four
|
||||
AB/BA pairs time the same restored input using HIP events. Diagnostic CPU input
|
||||
restoration is outside the timed event and is unrelated to game VRAM interop.
|
||||
|
||||
Added opt-in `D4R_FP8_HW_PACK`: native packed conversion of already quantised
|
||||
operands replaces software exponent/subnormal reconstruction. It preserves all
|
||||
254 finite OCP e4m3 encodings, including signed zero, in an exhaustive GPU check.
|
||||
All forty recorded launches still match exactly. Four complete 4K HDR frames
|
||||
also match FP16 RGB exactly with finite RGBA. ISA confirms both packed converts
|
||||
and FP8 WMMA. The baseline build's sixteen objects remain byte-identical.
|
||||
|
||||
| Paired replay median, ms | FP16 (software-packing test) | FP8 software packing | FP16 (hardware-packing test) | FP8 hardware packing |
|
||||
| --- | ---: | ---: | ---: | ---: |
|
||||
| enc1 | 0.175450 | 0.217050 | 0.175100 | 0.177700 |
|
||||
| enc2 | 0.141350 | 0.164550 | 0.132550 | 0.131550 |
|
||||
| enc3 tube | 0.108000 | 0.112000 | 0.107600 | 0.099850 |
|
||||
| dec2 | 0.129900 | 0.146000 | 0.143250 | 0.140850 |
|
||||
| dec1 | 0.169650 | 0.194450 | 0.154250 | 0.156550 |
|
||||
|
||||
These are two paired tests on the captured 512x288 workload. Medians avoid large
|
||||
isolated scheduling outliers; raw per-pair ratios are retained. They identify a
|
||||
substantial cost in software packing but do not establish an overall FPS gain.
|
||||
The separately run four-frame 4K hardware-packing network mean is 24.603463 ms;
|
||||
it still does not beat the measured FP16 total. Default packaging retains FP16.
|
||||
Hardware counters for bandwidth or WMMA utilization were not measured.
|
||||
|
||||
Reproduce the isolated build, encoding/replay checks and paired timings using
|
||||
the existing private validated captures; no source editing is required:
|
||||
|
||||
```powershell
|
||||
.\scripts\windows\build-native-m-fp8.ps1 -DlssDll "$PWD\nvngx_dlss.dll" -HardwarePacking
|
||||
.\scripts\windows\test-native-m-fp8.ps1 -ModuleDirectory "$PWD\build\native-m-fp8-hardware-pack" -CaptureDirectory "$PWD\test-results\ngx-m-exact-pv-capture\captures" -BaselineValidation "$PWD\test-results\m-native-exact-pv-temporal-reference\summary.json" -Benchmark
|
||||
```
|
||||
|
||||
Omit `-HardwarePacking` to compile the original FP8 experiment. The replay
|
||||
validator stops at the first mismatch, retains GPU stdout/stderr/exit code and
|
||||
hashes every compared logical output. `profile_report.py` accepts replay logs
|
||||
and reports per-pair GPU time and candidate/control ratios. This experiment is
|
||||
not installed by the game runner or substituted silently for the baseline.
|
||||
The conversion builtin is listed in the official
|
||||
[Clang AMDGPU builtin reference](https://clang.llvm.org/docs/AMDGPUBuiltinReference.html#builtin-amdgcn-cvt-pk-fp8-f32).
|
||||
|
||||
References: [HIP events](https://rocmdocs.amd.com/projects/HIP/en/develop/doxygen/html/group___event.html),
|
||||
[HIP occupancy API](https://rocm.docs.amd.com/projects/HIP/en/latest/doxygen/html/group___occupancy.html).
|
||||
@@ -1,62 +0,0 @@
|
||||
D4R WINDOWS QUICK TEST -- READ THIS FIRST
|
||||
|
||||
This is an EXPERIMENTAL Windows 11 D3D12 build for RDNA3 / RDNA3.5 / RDNA4.
|
||||
Only RX 9070 XT has been tested here. Other cards may fail.
|
||||
The package detects the real GPU automatically. Do not rename any DLLs.
|
||||
|
||||
1. EXTRACT THE WHOLE ZIP to a normal writable folder, e.g. Desktop\d4r-test.
|
||||
Do not run it inside the ZIP. Do not copy files into the game manually.
|
||||
Already installed an older test? Close the game and run RESTORE-GAME.cmd
|
||||
from that old package first, then extract this version to a new folder.
|
||||
|
||||
2. CLOSE YOUR GAME. If your distributor included the validated NVIDIA DLL pair,
|
||||
it is selected automatically; you only need to choose the game executable.
|
||||
Otherwise have these TWO ORIGINAL NVIDIA files ready:
|
||||
_nvngx.dll version 32.0.16.1714
|
||||
nvngx_dlss.dll version 310.9.1
|
||||
The xdfnx-dev public test ZIP does not include them. Other versions are rejected.
|
||||
The small _nvngx.dll inside this package is d4r, NOT the original NVIDIA file.
|
||||
|
||||
3. DOUBLE-CLICK START-K.cmd. Pick the actual game .exe when asked.
|
||||
If asked, pick your two NVIDIA DLLs. These choices are remembered for the next run.
|
||||
Next time, press Enter for the same game, or C to choose another.
|
||||
If Steam/Epic is needed, keep it open. Choose a D3D12 game without anti-cheat.
|
||||
If a launcher opens, type C and choose the real game executable next time.
|
||||
|
||||
4. IN THE GAME, select DLSS if available, otherwise FSR/XeSS for OptiScaler.
|
||||
Leave frame generation OFF. First launch can compile for several minutes.
|
||||
Keep the console open. Play for 30 seconds, check the image, then EXIT THE GAME.
|
||||
START-M.cmd tests DLSS 4.5 preset M; START-K.cmd tests DLSS 4 preset K.
|
||||
|
||||
5. SEND THE SINGLE ZIP shown as "SEND THIS ONE FILE" in the console.
|
||||
It is also in the results folder. Tell us your GPU, game, K/M and image result:
|
||||
"correct image", "black screen", "crash" or "visual corruption".
|
||||
A passing backend log does not automatically prove the image is correct.
|
||||
Logs can contain local paths. Review them before posting them publicly.
|
||||
|
||||
TO UNINSTALL: close the game and double-click RESTORE-GAME.cmd.
|
||||
Original replaced files are backed up and restored; changed files are preserved.
|
||||
Restore the previous game BEFORE choosing a different game for the next test.
|
||||
Always launch tests through START-K/M.cmd, not the usual game shortcut.
|
||||
|
||||
IF SOMETHING FAILS:
|
||||
- Wrong NVIDIA DLL: select the exact versions above on the next run.
|
||||
- No supported GPU / HIP failure: send the ZIP; do not spoof the GPU architecture.
|
||||
- vkd3d/Wine detected: use the game's original native Windows D3D12 files.
|
||||
- Access denied: extract to a writable folder. Do not disable system security.
|
||||
- Do not start a second test while the first game is running.
|
||||
|
||||
No HIP SDK installation is required; the isolated runtime is included.
|
||||
This uses synchronous interop and output checks. No debugger is attached by default.
|
||||
Exit codes and loaded DLLs are logged. A debugger is only an explicit developer option.
|
||||
Your local DLSS DLL is staged beside the d4r shim automatically.
|
||||
It is a correctness diagnostic, NOT an FPS benchmark or an optimized daily-use build.
|
||||
Colour, depth, motion and output remain in VRAM in the runtime fast path.
|
||||
|
||||
Runtime files are in files/. Cache/settings are created in work/.
|
||||
Licenses are in licenses/. Corresponding sources are a SEPARATE release download;
|
||||
testers do not need to download or build them. NVIDIA DLLs, when supplied by a
|
||||
distributor, keep their separate license and are not part of the GPL source archive.
|
||||
|
||||
Report: https://github.com/countervolts/d4r/issues/10
|
||||
Source: https://github.com/xdfnx-dev/d4r
|
||||
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user