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
- 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
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.
A replay only means something if the denoiser gets the bytes the game gave it.
The capture now records, for every bound guide, the caller's own DXGI format and
texel size next to the plane (they differ from the CUDA array's for every
converted format, and B8G8R8A8_UNORM is four bytes to D3D12 and sixteen to the
float array), the names the caller registered each surface under as well as the
names the denoiser reads it as, the exposure texture's own geometry, and the
feature's creation state - dimensions, quality, create flags, output-subrect
setting and the effective render preset. A frame whose staging is not readable
aborts its whole capture instead of writing a descriptor without its plane.
The harness reads all of it back: it sizes and creates the feature from the
capture, creates each guide in the recorded format at the recorded size, uploads
the recorded bytes, applies the recorded scalars, subrect origins, inversion
flags and camera matrices, binds the exact source names and clears the ones the
frame stopped registering. A missing guide descriptor, a missing or mis-sized
plane, a truncated parameter line, a claimed exposure with no geometry, or a
capture taken before the creation state was recorded is refused rather than
filled in with a default, because a replay that invents any of it still renders
a plausible image that matches nothing the game produced.
Ray Reconstruction's eleven DLSS-D Swin layers still run ZLUDA's compile of
NVIDIA's PTX; at 1280x720 -> 3840x2160 on gfx1201 they are 30.2 of a 31.6 ms
frame. The denoiser's high-fidelity output kernel is the first one with a native
replacement: make_ptx.py replaces its whole-texel RGBA16F store
(sust.b.2d.v4.b16.zero) through d4r_sust_v4b16, kernels/build.sh builds the pair
as the `rr` family, and packaging builds it into every target folder including
the RDNA4 FP8 ones.
Both libraries define modules named cuda_dldn_engine_*, with different text, so
one manifest cannot take the union of their hashes: kernel_manifest.py now takes
the denoiser DLL as --rr-dll and lets only its hashes authorize a
cuda_dldn_engine_* binary, and package_release.sh passes it when the denoiser is
bundled.
Verified in the D3D12 harness with Ray Reconstruction at 1280x720 -> 3840x2160:
the output kernel drops from 1.44 to 1.00 ms/frame and the 66 MB raw output is
byte-identical to the run with every kernel translated.
docs/native-kernels.md gains the denoiser family, the per-kernel cost table and
the instruction counts that show why the Swin layers are the remaining work.
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.
- Reprepare enc3 weights each launch to avoid stale caches after feature recreation
- Require per-slot input markers before evaluating recorded frames
- Advance split-frame timelines only through completed frames
- Add cancellation and readiness tests plus recreation consistency checks
- Update architecture and native kernel documentation
ref #8
- 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