Releases: NIGos/dlss5-bridge
Release list
v1.3.0
Two NGX evaluates could run at once, and that was a latent defect in the whole
Vulkan mirror rather than a limitation of any one title. It is fixed here.
Fixed
-
The mirror's D3D12 NGX evaluate and the game's own Vulkan NGX evaluate were
not serialised. The worker took no lock, and the render thread's hook section
is released before it wakes the worker, so both backends could be inside NGX at
the same time. Red Dead Redemption 2 faults on this; Baldur's Gate 3 does not,
and the difference is timing rather than safety. Both now take one critical
section, held around the forwarded call on one side and around the evaluate on
the other.What established it, rather than a guess: with every per-frame parameter dumped
at the fault and all of them in range, the private device reportingS_OK, and
the same build, game and values, the fault landed in a different module after a
different number of delivered frames on each run —nvapi64_impl.dllafter 89,
nvoglv64.dllafter 145. A malformed contract faults in the same place every
time. After serialising: 5400 frames, no fault. -
A game replacing its own super-resolution feature did not rebuild the
mirror's. Only a change of render or output size triggered a rebuild, and a
game can recreate at an unchanged size — switching HDR on, or going fullscreen,
does exactly that. The mirror then carried a feature whose temporal history was
accumulated under the configuration the game had just discarded, and the neural
add-on downstream, which matches features by create, had nothing to match and
said so while the mirror went on delivering. -
The exposure-texture refusal could not be overridden, though the log said it
could. The gate tested the flags the game declared rather than the ones the
config resolves to, and the mirrored feature was created from the game's value
either way, so settingflagsdid nothing. Both now read the resolved value, so
a game that drives DLSS from an exposure texture this build does not mirror can
be run withAutoExposureforced. Note that the arithmetically obvious value is
often107, which is treated as unset — Red Dead Redemption 2 declares43, so
the value to set is75.
Added
- The evaluate's failure branch now records the private device's removed reason,
the module the fault landed in, the number of frames delivered before it, and
every per-frame parameter as the block held them. This is what found the race,
and it costs nothing on a session that never faults.
Changed
vk_mirrornow defaults to 1, and is written into the generated config with
the rest. It was off by default and absent from the file, so a Vulkan user got
nothing and had no way to discover why. Hooking the Vulkan NGX entry points does
nothing in a process that has none, which is every DirectX game.- The generated config explains itself: the two keys that decide whether anything
happens are first, with a sentence each, and the rest is grouped rather than
being a list of sixteen bare numbers.
Tested on
- Red Dead Redemption 2, Vulkan: the mirror over the game's own DLSS, with the
exposure override, through HDR and fullscreen changes made mid-session. 5400
mirrored frames, no fault, and the neural add-on evaluating over the result. - Baldur's Gate 3, Vulkan: unchanged from 1.2.0.
- Image quality was not formally assessed on either.
v1.2.0
The driver's optical flow engine now works on Vulkan, which the previous release
said it never would. That claim was wrong, and this release is mostly the story of
why.
Hardware motion vectors on Vulkan
A game with no DLSS of its own, on Vulkan, can now be given a DLSS contract whose
motion vectors come from the NVIDIA driver — with no ReShade motion-vector shader
installed at all.
- The engine creates its own two textures on a private D3D11 device and opens
them on the private D3D12 one. It used to try the opposite:ID3D11Texture2D
aliases of the shared D3D12 textures the transport already creates, through
ID3D11Device1::OpenSharedResource1. That call is refused withE_INVALIDARGon
the driver this was developed on — and always has been. The same refusal is in
every D3D11 session log ever produced by this add-on: the mirror's
MakeSharedPairtries that direction first, is refused for every texture and
every format, and succeeds only by creating on D3D11 and opening on D3D12. - Nothing forced the failing direction. 1.1.0 documented, as a hard limit, that
the engine's textures had to be D3D12-created because the game's Vulkan device
imports them. That is true of the transport's four textures and false of the
engine's two, which are imported into nothing. The sentence was the limit. - Each frame's colour is copied into the engine's texture on the D3D12 side under a
CPU fence wait; NGX is handed the engine's motion-vector texture directly, with no
copy back.
Arming no longer needs a ReShade shader
The gate wanted motion vectors before it would build the transport, and the engine
that supplies them opens inside the transport. A machine with no motion-vector
shader installed therefore never armed, and the engine never got a first chance —
one had to be enabled once purely to open the door. The gate now accepts a session
on the expectation of the engine: the first frames build the transport and open it,
deliver nothing, and the vectors are real from the next one. If the engine then
refuses to open, the transport stands down rather than evaluating over an unwritten
texture.
Fixed
- The delivery gate refused every frame after the one that opened the engine.
It tested the motion-vector binding for a null resource, and the branch that
selects the engine leaves that null on purpose. The engine's branch had shipped
without ever executing. - An add-on unloaded while a frame was parked could hang the game: the worker's stop
path left the loop without setting the release event, and shutdown signalled the
events before stopping the worker rather than after. - A stalled queue retired the Vulkan mirror for the rest of the session. A stall is
now skipped and counted, and the mirror records nothing further until the queue is
observed to reach the stalled frame's own copies-done event. - The render thread's guard on the previous frame's park was shorter than the
worker's own budget, so one slow but successful evaluate stood the mirror down
permanently. - The status panel read the D3D11 optical flow session on a Vulkan runtime, so it
reported an engine that would open on the first frame over one that had already
tried and failed; and it reported no cost at all while the log printed one, because
it took the timer frequency from a field only the D3D11 path fills. - The panel reported no session for a working Vulkan mirror, and printed the render
size where the output size belonged. - A superseded synthetic session forced a second feature build, and a mirror rebuild
left the optical-flow engine's aliases on released textures. - A refusal told users the creation flags of a texture that had never been created,
beating the true message one line below it: with no motion-vector shader enabled
the panel now says so plainly. - Log lines corrected where they stated more than was established, including one
that named the game's own D3D11 device for a session opened on a private one.
Changed
- The add-on is
dlss5-bridge.addon64. Delete the olddlss5-dx11-bridge.addon64
— ReShade loads every add-on it finds, and two copies hook the same NGX entry
points over each other. The log says so if it happens; it cannot prevent it. The
old.cfgis read as-is, so settings carry over with nothing to do. - The source latch is released on D3D11 as well as Vulkan, so a game whose own DLSS
is switched off mid-session falls back to the synthetic contract instead of
delivering nothing until restarted. - Optical flow frame costs are no longer quoted. The figures from a standalone
harness and the one the add-on's own log reports measure different things and have
never been reconciled; the status panel reports the live cost for the session in
front of you.
Tested on
- Baldur's Gate 3, Vulkan: the mirror over the game's own DLSS, and the synthetic
contract with the driver's optical flow engine and no motion-vector shader
installed. The engine opens on its own, the conversion self-check reports zero
disagreement over 24000 sampled cells, and frames are delivered continuously. - Skyrim Special Edition, D3D11: the synthetic contract and the optical flow
engine over extended play. - Image quality was not assessed on either.
v1.1.0
The biggest release this project has had, and the last one. Three things are
new: Vulkan games are supported, motion vectors come straight from the NVIDIA
driver, and a game with no DLSS at all can now be given a DLSS contract built from
the two. All three are off unless turned on, and all three are NVIDIA-only.
The bridge is no longer D3D11-only, and no longer needs a third-party shader to
supply motion vectors. Both additions are off by default.
The Vulkan bridge
A Vulkan game's own DLSS contract is now read from the NGX evaluate and mirrored
onto the add-on's private D3D12 session, so the neural rendering add-on runs over
the game's own upscale at the game's own quality preset. Set vk_mirror=1 in
dlss5-dx11-bridge.cfg.
- The game's colour, depth and motion vectors are copied inside the same open
command buffer the detour arrives on. At that point the game's own images do
not yet hold this frame, so a copy recorded anywhere else reads the previous
one. - Depth is unpacked on the D3D12 side. A depth aspect copies as
X8_D24_UNORM_PACK32by specification, so the staging texture isR32_UINT
and a compute shader unpacks it into theR32_FLOATthe feature reads. No
Vulkan-side conversion and no format negotiation. - A frame the game's queue does not reach within 300 ms is skipped rather than
fatal, and the mirror records nothing further until the queue is observed to
reach that frame's own copies-done event.
Motion vectors from the NVIDIA driver
nvofapi64.dll — installed with the display driver — is driven directly through
its D3D11 interface, and its output is converted to the R16G16_FLOAT screen-space
vectors NGX expects. It is the first motion-vector provider tried; while it is
running, the three ReShade shader names are not consulted at all.
- No ReShade motion-vector shader is required. Previously the synthetic path
depended onvort_Motion.fxor an equivalent being installed and compiled. - Measured at 0.18 ms per frame at 3840x1600.
ofa_gridselects the grid size
(4 is the default; 2 costs about 63 MB more) andofa_perfthe performance
level. - Falls back to the shader providers, with a log line naming the reason, when the
driver is absent or will not open a session on the game's device.
Neural rendering for a game with no DLSS
What the two above add up to. For a game that never calls DLSS at all, a DLSS
contract is built from ReShade's depth buffer and the driver's motion vectors and
handed to the add-on as though the game had produced it — no engine support, no
DLSS in the game, no third-party shaders. Delivered at reshade_begin_effects.
synth_after sets the delay in seconds before it may arm; 0, the shipped
default, leaves it off.
A status panel in the ReShade overlay states which of the two sources is running,
the transport, the session and feature state, and the frame count.
Limitations
- NVIDIA only. The optical flow engine is the driver's. On a hybrid laptop
where the game renders on the integrated adapter, the driver will not open a
session and the shader providers are used instead. - The synthetic contract needs a depth buffer bound by generic_depth, at back
buffer size. A game that runs its own DLSS renders depth at render resolution
while ReShade presents at output resolution, so the sizes differ and the
contract is refused — correctly, since such a game has DLSS and needs the mirror
rather than the synthetic path. - Motion vectors from a ReShade shader are one frame old and lower quality
than an engine's own. The optical flow engine measures the finished frame, so it
has no access to what the engine knows about camera and object motion. Both are
reconstructions; the mirror, where it applies, is not. - A D3D11 game that switches its DLSS off mid-session stops being served until
it is restarted. The Vulkan path recovers from this; the D3D11 path does not. - The source-latch release is not verified. The path that hands the frame back
to the synthetic contract when a mirrored game's DLSS goes quiet has not been
exercised on any title. - Image quality was not assessed.
Fixed
- An add-on unloaded while a frame was parked could hang the game. The worker's
stop path left the loop without setting the release event, and shutdown signalled
the events before stopping the worker rather than after. - A stalled queue retired the mirror for the rest of the session.
- The render thread's guard on the previous frame's park was shorter than the
worker's own budget, so one slow but successful evaluate stood the mirror down
permanently. It is now derived from the two budgets it covers. - The status panel reported no session for a working Vulkan mirror, and printed
the render size where the output size belonged. - A superseded synthetic session forced a second feature build.
- A mirror rebuild left the optical-flow engine's D3D11 aliases on released
textures. - Log lines corrected where they stated more than was established: a stand-down
claiming to discard a feature that is released elsewhere, a rebuild reason naming
a size change on a handover, and a stall message naming causes never observed
reaching it.
Changed
- The source for the synthetic path, the Vulkan mirror and the ReShade add-on
API headers is now in the repository. The previously published source did not
include them and could not be built as documented. BRIDGE_VERSIONandversion.rcare back in step. The 1.0.28 binary reported
itself as 1.0.27.
Tested on
Two titles, and the coverage is uneven.
- Skyrim Special Edition, D3D11: the synthetic contract and the driver's
optical flow, over extended play. - Baldur's Gate 3, Vulkan: the mirror, but narrowly — four sessions, roughly
25000 mirrored frames, no crash. The mirror builds, delivers, the neural add-on
creates its feature over the result, and the stall path was exercised once and
recovered. Image quality was not compared.
Project status
This is the last feature release. The DLSS 5 add-on now supports D3D11 and
D3D9 directly, which was this bridge's original reason to exist — for those games,
use that add-on on its own; it is the one that gets updated. The three features
above are what it does not cover, and are why this release is still worth taking.
There is no active development after this. The repository stays up and stays MIT,
the source is complete and builds from a clean copy with the command in the README,
and issues can be opened and will be read — but assume nothing is fixed unless
someone picks it up. Fork it freely.
v1.0.27
Fixed
- A Ray Reconstruction evaluate is no longer mirrored onto the super-resolution feature. A denoise hands over the same
Color,Depth,MotionVectorsandOutputas an upscale, so those four cannot tell the two apart. Twelve resource keys that only the denoiser sets are probed on every evaluate, in both spellings, and a match is forwarded untouched. A feature created through these hooks was already recognised by handle; this covers the one case that table cannot, a feature created before the hooks went in. No shipping D3D11 title is known to produce such an evaluate: the NGX SDK definesNVSDK_NGX_D3D11_DLSSD_Eval_Params, but D3D11 has no ray tracing API and none of the denoiser's inputs exist. Insurance and a diagnostic; not verified doing its work.
Added
- The first five evaluates list
NormalRoughness,DiffuseAlbedo,SpecularAlbedoandSpecularHitDistance, so a log that hits this shows why nothing was mirrored. - A note in
bridge.incstating the three rules any second source of contract must obey: it must arrive already complete, the size fallback inBridgeFrameis a last-resort repair rather than a supply route, andDLSS.Feature.Create.Flagsneeds storage per source.
Changed
- The source for 1.0.21 through 1.0.26 is now in the repository. Seven tags resolved to a single commit and six releases shipped binaries whose source was never published.
v1.0.26is repointed at it. The earlier tags stay where they are rather than being moved, which would make each claim a later release's source. - The documented build command links
advapi32.lib.RegGetValueWis used and the line as written did not link. - The known limit "Only tested on one game and one GPU" is replaced. Nine titles across seven engines are listed thirty lines above it.
Notes
- Verified on Baldur's Gate 3 in that the stand-aside stays silent, the contract is unchanged and the session is clean.
v1.0.26
Fixed
- A game that reports its input and output dimensions the wrong way round has them swapped back. DLSS never returns an image smaller than the one it is given, so an output below the input is not a contract. Four engines write them inverted: Gallipoli, The Elder Scrolls Online, Phantasy Star Online 2 and House Party's Unity plugin. Earlier releases patched the output from the output texture instead, which works only while the allocation equals the display size; under dynamic resolution it never does, and the feature that was built could not be evaluated. Aimed at issues #5 and #8; not verified in either.
- An exposure texture supplied by the game is mirrored to the D3D12 side. Mount & Blade II: Bannerlord creates with
AutoExposureclear and supplies a 1x1 exposure texture every frame; the bridge copied the flags faithfully and dropped the texture, so its feature accumulated with no exposure at all. Before 1.0.16 the forcedflags=107carriedAutoExposureand hid this. The mirror uses the same typed-format conversion as the other four, without which a typeless exposure texture — Phantasy Star Online 2 supplies one — would have kept the defect. - The parameter block no longer keeps a released pointer when the exposure mirror is dropped: the key is cleared and the GPU drained first. The block is allocated once per session and NGX does not reference-count what it holds.
nvngx_dlssnr.dllandnvngx_dlss.dllare looked for beside the game as well as beside the add-on, and the log says which. ReShade can load add-ons from another directory, and the message claimed the game folder while only the add-on's had been searched.- The NGX data path is the game's folder when the two differ. Pointing NGX at a directory holding none of its files was never intended.
Added
- The fault address and the module that owns it, as an offset into that module, when NGX initialisation or device creation raises an exception. An absolute address changes every run.
probe=1creates a D3D12 device and callsInit_Extwithout waiting for the game to call DLSS, for titles whose DLSS comes from another add-on. Off by default.- Every add-on's load address is listed.
Changed
- The reactive mask was probed under a name that is not an NGX key. It is
DLSS.Input.Bias.Current.Color.Mask; the log asked forBiasCurrentColorMask, so every "absent" it has ever reported was a probe of a name nothing sets. Whether any title supplies one is still unknown. The transparency-layer keys are probed for the same reason. - Absent resources distinguish a key the game left unset from one this runtime does not have. NGX results are named rather than printed as signed decimals: the
-1160773616in every previous log was0xBAD00010,UnsupportedParameter.
Notes
- Verified on Baldur's Gate 3 only in that the three dimension repairs stay silent there, the contract is unchanged, and the session is clean. None of the fixes above has been seen doing its work.
- Issue #7 (Batman: Arkham Knight) is not fixed. It faults in
Init_Extlike Prey 2017; this release is the first that names the module and offset.
v1.0.25
Fixed
- The D3D12 device handed to NGX is ReShade's underlying device, not its proxy. ReShade wraps every D3D12 device created through the export, this add-on's own included, and then broadcasts
init_device,init_pipeline,init_samplerand the rest to every loaded add-on for everything built from it. Luma is a DX11-only framework whose compile-time API guard is off unless a game opts in, and Prey 2017 does not: itsOnInitDevicereturns early for a non-D3D11 device, so ReShade never gives it per-device data, and every other handler then dereferences that null.NVSDK_NGX_D3D12_Init_Extcreating pipeline state on the device was the first such event, and it faulted at an address insideLuma-Prey.addon. The proxy is now unwrapped through ReShade's ownIID_UnwrappedObject, so no other add-on is handed D3D12 objects it never asked for.unwrap=0indlss5-dx11-bridge.cfgrestores the old behaviour. Aimed at Prey 2017; not verified there. - No module is patched while this add-on's own NGX initialisation is running. The loader notification runs under the loader lock and was enumerating modules, reading version resources from disk and writing jumps into code. The guard was missing from the 1.0.24 binary; it is present here and a log line marks it running.
Added
probe=1creates a D3D12 device and callsNVSDK_NGX_D3D12_Init_Exton its own, without waiting for the game to call DLSS. Prey has no DLSS of its own, so removing the add-on that provides it also removed every call and left nothing to test. Off by default.- Fault addresses are reported as an offset into the owning module, and every add-on's load address is listed. An absolute address changes each run and tells the owner of that module nothing.
Notes
- Verified on Baldur's Gate 3, whose device is also wrapped: the unwrap runs, the session opens, and 17,000 frames and three feature rebuilds follow.
- Prey 2017 is unverified. The diagnosis predicts the session now opens there; if it does not, the diagnosis is wrong.
- On ReShade older than 6.6 there is no proxy to unwrap and behaviour is unchanged.
v1.0.24
Fixed
Correction. The first item did not reach this binary. The edit that guards the loader-lock callback was lost before the file was written, so
OnDllLoadedstill scans and patches unconditionally here. Present in 1.0.25, where a log line marks it running. The remaining items in this release are unaffected.
- No module is patched while this add-on's own NGX initialisation is running. The loader notification runs under the loader lock, on the thread doing the load, and it was enumerating modules, reading version resources from disk and writing jumps into code.
NVSDK_NGX_D3D12_Init_Extloadsnvngx_dlss.dllitself, so in Prey 2017 that notification arrived inside NGX's own initialisation and patched the snippet NGX was setting up;Init_Extfaulted 169 ms later. The scan is now deferred to a call site holding no lock. Aimed at Prey 2017; not verified there. - The DRED retry added in 1.0.21 did not turn DRED off.
D3D12_DRED_ENABLEMENT_DISABLEDis written nowhere in the add-on, so the second attempt ran under the identical setting and the message announced an action that never happened. Removed.dred=0indlss5-dx11-bridge.cfgremains the only way to make an attempt without DRED. - The command queue, list and fence event are checked before the session is marked ready. All three were created unchecked and dereferenced on the first frame. A null fence event was the worst of them:
SetEventOnCompletionon a null handle blocks the render thread with no timeout. - A feature handle reused by NGX for super resolution is dropped from the other-features table. Nothing removed entries and NGX recycles freed handle addresses, so a recycled handle made every later evaluate take the "not super resolution" path for the rest of the session.
- Layer slots are reused after a module unloads. Each unload and reload of an NGX module burned a slot permanently.
Added
- The fault address and the module that owns it are logged when NGX initialisation or D3D12 device creation raises an exception. Three competing explanations previously produced the same log line.
Notes
- Every item here was found by reading the code, not by reproducing it. None is verified in the positive: Baldur's Gate 3 reaches none of these paths and was used only to confirm nothing regressed.
- Prey 2017 without the OptiScaler proxy present still faults in
Init_Ext, so the proxy is ruled out as the cause, as are the NGX module choice fixed in 1.0.22 and the SDK version constant. - Verified on Baldur's Gate 3.
v1.0.23
Fixed
- The DLSS render preset is copied to the D3D12 feature. All six
DLSS.Hint.Render.Preset.*keys are mirrored when the game sets them. The preset selects which DLSS model runs, so the two sides were upscaling with different models and the neural-rendering add-on worked from the D3D12 one. Prey 2017 reaches DLSS through Luma, which sets these; DLSSTweaks, OptiScaler and many games set them directly. UnlikeMV.Scale,nvsdk_ngx_helpers.hdoes not write these keys, so an absent one is left absent rather than given a value.
Added
- A module that exports the NGX entry points but is not the driver's loader is named when the D3D12 session faults. Prey 2017 runs OptiScaler installed as
WINMM.dll: it patches code inside the driver's NGX module and opens its own session on it first, which is the difference from titles where the same driver and module initialise. The log now says so and names the test — running without the proxy.
Notes
- Baldur's Gate 3 sets no render presets and loads no NGX proxy, so both additions were verified only in that they stay silent. Neither has been seen doing its work.
- Prey 2017 on 1.0.22 takes the correct NGX module and still faults in
Init_Ext. The module choice fixed in 1.0.22 was a real defect but not the cause there. The SDK version is ruled out: Baldur's Gate 3 initialises with the same version, driver and module. - Verified on Baldur's Gate 3.
v1.0.22
Fixed
- The NGX D3D12 entry points are taken from the driver's loader, not from whichever module exports them first. Prey 2017 loads a third-party
WINMM.dllthat exports them too. It comes from the game folder, so it was enumerated ahead of the driver, and itsInit_Extfaulted — while the DLSS 5 add-on had hooked the driver's copy, leaving the two add-ons on different NGX modules._nvngx.dllnow wins wherever it lives; a proxy in the game folder under that name still wins, because it is the one the game itself reaches. Aimed at Prey 2017 and any title with an NGX wrapper beside it; not verified there.
Added
- The module the NGX D3D12 entry points came from is logged. Establishing this previously meant comparing an address against a module base by hand.
Notes
- Prey 2017 on 1.0.21 creates its D3D12 device and fails at
Init_Ext. The device-creation fault addressed in 1.0.21 no longer occurs there, so the retry with DRED off has still never run. - Verified on Baldur's Gate 3.
v1.0.21
Fixed
Correction. The retry below did not do what it says.
D3D12_DRED_ENABLEMENT_DISABLEDis written nowhere in the add-on, so the second attempt ran under the identical setting and the message announced an action that never happened. Removed in 1.0.24.dred=0indlss5-dx11-bridge.cfgis the only thing that produces an attempt without DRED.
- Device creation is retried once with DRED off when the first attempt raises an exception. DRED is switched on immediately before that call and is the only thing this add-on changes ahead of it, so it is taken back out rather than asking anyone to edit a file. Aimed at Prey 2017; the retry path has not run on a machine where device creation succeeds.
Added
- The NVIDIA driver version, alongside the Windows one. Reports carry
32.0.16.1656, discussions use616.56. - A warning when the driver is older than the one this release is verified on. Final Fantasy XIV on 560.94 could not create a neural-rendering feature and updating the driver fixed it.
- The denoising capability block reports its result by name and its declared minimum driver. A driver that does not carry the capability key at all is called out: that is what Final Fantasy XIV showed before the update. The minimum shown belongs to Ray Reconstruction and does not speak for neural rendering, which has no capability key of its own.
- Frame timings are marked when the game window is not in focus. An unfocused window changes the frame interval and the bridge's share of it, and the figure then reads as a regression that is not there.
Notes
D3D12CreateDevicein Prey 2017 carries one hook, ReShade's, with the same bytes after the jump as a title that works. A second injector was ruled out.- Verified on Baldur's Gate 3 and Final Fantasy XIV.