NGX's CNN takes this frame's exposure scale and pre-exposure in both translated kernels (input words 244-256,
reconstruction 592-604) and the previous frame's exposure as the input kernel's texture 352
(cuda_copy_exposure_kernel's half surface). The runtime left all of it at the model dump's values, so HDR games
with a pre-exposure other than 1 or a changing exposure measured 18-39 dB against NGX; now 54-64 dB.
AutoExposure (flag 0x40), which the shim refused for E/F: NGX runs K's log-mean measurement on M's grid every
second frame. exposure_k.comp MODE 3 writes it to the 1x1 image the kernels sample; sr/exposure_copy_e.comp
keeps the previous exposure. 60-66 dB over eleven frames at 960x540 -> 1920x1080, pre-exposure 19-21.
The reconstruction's jitter words 544-556 are (y, x); the runtime wrote (-x, -y), which matches only the
harness's first three jitters, so every later frame of a game's jitter sequence measured 26-28 dB. Twelve-frame
captures now measure 60-66 dB HDR and LDR; on the Steam Deck through the shim 51-67 dB against ZLUDA.
The D3D12 harness takes per-frame lists in D4R_HARNESS_PRE_EXPOSURE / _EXPOSURE_SCALE; d4r-e takes the
AutoExposure flag, per-frame exposure values and the game's exposure texture. E/F models need rebuilding
(the install's model cache key changes); older models keep the old binding and refuse AutoExposure.
Presets E (5) and F (6) run on d4r's own Vulkan engine without cooperative
matrices: the input and reconstruction kernels translated from the user's DLL
(engine/compile_sr_e.py, rr/ptx2rr.py), the network engine/sr/e_net.comp with
packed v_pk_fma_f16 accumulation (engine/cnn_sr/mma_f16.glsl, the default
head; --head-accumulation f32 keeps the f32 head). Runtime runtime_e.inc
(EModel/EEngine), game adapter game_e.cpp, replay d4r-e; the shim serves them
from engine\e and engine\f (D4R_ENGINE_MODEL_E_DIR / _F_DIR), LDR or HDR, any
render size, not with AutoExposure. build-engine-models.sh builds both.
Translator fixes that apply to every translated kernel: .relu on f16/f16x2
fma/add/mul was ignored; add.rz was always taken for the roundf idiom (lost
the log1pf correction term); formatted image stores expand at the call site
(SPIR-V image type fix); f16 mma.sync m16n8k8/k16, .const loads, shared
16-bit stores, aligned 32-bit arena words (D4R_WORD_ARENA), unified arena.
Steam Deck gfx1033: 2.55 ms at 640x360 -> 1280x720, 6.20 ms at 1080p
output; Rounded Quality sizes take mid_3x3 (reconstruction 2.44 -> 1.23 ms).
Ray Reconstruction CNN presets A-C (compile_rr3.py, the packed RR flavor)
stay out of this commit; engine/README.md already documents their tuning.
- Add native preset K kernels for gfx1030–gfx1036 using software matrix
products, with fast and accuracy builds and RDNA2 motion kernels.
- Follow OptiScaler's DLSS and RR preset overrides, sanitize unsupported
values and select the preset matching the feature's quality mode.
- Enable FSR 4 under NVIDIA GPU spoofing by exposing real AMD PCI IDs
to OptiScaler and FidelityFX modules; bundle AMD's loader and upscaler.
- Keep K on native kernels in engine auto mode unless HIP is selected,
and fall back to CUDA for M/L when shader_float8 is unavailable.
- Add native-engine K GPU timings, preset recreation harness controls
and regression coverage; fix the input-wait test's glibc name clash.
- Update configuration, installer guidance and release documentation,
simplify the README and move gameplay videos to docs/videos.md.
RDNA2 kernels remain untested on RDNA2 hardware; software matrix
arithmetic was validated against WMMA on RDNA3.
- [Interop] MarkerPollUs = auto is the new default: the input-marker wait learns when
each feature's inputs become ready, sleeps in <=200 us chunks, yields near the
prediction and backs off when late (d4r_input_wait.h); a number keeps fixed pacing
(0 yields). d4r_config.py no longer exports 200 when the key is unset
- D4R_SHIM_GPU_INPUT_WAIT=1 (experimental, split VRAM, age 0): NGX's null stream
waits on a coherent Vulkan word imported into HIP (d4rStreamWaitValue32Eq) instead
of CPU polling. The original readback marker stays the authority; a CPU watchdog
releases discarded lists and timeouts. Denoiser, verify, capture and dilation
frames keep the CPU wait
- D4R_SHIM_GPU_COMPLETION=1 (needs GPU_INPUT_WAIT): the bridge writes a completion
word right after the native output kernel (d4rNgxWriteValue32), and the game's queue
polls it with a bounded compute wait (kernels/support/vulkan_wait.comp), replacing
the split list's CPU timeline signal. frame_retired writes the same word on every
failure path
- D4R_SHIM_NATIVE_COMPLETION=1: a null-stream callback in the bridge signals the
split timeline (d4rNgxTimeline*); D4rFrameCompletion::can_signal only releases the
oldest outstanding frame
- RGBA8 output: tex_common.h adds an 'R4' redirect tag, so K's native output kernel
stores packed RGBA8 directly (D4R_SHIM_OUTPUT_RGBA8=1, checked against the kernel
manifest by d4rOutputKernelRgba8). Host packing handles RGBA8 too.
patches/vkd3d-proton/0004 (VKD3D_D4R_LINEAR_RGBA8=WxH) makes such outputs linear and
exportable so the result can be written in place
- D4R_SHIM_FUSE_RGBA8_INPUT=1: one Vulkan pass converts and copies RGBA8 color input
(vulkan_read.comp mode 5 matches the blit's toward-zero halves, plus a row stride)
- profiling: thread CPU time from the Unix bridge (Wine's GetThreadTimes ticks at
10 ms); game-queue D3D12 timestamps (vk_input/vk_dlss_wait/vk_output/vk_total);
gpu_eval split into input_gpu_wait and dlss_gpu; D4R_PROFILE_GPU_EVENTS,
_TIMESTAMPS, _LOG and _CPU_TIME=0 switch off individual parts for bisection
- bridge: D4R_NGX_STREAM_PRIORITY=high|normal runs NGX on a priority stream
(off by default; no gain measured)
- release_feature: a feature already marked retiring by a failed drain can still
be released normally
- harness: RGBA8 with motion and jitter scenes (re-quantized each frame),
D4R_HARNESS_RGBA8_RAMP, D4R_HARNESS_THRASH_MB to evict L2/Infinity Cache before
each evaluation
- kernels/native: in_hoist.py and split_output_paths.py (opt-in scheduling
experiments); scripts/build_k_ldr_output.sh builds K's LDR output with an
optional D4R_LDR_OUTPUT_MAX_VGPR cap
- tests: test_input_wait.py and test_latency_optimizations.py; MarkerPollUs and
frame-completion tests updated
- layer_m.comp builds relaxed by default (M_RELAXED: f32 accumulators, paired FP8
conversions, no activation table) with two windows per wave sharing weight tiles
(WPW=2); M_EXACT=1 keeps NVIDIA's roundings, bit-identical to the CUDA path
- layer.comp reuses weight tiles across its waves (TPW=2 in the 32-channel layers)
- engine/rr/rr2_w.comp: one wave per window for preset F's dec0_0 and enc0, used by
compile_rr2.py at the new default D4R_RR_RELAXED=3 (build_native_model.sh too);
D4R_RR_FUSE=1 matches the reference's fused multiply-adds, ptx2rr.py --snorm16
- [Engine] Network defaults to vulkan; the HIP network is opt-in
Run the signed CUDA-capable denoiser through feature 13 with independent D/E presets, pre-Init discovery, per-frame guide and camera snapshots, normalized integer guide staging, paired alpha output, and recorded-resource retirement.
Add the required ZLUDA/LLVM patch, behavioral configuration tests, GPU harness coverage, optional denoiser installation and packaging, and tested support limitations. Preserve upstream attribution and distinguish LLVM licensing from the ZLUDA portions of the patch.
A standalone Vulkan inference engine (engine/) for DLSS presets K and M that
runs from weights extracted from the user's own nvngx_dlss.dll, with d4r's
own input, network and reconstruction shaders or the native HIP network
layers, recorded into the game's command list by the shim. Opt-in
([Engine] Enabled / D4R_ENGINE=1); anything uncovered falls back to the
CUDA/ZLUDA path with the reason logged.
Byte-identical to NGX's CUDA backend under the phase-capable reference
(1706x960 -> 2560x1440, native HIP network, eleven frames, RX 9070 XT):
- K render- and display-resolution motion vectors, HDR and LDR
- K game-supplied exposure and automatic exposure with any pre-exposure
and exposure scale (one residual: effective exposure exactly 2 or 4)
- K and M with the DLSS indicator's inverted-axis parameters
- M with any exposure settings (NGX ignores them for M)
K packages need the current compile_k.py (marker D4RO0003).
Also: HIP shared buffers are pooled across feature recreation (ROCm leaks
destroyed imports), hipnet.bin must match the preset, M-only games do not
load the K model, install_d4r_runtime.sh stages k, k-ldr, m, m-ldr with
hip/, the activation table has a generator (gen_activation_m.py), and
package_release.sh can bundle the engine's shaders (never its weights).
Signed-off-by: woutermans <[email protected]>
- Add default-off PreferAccuracy for all native kernel families,
including RDNA4 FP8 variants.
- Restore intermediate FP8 quantization, per-MMA FP16 rounding,
denormal handling and NGX synchronization in accuracy mode.
- Select separately marked accuracy kernels and use a separate JIT
cache; reject mixed sets and never silently substitute fast kernels.
- Add a pinned GLIBC 2.41 build environment for ZLUDA/LLVM, the DLLs
and both kernel sets, with ABI checks and toolchain provenance.
- Support parallel target builds and pre-extracted PTX; correct
ROCm header paths and Clang-CL input handling.
- Bump to 0.1.3 and update release notes, documentation and tests.
Validation: 11 tests passed; all 912 kernels built; E/K/M GPU harness
runs completed with accuracy off/on. Packaged libraries loaded under
GLIBC 2.41 and require no GLIBC version newer than 2.38.
RTX image-quality parity remains unverified.
Fixes#6
Refs #6
- Fix Cyberpunk 2077 preset-K black artifacts by preserving FP16/FP64
denormal requirements while limiting denormal suppression to FP32.
- Fix stale direct-output redirects after array destruction, preventing
reused handles from inheriting an earlier feature's output buffer.
- Log rejected resource formats and dimensions, including failures after
startup, with rate limiting for repeated errors.
- Add opt-in blocking output synchronization with a dedicated bridge
export and fallback to context synchronization.
- Report output-wait CPU and wall time, and defer GPU timing queries
until asynchronous evaluation has completed. The CPU-overhead
mitigation for #7 still needs reporter confirmation.
- Reject release libraries requiring GLIBC newer than the configured
baseline, defaulting to 2.41, and document compatible builds.
Validation: shim and bridge builds pass; targeted redirect-lifetime and
format-logging checks pass.
Fixes#5Fixes#8
Refs #7
RDNA4 (experimental; untested on RDNA4 hardware)
- kernels/common/wmma_layout.h picks the WMMA operand/accumulator layout
per target; K (pwin_*) and M (swin_*) index through it, so the same
sources build for gfx11 and gfx12. D4R_WMMA_LAYOUT=12 on gfx11 is a test
shim that runs the gfx12 indexing on gfx11 WMMA.
- M can use native e4m3 FP8 WMMA on gfx12 (D4R_NATIVE_FP8=1). Texture
tails (enc0_tail, dec0_head) get gfx12 f16 and FP8 paths that match
ZLUDA's gfx12 lowering.
- ZLUDA patch 0007: gfx12 WMMA helpers, optional native FP8 MMA
(D4R_ZLUDA_WMMA_FP8_NATIVE), a layout override for testing, and an
architecture argument for d4r_emit. Texture kernels are now compiled
offline per target through d4r_emit (D4R_ZLUDA_EMIT) instead of on the
local GPU.
- New d4r.ini option [Kernels] NativeFp8 (default on), wired through the
shim and d4r_config.py. On gfx12 the bridge serves kernels/<arch>-fp8
when it is on.
- The bridge picks the KFD GPU with the most SIMDs (so an iGPU is not
chosen over a discrete GPU); D4R_GPU_ARCH overrides it.
- kernels/build.sh and package_release.sh build gfx1100-gfx1103 and
gfx1200/gfx1201 (plus -fp8 variants), and D4R_BUNDLE_TEX takes
per-target folders.
Performance (RDNA3; harness byte-identical unless noted)
- ZLUDA patch 0006: m16n8k8 f16 MMAs on WMMA (E; not bit-exact, 52-55 dB
per layer, D4R_ZLUDA_WMMA_K8=0 disables it), per-key weight-image slots
for native prep kernels (d4r_prep_key_at, d4r_prep_key_slots), and
wave64 builds of MMA-free kernels (D4R_ZLUDA_WAVE64).
- M: packed FP8 encoding, conflict-free patch-merge reads, scalar weight
loads in enc1, and weight prep once per weight set for the six enc3
tube blocks.
- K: CU mode for the six non-wide pwin layers.
- Texture kernels: every DLSS flag variant is built natively (24 K output,
8 M post, 4 M downsample, 4 M enc0), not only Townfall's; post and K
output run as wave64.
- M direct output: rrlite_downsample_kernel writes the shim's output
buffer; the shim's default direct-output presets are now 11,13.
Tools
- dump_runner takes the prep grid from d4r_prep_blocks and refuses
texture/surface dumps.
- New pwin_check.py, swin_check.py, model_enc3.py and tail_check.hip.
Docs: README GPU table and RDNA4 notes, building (patches 0002-0007,
d4r_emit), native-kernels (RDNA4 section), performance (new numbers),
packaging README. Version 0.1.2.