ask() takes the default on Enter or EOF, ignores whitespace, accepts any answer starting with y or n and
re-asks otherwise. Without a terminal (or with --yes) DO_ENGINE defaults to building the models.
RELEASE_NOTES.md: the install.sh engine setup, [Engine] Enabled = auto, and the FSR Ray Regeneration backend
that this build does not carry.
Verified copies go to ~/.cache/d4r: the next game's install copies them instead of downloading or building
again. Enabled = auto (the new default) turns the engine on when d4r/engine holds a model; the shim probes the
nine model folders. build-engine-models.sh gains --exact (NVIDIA's roundings) and --find-proton.
A fresh extract plus bash install.sh builds all 9 models in about a minute, and they run in the shim.
Engine-vs-CUDA path: K 67 dB, M/L 45-50 dB, RR D/E/F 43/46/37 dB.
- [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
- engine/compile_rr2.py, runtime_rr2.inc, engine/rr/rr2_m.comp, exposure_f.comp,
gen_rr2_enc0.py, rr2_pack.py, rr2_ref.py: the rr2_* model (nvngx_dlssd.dll 310.9's
third network) as d4r's own shaders - exposure, enc0 gather/block split, enc1-5 and
dec4-0 through one matrix shader, translated output passes; weights packed from the
DLL, argument blocks from the capture
- ptx2rr: match the driver's fused roundings - opaque-zero OR around cvt.rn.f16.f32
against v_fma_mix, half-away-from-zero formatted stores, UNORM 10:10:10:2 as RGBA32F
of q/1023, OCML tanhF with the AMDGPU exp lowering, binary16 fma and fetch roundings;
--probe for register bisection against ZLUDA
- dec0_m/swin_m/enc0_*: RR_MIX build option (D4R_RR_MIX=1), one v_fma_mix rounding per
32-deep step, ~5% faster, not bit-exact; default build stays exact
- runtime_rr.inc: RModel/REngine dispatch to the D4RR0002 model; replay_rr: RGBA32F and
A2B10G10R1010 texel sizes, roughnessPacked bit, larger debug staging
- shim: engine\rr-f model slot, 310.9 version probe so preset F is only claimed when the
CUDA path has it; d4r.ini / d4r_config.py Model = F; run_rr_engine_compare.sh D4R_RR_DLL
- kernels/rr/swin_native.h + rr_swin_native_test.cpp: HIP port of encoder 1 for the
FP8-product and rounding cost measurements
- engine/rr/README: preset F's block, options, capture-by-capture results, timings and
the open camera-matrix difference
The ten network layer dispatches only need dispatch serialization, not a
global memoryBarrier flush: each layer's cross-block traffic goes through
its own buffers, already published by the preceding stage's flush. An
empty compute->compute pipeline barrier keeps the ordering and removes
the flush cost: whole-frame median 2515.0 -> 2431.7 us at Balanced
(1488x837 -> 2560x1440), 3818.9 -> 3773.3 at Quality, 1892.6 -> 1810.6
at Performance, byte-identical to the captured launches (chain test
10/10 layers 100.0%, frame test inf dB, 8- and 16-frame outputs match).
Also documents this session's discarded probes (intra-frame barrier
relaxation, colSum subgroup shuffle, downsample BLOCK_Y 32, expansion
EO stride 24, cross-frame pipelining analysis, the NO_ROUND 7.0%
rounding-free ceiling) and adds the round_half.glsl include guard.
Add an optional D4R_INSTALL_MODE=asi release (d4r-<version>-asi.zip)
holding only d4r.asi and a companion d4r/ folder, to drop into an
existing OptiScaler plugin directory.
- Shim: export InitializeASI. It identifies OptiScaler by its PE export
name to find the active INI, then launches d4r-setup.exe out of
process (no GPU or network work under the loader lock). The .asi
build loads its runtime and config from the companion d4r/ folder.
- tools/d4r_asi_setup.cpp: native helper. It waits for the game to
exit, installs the D3D12 wrapper and the private d4r12core.dll beside
the EXE, and merges the NGX route into the loader's INI (including
GE-Proton's prefix-local INI) with backups. Unchanged launches do
nothing. It skips Proton helpers and background utilities and runs
setup for one plugin install at a time.
- scripts/private_d3d12_core.py: points vkd3d's d3d12.dll forwarder at
d4r12core.dll without moving code addresses.
- install.sh runs from inside the ASI's d4r/ as well as the proxy
release root. d4r-check.sh checks ASI installs (loader, plugin path,
LoadAsiPlugins, HookOriginalNvngxOnly, Wine drive paths).
- Packaging, build script, docs, ASI_README.txt and tests.
- engine/rr: d4r's own shaders for the denoiser frame (exposure, six encoders,
five decoders, hkpn output stage) at NGX layouts, plus PTX->GLSL/HIP packing
scripts, reference implementations and weight extraction
- runtime.h/runtime_rr.inc, game_rr.{h,cpp}: GameDenoiser wired into the engine
build (d4r-rr replay binary) and the D3D12 shim's feature-13 path
- shim: answer GetFeatureRequirements from d4r's own state only (the old
cross-binary CUDA handoff crashed OptiScaler's scan); drop the core's
CUDA GetFeatureRequirements import
- shim/harness: exact guide capture/replay of a frame's RR inputs
- kernels/rr: expanded enc0/engine prototypes; kernels/tools: ptxsim rewrite
plus rrsim and an engine test; vulkan: ptx2glsl FP8/cooperative-matrix
support, kvk inout buffers and KVK_DISABLE_OPTIMIZATION
- bridge: report the surface array in cuSurfObjectCreate traces
- packaging: RR settings and the ICU launch overrides in D4R_README
0008 was already taken by 0008-native-post-phase-kernels.patch, so the five
patches that follow it in the build order shift up by one: ray-reconstruction
PTX support, native-FP8 conversion, packed FP8 operands, shadow-store
coalescing and signed FP8 conversion. The patches themselves are unchanged;
only their numbers and the references in README.md, docs/building.md,
docs/native-kernels.md, docs/rr-engine.md, packaging/SOURCES.txt and
scripts/build_release_glibc241.sh move.
Patch 0011 merges a complete accumulator-register pair overwrite into one
shadow-layout conversion (reads, rewritten shadow accesses and block
boundaries prevent it; partial writes keep read/modify/write), and requests
eight waves per SIMD for gfx12 native-FP8 functions. Patch 0012 keeps signs
in the native conversion: finite overflow clamped, NaNs mapped to signed
infinity, post-conversion sign masks gone; plain and ReLU remain
exhaustive-table identical to the software codec.
Eighty-frame harness at 720p->4K, excluding the first twenty: control
24.764 ms, coalescing 23.340 ms, plus eight waves 20.135 ms, plus signed
conversion 16.234 ms (15.144 ms with the harness idle gap removed); all
eighty saved frames byte-identical to the matching control. Twelve- and
ten-wave budgets regress (25.56/24.61 ms); fast math changes the image
(18.92 ms) and is not selected.
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.
scripts/check_redistributable.py refuses NVIDIA binaries (by name and
version resource), NGX SDK headers, PTX and code objects, PTX translations
(marked by ptx2glsl.py/condense.py) and the engine's model data in the
repository, and in each release variant (clean/installer/full) whatever
that variant does not contain. package_release.sh runs it before zipping;
scripts/git-hooks/pre-commit runs it locally.
Signed-off-by: woutermans <[email protected]>
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]>
Implement NGX's Vulkan API over the existing CUDA backend. Compute shaders
pack the game's sampled images into buffers shared with CUDA (device-local
memory exported through the Wine bridge), and a device event in the game's
command buffer holds its queue until the result is written back, keeping
frame age at zero. DLSS reads inputs through pitch-linear textures and its
native output kernel writes the shared buffer directly; input and
completion waits are adaptive.
Make it work across engines: shared buffers are concurrent over every
compute-capable queue family (Indiana Jones records DLSS on async compute),
depth kept in an R32F colour image is accepted under a depth aspect, and the
extension-requirement query allows a null list. Spare buffer sets are
imported on the first frame and never while a frame is pending, since an
import can block on GPU work that is waiting for us; host staging covers any
shortfall.
Fix two exit hazards. A game quitting without NGX shutdown left the GPU
waiting on an event that only a killed thread would set, resetting the ring
10 s later: the bridge now runs a shim hook before teardown and skips all
CUDA destroy/sync calls once Wine is shutting the process down. The shim's
own entry point skips CRT static destructors at process termination, where
locks held by killed threads made the exit spin forever.
Add a Vulkan DLSS harness (dynamic, recreate, discard, invalid, exit,
compute-queue and in-flight modes), staging/depth probes, ABI/config tests,
and an OptiScaler settings overlay for Vulkan games.
Validate Env identifiers and accept UTF-8 BOMs and last-value INI keys.
Resolve the OptiScaler GPL license before builds and support both system
license locations. Match the bridge's KFD selection by SIMD count.
Preset K, byte-identical to the previous output in all captured buffers
and the harness image, measured on an RX 7700 XT:
- LDS row padding so WMMA operand loads hit distinct banks
- WGP mode for enc1/enc2/dec1/dec2, ds_bpermute half-wave exchange for
enc0/dec0/dec3, more waves per window in enc4/dec4/dec5
- cheaper operand plumbing in common/wmma_layout.h (packed f16
conversions, no dynamic vector indexing), raw buffer weight loads,
accumulator-init vectors prepared once
- enc1 as a single-buffer recompute layer, dec1 Q/K/V chains split
- dec5 as four dependent phase kernels
- Explicitly route OptiScaler to d4r\nvngx.dll in release packages.
- Extract INI generation into a helper that preserves line endings
and rejects missing or duplicate settings.
- Check NGX routing separately from file presence and return failure
when the installation is incomplete or misconfigured.
- Add an optional OptiScaler patch for external DLSS backends while
preserving AMD identity for FSR4, with matching launch guidance.
- Align portable and launcher marker polling defaults at 200 us.
- Log when d4r's model override replaces game or OptiScaler presets.
- Add configuration, package, routing and coexistence regression tests.
- Update installation documentation, add FSR/DLSS comparison videos
and ignore local .tools artifacts.
Refs: #7, #14
- 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.