13 KiB
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 0008 in order |
| vkd3d-proton | 3dfc6f07 (the base GE-Proton11-3 ships), plus patches/vkd3d-proton/0001 through 0003 in order |
| 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
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 0008; 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), 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:
m16n8k8f16 MMAs (DLSS 3 CNN, presets E/F) on RDNA3 WMMA like the k16 ones (D4R_ZLUDA_WMMA_K8=0disables 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.shnow writes the_w64helper variants too. - 0007: gfx12 WMMA layout lowering, optional native e4m3 FP8 WMMA (
D4R_ZLUDA_WMMA_FP8_NATIVE=1), and an architecture argument ford4r_emit.D4R_ZLUDA_WMMA_LAYOUT=12on gfx11 is a validation shim, not a release setting. - 0008: post-phase kernels for native overrides (
NAME_post1…NAME_post8, see native-kernels.md). Preset K's dec5 layer runs as four phase kernels, so the K set needs this patch: an olderlibnvcuda.sowould skip the phases.
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
scripts/build_vkd3d_proton_d4r.sh ~/.cache/d4r-vkd3d-d4r
Patches 0001 and 0002 provide same-frame command-list splitting and resource-lifetime tracking; both are required by the shim. Patch 0003 adds experimental exportable linear textures, enabled only by VKD3D_D4R_LINEAR_TEXTURES=1. Point D4R_VKD3D_DIR (or VkD3DDir in d4r.ini) at the output and update d3d12.dll and d3d12core.dll together.
3. Shim, bridge and NVAPI identity
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
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
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:
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
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_ARCHScan select fewer targets); each gfx12 target also gets an<arch>-fp8variant; - writes the kernel manifest from the DLLs you list (it records hashes of their PTX, nothing else);
- stages OptiScaler as
dxgi.dllwith the settings inpackaging/optiscaler.settings, applied byscripts/configure_optiscaler.py; both full and clean ZIPs setNvngxPath=d4r\nvngx.dllexplicitly, retainingOptiDllPath=d4rfor other libraries; - includes
install.shinstead of NVIDIA's two DLLs by default, retaining any supplied texture kernels (built from NVIDIA's PTX bykernels/build.sh tex); builds accuracy texture sets withD4R_ZLUDA_EMITunless marked prebuilt sets are supplied inD4R_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.
D4R_BUNDLE_NVIDIA=installer is the default: the ZIP includes install.sh, and users run bash install.sh after extraction to fetch the pinned official NVIDIA DLLs. This mode requires D4R_BUNDLE_DLSS to match the DLSS 310.7.0 SHA-256 pinned in the installer, so bundled texture kernels match the downloaded library; D4R_BUNDLE_NGX is only needed with D4R_BUNDLE_NVIDIA=1, which retains the old DLL-bundling mode.
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 describes how the installed files work together.
GLIBC 2.41 release builds
Build the pinned environment with:
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–0008 applied |
D4R_VKD3D_SRC |
isolated vkd3d-proton checkout inside that directory, with its submodules and patches 0001–0003 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
python3 -m unittest discover -s tests -vincludes OptiScaler INI generation, full/clean package staging and NGX-routing checker regressions. Package tests use fixture binaries and GPU-build stand-ins; real DLL loading still needs the OptiScaler/Proton harness.scripts/check_environment.shlists the tools, GPU and Proton builds it finds.- The D3D12 harness (
scripts/run_d3d12_dlss_harness_proton.sh) drives DLSS outside a game.D4R_HARNESS_MOTION_SCENE=1 D4R_HARNESS_SAVE_FRAMES=1saves a temporal sequence for byte comparisons. Compare the regular output path againstD4R_SHIM_OUTPUT_PACKED=1and/orD4R_SHIM_INPLACE=1 VKD3D_D4R_LINEAR_TEXTURES=1, with VRAM interop, split frames and direct output enabled;D4R_HARNESS_OUTPUT_RGB10A2=1selects packed output.D4R_HARNESS_RECREATE_OUTPUT=1releases and recreates the game's output texture between completed frames; compare its copy and in-place sequences to catch imported-memory handle reuse.D4R_HARNESS_RECREATE=4 D4R_HARNESS_VERIFY_RECREATION=1checks repeated feature/quality recreation.D4R_HARNESS_SKIP_RECORDED_INPUT=1checks discarded command-list input readiness without injecting stale history.
- Native kernels have their own validation path; see native-kernels.md.