AMD FSR3.1 - FSR 4.1 - DLSS5 NR #1335

Closed
notquiteog wants to merge 146 commits from main into main
notquiteog commented 2026-11-09 22:03:50 +00:00 (Migrated from github.com)

Exactly as the title says, adds AMD FSR4 and DLSS5 NR with options, for older systems it supports FSR 3.1, next update adds NR for AMD and DLSS5 NR on linux

Exactly as the title says, adds AMD FSR4 and DLSS5 NR with options, for older systems it supports FSR 3.1, next update adds NR for AMD and DLSS5 NR on linux
hckrman101 (Migrated from github.com) reviewed 2026-11-09 22:03:50 +00:00
NotRexed commented 2026-11-09 22:23:24 +00:00 (Migrated from github.com)

Thanks for this. FSR 3.1 frame generation is something players have been asking for, and this is the only PR that has it. It's too much to review and test as one piece, though, so could you split it?

1. FSR 3.1 upscaling + frame generation on its own (vk_fsr3fi.cpp, the vendored FidelityFX files, AMD's runtime DLLs from GPUOpen pinned by commit as you have it now, the menu row). This one I'd like to take first. It'll be tested here for fps, frame pacing and visual flashes before it's merged.

2. FSR 4.1 and the DLSS 5 / Streamline path as separate PRs. Please include a short description of what each does, the GPUs and drivers they need, and how you tested them.

A few notes for the split:

  • No license acceptance in CI. The workflow currently runs scripts/ngx_sdk.py ... --accept-nvidia-license, so every release build would accept NVIDIA's DLSS license and ship NVIDIA's library. The maintainer hasn't decided on that, so please leave it out of the FSR PR. Today each player accepts the license themselves in the builder.
  • Pin NVIDIA Streamline to a commit SHA, not the v2.14.16 tag, the same way the AMD checkout is pinned.
  • Please keep release.yml and the other workflow edits out of the FSR PR unless the feature needs them, and say why for any that stay.
  • The FSR 3.1 PR should build and pass tests/run_all.py on current main by itself.

Once the FSR 3.1 part is up, I'll test it right away. Then #1313, #1095, #1096 and #1097 can be closed as superseded.

Thanks for this. FSR 3.1 frame generation is something players have been asking for, and this is the only PR that has it. It's too much to review and test as one piece, though, so could you split it? **1. FSR 3.1 upscaling + frame generation on its own** (`vk_fsr3fi.cpp`, the vendored FidelityFX files, AMD's runtime DLLs from GPUOpen pinned by commit as you have it now, the menu row). This one I'd like to take first. It'll be tested here for fps, frame pacing and visual flashes before it's merged. **2. FSR 4.1 and the DLSS 5 / Streamline path** as separate PRs. Please include a short description of what each does, the GPUs and drivers they need, and how you tested them. A few notes for the split: - **No license acceptance in CI.** The workflow currently runs `scripts/ngx_sdk.py ... --accept-nvidia-license`, so every release build would accept NVIDIA's DLSS license and ship NVIDIA's library. The maintainer hasn't decided on that, so please leave it out of the FSR PR. Today each player accepts the license themselves in the builder. - **Pin NVIDIA Streamline to a commit SHA**, not the `v2.14.16` tag, the same way the AMD checkout is pinned. - Please keep `release.yml` and the other workflow edits out of the FSR PR unless the feature needs them, and say why for any that stay. - The FSR 3.1 PR should build and pass `tests/run_all.py` on current `main` by itself. Once the FSR 3.1 part is up, I'll test it right away. Then #1313, #1095, #1096 and #1097 can be closed as superseded.
madebyjordan commented 2026-11-09 22:28:06 +00:00 (Migrated from github.com)

Two things for the split, so it doesn't overlap work that's already open or merged:

  • FSR 4.1 is already #1008 (mine). I'm updating it to run on #841's inputs: the colour, depth, camera jitter and motion vectors, including the characters' own. They move into a shared vk_temporal.cpp with a small engine interface, so DLSS and FSR 4.1 are two engines on one input path. Tested on an RX 6700 XT (FSR 4.1.2), and it also runs on Linux. A separate FSR 4.1 PR from this one would duplicate it. Happy to compare notes if yours does something #1008 doesn't.
  • For the FSR 3.1 PR: #841 already puts a camera jitter into the game (nx2/oot_jitter.py) and builds motion vectors with actor motion. This branch adds a second camera hook (nx2/oot_camera.py) and a second motion pass (vk_camera_motion.cpp). Taking #841's inputs instead keeps one jitter in the game and gives FSR 3.1 the characters' motion too. Once #1008's update is up, FSR 3.1 could plug in there as one more engine.
Two things for the split, so it doesn't overlap work that's already open or merged: - **FSR 4.1 is already #1008** (mine). I'm updating it to run on #841's inputs: the colour, depth, camera jitter and motion vectors, including the characters' own. They move into a shared `vk_temporal.cpp` with a small engine interface, so DLSS and FSR 4.1 are two engines on one input path. Tested on an RX 6700 XT (FSR 4.1.2), and it also runs on Linux. A separate FSR 4.1 PR from this one would duplicate it. Happy to compare notes if yours does something #1008 doesn't. - **For the FSR 3.1 PR**: #841 already puts a camera jitter into the game (`nx2/oot_jitter.py`) and builds motion vectors with actor motion. This branch adds a second camera hook (`nx2/oot_camera.py`) and a second motion pass (`vk_camera_motion.cpp`). Taking #841's inputs instead keeps one jitter in the game and gives FSR 3.1 the characters' motion too. Once #1008's update is up, FSR 3.1 could plug in there as one more engine.
notquiteog commented 2026-11-09 22:29:09 +00:00 (Migrated from github.com)

Thanks for this. FSR 3.1 frame generation is something players have been asking for, and this is the only PR that has it. It's too much to review and test as one piece, though, so could you split it?

1. FSR 3.1 upscaling + frame generation on its own (vk_fsr3fi.cpp, the vendored FidelityFX files, AMD's runtime DLLs from GPUOpen pinned by commit as you have it now, the menu row). This one I'd like to take first. It'll be tested here for fps, frame pacing and visual flashes before it's merged.

2. FSR 4.1 and the DLSS 5 / Streamline path as separate PRs. Please include a short description of what each does, the GPUs and drivers they need, and how you tested them.

A few notes for the split:

  • No license acceptance in CI. The workflow currently runs scripts/ngx_sdk.py ... --accept-nvidia-license, so every release build would accept NVIDIA's DLSS license and ship NVIDIA's library. The maintainer hasn't decided on that, so please leave it out of the FSR PR. Today each player accepts the license themselves in the builder.
  • Pin NVIDIA Streamline to a commit SHA, not the v2.14.16 tag, the same way the AMD checkout is pinned.
  • Please keep release.yml and the other workflow edits out of the FSR PR unless the feature needs them, and say why for any that stay.
  • The FSR 3.1 PR should build and pass tests/run_all.py on current main by itself.

Once the FSR 3.1 part is up, I'll test it right away. Then #1313, #1095, #1096 and #1097 can be closed as superseded.

On it rn

> Thanks for this. FSR 3.1 frame generation is something players have been asking for, and this is the only PR that has it. It's too much to review and test as one piece, though, so could you split it? > > **1. FSR 3.1 upscaling + frame generation on its own** (`vk_fsr3fi.cpp`, the vendored FidelityFX files, AMD's runtime DLLs from GPUOpen pinned by commit as you have it now, the menu row). This one I'd like to take first. It'll be tested here for fps, frame pacing and visual flashes before it's merged. > > **2. FSR 4.1 and the DLSS 5 / Streamline path** as separate PRs. Please include a short description of what each does, the GPUs and drivers they need, and how you tested them. > > A few notes for the split: > > * **No license acceptance in CI.** The workflow currently runs `scripts/ngx_sdk.py ... --accept-nvidia-license`, so every release build would accept NVIDIA's DLSS license and ship NVIDIA's library. The maintainer hasn't decided on that, so please leave it out of the FSR PR. Today each player accepts the license themselves in the builder. > * **Pin NVIDIA Streamline to a commit SHA**, not the `v2.14.16` tag, the same way the AMD checkout is pinned. > * Please keep `release.yml` and the other workflow edits out of the FSR PR unless the feature needs them, and say why for any that stay. > * The FSR 3.1 PR should build and pass `tests/run_all.py` on current `main` by itself. > > Once the FSR 3.1 part is up, I'll test it right away. Then #1313, #1095, #1096 and #1097 can be closed as superseded. On it rn
Brett-D commented 2026-11-09 22:33:18 +00:00 (Migrated from github.com)

For the DLSS 5 / NR part of the split: I have an NGX-direct path for feature 18 (NVSDK_NGX_Feature_DLSSNR) working on Vulkan in Hookshot — the fallback docs/neural-rendering.md mentions. It uses NVIDIA's own DLSS-NR NGX headers (the RTX Remix NGX package) and the DLSS SDK's nvsdk_ngx_s.lib. That means no Streamline DLLs and no reconstructed options struct, and it shares the NGX setup already merged in #841. Nothing of NVIDIA's is committed; the player fetches it the same way as #841.

Measured on an RTX 5090 (driver 621.14): the model evaluates in-game every frame and fps holds at 60 at 2048×1152. It uses 386 MB of VRAM, and a standalone test measured ~1.3–1.6 ms per frame at 720p. Every eval parameter is exposed (intensity, tone, structure, skin, style 0–7, auto mask, blend mode, UI correction). Like #1335 it has no motion vectors yet, so each frame is processed on its own.

One open question: whether the Remix package's terms cover use outside Remix. Happy to contribute it as the NR follow-up PR, or to hand the code to @notquiteog to fold in, whichever the maintainer prefers.

For the DLSS 5 / NR part of the split: I have an NGX-direct path for feature 18 (NVSDK_NGX_Feature_DLSSNR) working on Vulkan in Hookshot — the fallback docs/neural-rendering.md mentions. It uses NVIDIA's own DLSS-NR NGX headers (the RTX Remix NGX package) and the DLSS SDK's nvsdk_ngx_s.lib. That means no Streamline DLLs and no reconstructed options struct, and it shares the NGX setup already merged in #841. Nothing of NVIDIA's is committed; the player fetches it the same way as #841. Measured on an RTX 5090 (driver 621.14): the model evaluates in-game every frame and fps holds at 60 at 2048×1152. It uses 386 MB of VRAM, and a standalone test measured ~1.3–1.6 ms per frame at 720p. Every eval parameter is exposed (intensity, tone, structure, skin, style 0–7, auto mask, blend mode, UI correction). Like #1335 it has no motion vectors yet, so each frame is processed on its own. One open question: whether the Remix package's terms cover use outside Remix. Happy to contribute it as the NR follow-up PR, or to hand the code to @notquiteog to fold in, whichever the maintainer prefers.
nullifyshot commented 2026-11-09 22:34:00 +00:00 (Migrated from github.com)

May I ask why Streamline is being added at all? The latest NGX supports DLSS5NR, which is what the repo uses, I find it unnecessary for Streamline to be added when NGX suits the needs.

May I ask why Streamline is being added at all? The latest NGX supports DLSS5NR, which is what the repo uses, I find it unnecessary for Streamline to be added when NGX suits the needs.
notquiteog commented 2026-11-09 22:34:08 +00:00 (Migrated from github.com)

Two things for the split, so it doesn't overlap work that's already open or merged:

Ok, I'm looking at your branch and I'll adjust my PR around it, I have a bunch of uncommitted work to bring NR to AMD

> Two things for the split, so it doesn't overlap work that's already open or merged: > > * **FSR 4.1 is already [AMD FSR 4.1 (collaboration branch) #1008](https://git.magicbean.dev/MagicBeanDev/Hookshot/pulls/1008)** (mine). I'm updating it to run on [NVIDIA DLSS, DLAA and Reflex (NGX + Vulkan, Linux and Windows, opt-in) #841](https://git.magicbean.dev/MagicBeanDev/Hookshot/pulls/841)'s inputs: the colour, depth, camera jitter and motion vectors, including the characters' own. They move into a shared `vk_temporal.cpp` with a small engine interface, so DLSS and FSR 4.1 are two engines on one input path. Tested on an RX 6700 XT (FSR 4.1.2), and it also runs on Linux. A separate FSR 4.1 PR from this one would duplicate it. Happy to compare notes if yours does something [AMD FSR 4.1 (collaboration branch) #1008](https://git.magicbean.dev/MagicBeanDev/Hookshot/pulls/1008) doesn't. > * **For the FSR 3.1 PR**: [NVIDIA DLSS, DLAA and Reflex (NGX + Vulkan, Linux and Windows, opt-in) #841](https://git.magicbean.dev/MagicBeanDev/Hookshot/pulls/841) already puts a camera jitter into the game (`nx2/oot_jitter.py`) and builds motion vectors with actor motion. This branch adds a second camera hook (`nx2/oot_camera.py`) and a second motion pass (`vk_camera_motion.cpp`). Taking [NVIDIA DLSS, DLAA and Reflex (NGX + Vulkan, Linux and Windows, opt-in) #841](https://git.magicbean.dev/MagicBeanDev/Hookshot/pulls/841)'s inputs instead keeps one jitter in the game and gives FSR 3.1 the characters' motion too. Once [AMD FSR 4.1 (collaboration branch) #1008](https://git.magicbean.dev/MagicBeanDev/Hookshot/pulls/1008)'s update is up, FSR 3.1 could plug in there as one more engine. Ok, I'm looking at your branch and I'll adjust my PR around it, I have a bunch of uncommitted work to bring NR to AMD
notquiteog commented 2026-11-09 22:38:36 +00:00 (Migrated from github.com)

May I ask why Streamline is being added at all? The latest NGX supports DLSS5NR, which is what the repo uses, I find it unnecessary for Streamline to be added when NGX suits the needs.

NGX is not open source, Streamline allows users to replace the DLL's themselves easily as well

> May I ask why Streamline is being added at all? The latest NGX supports DLSS5NR, which is what the repo uses, I find it unnecessary for Streamline to be added when NGX suits the needs. NGX is not open source, Streamline allows users to replace the DLL's themselves easily as well
hckrman101 commented 2026-11-09 23:22:35 +00:00 (Migrated from github.com)

We can support NR with NGX, which is cross-platform. Let's do that

None of DLSS is open-source, so it's moot

We can support NR with NGX, which is cross-platform. Let's do that None of DLSS is open-source, so it's moot
hckrman101 (Migrated from github.com) reviewed 2026-11-09 23:27:46 +00:00
hckrman101 (Migrated from github.com) left a comment

Thanks for this. There's real work in here, especially the FSR 3.1 frame interpolation, which no other PR has. I read the hand-written integration against current main and skipped the vendored SDK sources. Provenance and licence notes for third_party/ffx-api and third_party/fidelityfx-sdk look fine: MIT, pinned commits, unmodified.

I agree with the split NotRexed asked for. Below is what I found, so each piece can land cleanly.

Bugs in the FSR 3.1 upscaler (gpu/vk/vk_fsr3.cpp, vk_draw.cpp seam)

  • Resize leaves the new images uninitialised. prepare() remakes every internal image when the render or output size changes, but first_evaluation is only reset by shutdown(). On the next upscale(), first is false, so the new images never get their UNDEFINED→GENERAL barrier or their clear. lut_uploaded also stays true, so the new lanczos_lut is never filled. After any size change (window resize, Render resolution, a dynamic-resolution change) the passes run on undefined layouts and an empty Lanczos LUT.
  • Resize frees images the GPU may still be using. make_image() → drop_image() destroys the old images straight away, with no idle and no deferred free, while earlier command buffers can still reference them. vk_dlssnr.cpp already does this correctly with device_wait_idle_locked() under present_mu. vk_ffx.cpp's idle() uses a bare vkDeviceWaitIdle from the replay thread. That breaks the external-sync rule your own comment in vk_dlssnr.cpp describes, because the present queue can be submitting at the same moment.
  • The blit isn't synchronised with the output write. The last barrier in fsr3::upscale() has dst FRAGMENT|COMPUTE / SHADER_READ, but the seam then reads fsr3::output_image() with vkCmdBlitImage, which is TRANSFER / TRANSFER_READ. The blit isn't ordered after the RCAS/accumulate write. Nothing orders the blit's write to the game's target before the game's next reader either. Separately, B10G11R11 isn't guaranteed BLIT_DST, so the format feature should be checked once.
  • Colour space. The network's input is the square root of the tonemapped colour, and main's DLSS path (#841, dlss_out.comp) squares the result back to linear before writing the network's output. This PR gives FSR 3.1 and FSR 4 dw().imgs[0] / dw().srcs[0] directly and blits the result into the target without squaring. If I'm reading main right, the FSR picture comes out in the wrong transfer function. It also says FFX_UPSCALE_ENABLE_HIGH_DYNAMIC_RANGE for an input that isn't linear HDR.

Duplicate inputs. nx2/oot_camera.py plus vk_camera_motion.cpp add a second camera hook and a camera-only motion pass, but main already has #841's jitter (nx2/oot_jitter.py) and motion vectors with the skinned actors' own motion. oot_camera.py also changes the lifted C for everyone, at four projection sites every frame. #1008's vk_temporal.cpp moves #841's chain behind an engine interface. FSR 3.1 should plug in there as one more engine, so there's one jitter in the game and FSR gets actor motion too.

Upscaler values clash with #1008. Both PRs extend the saved dlss key past DLAA with different meanings: here 3 = FSR 3.1 and 4 = FSR 4, in #1008 3 = FSR 4 and 4 = FSR 4 Native AA. Whichever lands second has to renumber. I'd suggest keeping #1008's 3/4 and adding FSR 3.1 as 5, so nobody's saved ini changes meaning between releases.

Teardown. None of the new shutdown() functions (ffx, fsr3, fsr3fi, dlssnr, dlssnr_ngx, streamline, dlssg, camera_motion) is called anywhere. That avoids the exit-time ffxDestroyContext-from-a-static crash we found in #1008, but only because nothing is ever destroyed. If teardown gets wired up later, it needs to run before the device goes and never from a static destructor.

DLSS 5 NR. This isn't ray reconstruction. It's NVIDIA's "neural rendering" uplift, run over the finished frame before the HUD. It worries me most for main:

  • The Streamline path's DlssNrOptions (GUID, struct version, layout) is reverse-engineered from a prerelease DLL, because the real header is only in NVIDIA's NDA SDK. The NGX-direct path uses NVSDK_NGX_Feature_Reserved18 with guessed parameter names.
  • readme and explain_refusal tell RTX 20–40 users to use a patched nvngx_dlssnr.dll and set HKLM\...\NGXCore\EnableSignatureOverride=1. That turns off NGX signature checking for every game on the PC. I don't think upstream should document or support that.
  • Per the thread, NR should go through NGX, cross-platform. Brett-D's path uses NVIDIA's own NR headers and needs neither Streamline nor the reconstructed struct, which looks like the better base.

Release and CI. These need to come out of the feature PRs:

  • --accept-nvidia-license in both workflows, and the prebuilt hookshot_vk.dll shipped in the Windows package with NGX statically linked. That changes main's "each player accepts NVIDIA's licence in the Builder" model, and it's the maintainer's call.
  • Repository.cs, the HOOKSHOT_REPOSITORY plumbing in setup.c, hos_update.c, linux_update.py and version.py, .releaserc.json (feat → patch), changelog.txt and the fork's version bumps. That's fork release machinery.
  • prebuilt_renderer() in make_game.py: the Builder stops compiling the renderer on the player's PC.

Unrelated behaviour changes that should be their own PRs:

  • nn_vi.c: the vsync event now follows the display's refresh rate by default instead of 60. That changes pacing for everyone on a high-refresh monitor, with no opt-in.
  • HOS_DISPLAY_VRR, HOS_FPS_FORCE and the 120 Hz HLE.
  • The ParLock per-site counters, plus the always-on atomic counters in texture_touch_quick and gpu_buffer_bind, which sit on hot paths.

Linux. FSR 4 (vk_ffx) and Streamline are Windows-only stubs, and FSR 3.1 is the only new path that compiles on Linux. CI never ran on this PR (head is the fork's main, and there are no checks), so there's no evidence either way that the Linux build or tests/run_all.py pass. It also conflicts with main (39 commits behind).

On #1008 vs this: I'd take #1008's architecture as the base for main: the TemporalEngine on #841's inputs, the right colour handling, and it runs on Linux. That makes #1008 the FSR 4 path, so vk_ffx.cpp here would duplicate it. From this PR, the unique and valuable parts are the FSR 3.1 upscaler, as an engine on vk_temporal (with the fixes above), and FSR 3.1 frame interpolation (vk_fsr3fi.cpp) plus the Frame generation method row. Those are a great first split PR. NR should come separately over NGX.

Thanks for this. There's real work in here, especially the FSR 3.1 frame interpolation, which no other PR has. I read the hand-written integration against current main and skipped the vendored SDK sources. Provenance and licence notes for `third_party/ffx-api` and `third_party/fidelityfx-sdk` look fine: MIT, pinned commits, unmodified. I agree with the split NotRexed asked for. Below is what I found, so each piece can land cleanly. **Bugs in the FSR 3.1 upscaler (`gpu/vk/vk_fsr3.cpp`, `vk_draw.cpp` seam)** - **Resize leaves the new images uninitialised.** `prepare()` remakes every internal image when the render or output size changes, but `first_evaluation` is only reset by `shutdown()`. On the next `upscale()`, `first` is false, so the new images never get their UNDEFINED→GENERAL barrier or their clear. `lut_uploaded` also stays true, so the new `lanczos_lut` is never filled. After any size change (window resize, Render resolution, a dynamic-resolution change) the passes run on undefined layouts and an empty Lanczos LUT. - **Resize frees images the GPU may still be using.** `make_image()` → `drop_image()` destroys the old images straight away, with no idle and no deferred free, while earlier command buffers can still reference them. `vk_dlssnr.cpp` already does this correctly with `device_wait_idle_locked()` under `present_mu`. `vk_ffx.cpp`'s `idle()` uses a bare `vkDeviceWaitIdle` from the replay thread. That breaks the external-sync rule your own comment in `vk_dlssnr.cpp` describes, because the present queue can be submitting at the same moment. - **The blit isn't synchronised with the output write.** The last barrier in `fsr3::upscale()` has dst `FRAGMENT|COMPUTE / SHADER_READ`, but the seam then reads `fsr3::output_image()` with `vkCmdBlitImage`, which is `TRANSFER / TRANSFER_READ`. The blit isn't ordered after the RCAS/accumulate write. Nothing orders the blit's write to the game's target before the game's next reader either. Separately, B10G11R11 isn't guaranteed `BLIT_DST`, so the format feature should be checked once. - **Colour space.** The network's input is the square root of the tonemapped colour, and main's DLSS path (#841, `dlss_out.comp`) squares the result back to linear before writing the network's output. This PR gives FSR 3.1 and FSR 4 `dw().imgs[0]` / `dw().srcs[0]` directly and blits the result into the target without squaring. If I'm reading main right, the FSR picture comes out in the wrong transfer function. It also says `FFX_UPSCALE_ENABLE_HIGH_DYNAMIC_RANGE` for an input that isn't linear HDR. **Duplicate inputs.** `nx2/oot_camera.py` plus `vk_camera_motion.cpp` add a second camera hook and a camera-only motion pass, but main already has #841's jitter (`nx2/oot_jitter.py`) and motion vectors with the skinned actors' own motion. `oot_camera.py` also changes the lifted C for everyone, at four projection sites every frame. #1008's `vk_temporal.cpp` moves #841's chain behind an engine interface. FSR 3.1 should plug in there as one more engine, so there's one jitter in the game and FSR gets actor motion too. **Upscaler values clash with #1008.** Both PRs extend the saved `dlss` key past DLAA with different meanings: here 3 = FSR 3.1 and 4 = FSR 4, in #1008 3 = FSR 4 and 4 = FSR 4 Native AA. Whichever lands second has to renumber. I'd suggest keeping #1008's 3/4 and adding FSR 3.1 as 5, so nobody's saved ini changes meaning between releases. **Teardown.** None of the new `shutdown()` functions (`ffx`, `fsr3`, `fsr3fi`, `dlssnr`, `dlssnr_ngx`, `streamline`, `dlssg`, `camera_motion`) is called anywhere. That avoids the exit-time `ffxDestroyContext`-from-a-static crash we found in #1008, but only because nothing is ever destroyed. If teardown gets wired up later, it needs to run before the device goes and never from a static destructor. **DLSS 5 NR.** This isn't ray reconstruction. It's NVIDIA's "neural rendering" uplift, run over the finished frame before the HUD. It worries me most for main: - The Streamline path's `DlssNrOptions` (GUID, struct version, layout) is reverse-engineered from a prerelease DLL, because the real header is only in NVIDIA's NDA SDK. The NGX-direct path uses `NVSDK_NGX_Feature_Reserved18` with guessed parameter names. - readme and `explain_refusal` tell RTX 20–40 users to use a patched `nvngx_dlssnr.dll` and set `HKLM\...\NGXCore\EnableSignatureOverride=1`. That turns off NGX signature checking for every game on the PC. I don't think upstream should document or support that. - Per the thread, NR should go through NGX, cross-platform. Brett-D's path uses NVIDIA's own NR headers and needs neither Streamline nor the reconstructed struct, which looks like the better base. **Release and CI.** These need to come out of the feature PRs: - `--accept-nvidia-license` in both workflows, and the prebuilt `hookshot_vk.dll` shipped in the Windows package with NGX statically linked. That changes main's "each player accepts NVIDIA's licence in the Builder" model, and it's the maintainer's call. - `Repository.cs`, the `HOOKSHOT_REPOSITORY` plumbing in `setup.c`, `hos_update.c`, `linux_update.py` and `version.py`, `.releaserc.json` (`feat` → patch), `changelog.txt` and the fork's version bumps. That's fork release machinery. - `prebuilt_renderer()` in `make_game.py`: the Builder stops compiling the renderer on the player's PC. **Unrelated behaviour changes that should be their own PRs:** - `nn_vi.c`: the vsync event now follows the display's refresh rate by default instead of 60. That changes pacing for everyone on a high-refresh monitor, with no opt-in. - `HOS_DISPLAY_VRR`, `HOS_FPS_FORCE` and the 120 Hz HLE. - The ParLock per-site counters, plus the always-on atomic counters in `texture_touch_quick` and `gpu_buffer_bind`, which sit on hot paths. **Linux.** FSR 4 (`vk_ffx`) and Streamline are Windows-only stubs, and FSR 3.1 is the only new path that compiles on Linux. CI never ran on this PR (head is the fork's `main`, and there are no checks), so there's no evidence either way that the Linux build or `tests/run_all.py` pass. It also conflicts with main (39 commits behind). **On #1008 vs this:** I'd take #1008's architecture as the base for main: the TemporalEngine on #841's inputs, the right colour handling, and it runs on Linux. That makes #1008 the FSR 4 path, so `vk_ffx.cpp` here would duplicate it. From this PR, the unique and valuable parts are the FSR 3.1 upscaler, as an engine on `vk_temporal` (with the fixes above), and FSR 3.1 frame interpolation (`vk_fsr3fi.cpp`) plus the Frame generation method row. Those are a great first split PR. NR should come separately over NGX.
@ -160,3 +81,4 @@
--skip-tag "$SKIP_TAG" ||
{ echo "no release with a setup list: built without the profile"; exit 0; }
python3 -I scripts/release_parts.py profile /tmp/setup.txt work ||
{ echo "the profile did not download: built without it"; exit 0; }
hckrman101 (Migrated from github.com) commented 2026-11-09 23:27:46 +00:00

Same here for the AppImage: --accept-nvidia-license in CI makes every release accept NVIDIA's licence. Please drop it from the feature split.

Same here for the AppImage: `--accept-nvidia-license` in CI makes every release accept NVIDIA's licence. Please drop it from the feature split.
@ -366,4 +258,3 @@
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ inputs.tag }}
persist-credentials: false
hckrman101 (Migrated from github.com) commented 2026-11-09 23:27:46 +00:00

This accepts NVIDIA's DLSS licence on every release build and links NGX into the shipped hookshot_vk.dll. Main's model is that each player accepts it in the Builder, and changing that is the maintainer's call, so please leave it out of the feature PRs.

This accepts NVIDIA's DLSS licence on every release build and links NGX into the shipped `hookshot_vk.dll`. Main's model is that each player accepts it in the Builder, and changing that is the maintainer's call, so please leave it out of the feature PRs.
notquiteog commented 2026-11-10 01:32:18 +00:00 (Migrated from github.com)

Thanks for this. There's real work in here, especially the FSR 3.1 frame interpolation, which no other PR has. I read the hand-written integration against current main and skipped the vendored SDK sources. Provenance and licence notes for third_party/ffx-api and third_party/fidelityfx-sdk look fine: MIT, pinned commits, unmodified.

I agree with the split NotRexed asked for. Below is what I found, so each piece can land cleanly.

Bugs in the FSR 3.1 upscaler (gpu/vk/vk_fsr3.cpp, vk_draw.cpp seam)

  • Resize leaves the new images uninitialised. prepare() remakes every internal image when the render or output size changes, but first_evaluation is only reset by shutdown(). On the next upscale(), first is false, so the new images never get their UNDEFINED→GENERAL barrier or their clear. lut_uploaded also stays true, so the new lanczos_lut is never filled. After any size change (window resize, Render resolution, a dynamic-resolution change) the passes run on undefined layouts and an empty Lanczos LUT.
  • Resize frees images the GPU may still be using. make_image() → drop_image() destroys the old images straight away, with no idle and no deferred free, while earlier command buffers can still reference them. vk_dlssnr.cpp already does this correctly with device_wait_idle_locked() under present_mu. vk_ffx.cpp's idle() uses a bare vkDeviceWaitIdle from the replay thread. That breaks the external-sync rule your own comment in vk_dlssnr.cpp describes, because the present queue can be submitting at the same moment.
  • The blit isn't synchronised with the output write. The last barrier in fsr3::upscale() has dst FRAGMENT|COMPUTE / SHADER_READ, but the seam then reads fsr3::output_image() with vkCmdBlitImage, which is TRANSFER / TRANSFER_READ. The blit isn't ordered after the RCAS/accumulate write. Nothing orders the blit's write to the game's target before the game's next reader either. Separately, B10G11R11 isn't guaranteed BLIT_DST, so the format feature should be checked once.
  • Colour space. The network's input is the square root of the tonemapped colour, and main's DLSS path (#841, dlss_out.comp) squares the result back to linear before writing the network's output. This PR gives FSR 3.1 and FSR 4 dw().imgs[0] / dw().srcs[0] directly and blits the result into the target without squaring. If I'm reading main right, the FSR picture comes out in the wrong transfer function. It also says FFX_UPSCALE_ENABLE_HIGH_DYNAMIC_RANGE for an input that isn't linear HDR.

Duplicate inputs. nx2/oot_camera.py plus vk_camera_motion.cpp add a second camera hook and a camera-only motion pass, but main already has #841's jitter (nx2/oot_jitter.py) and motion vectors with the skinned actors' own motion. oot_camera.py also changes the lifted C for everyone, at four projection sites every frame. #1008's vk_temporal.cpp moves #841's chain behind an engine interface. FSR 3.1 should plug in there as one more engine, so there's one jitter in the game and FSR gets actor motion too.

Upscaler values clash with #1008. Both PRs extend the saved dlss key past DLAA with different meanings: here 3 = FSR 3.1 and 4 = FSR 4, in #1008 3 = FSR 4 and 4 = FSR 4 Native AA. Whichever lands second has to renumber. I'd suggest keeping #1008's 3/4 and adding FSR 3.1 as 5, so nobody's saved ini changes meaning between releases.

Teardown. None of the new shutdown() functions (ffx, fsr3, fsr3fi, dlssnr, dlssnr_ngx, streamline, dlssg, camera_motion) is called anywhere. That avoids the exit-time ffxDestroyContext-from-a-static crash we found in #1008, but only because nothing is ever destroyed. If teardown gets wired up later, it needs to run before the device goes and never from a static destructor.

DLSS 5 NR. This isn't ray reconstruction. It's NVIDIA's "neural rendering" uplift, run over the finished frame before the HUD. It worries me most for main:

  • The Streamline path's DlssNrOptions (GUID, struct version, layout) is reverse-engineered from a prerelease DLL, because the real header is only in NVIDIA's NDA SDK. The NGX-direct path uses NVSDK_NGX_Feature_Reserved18 with guessed parameter names.
  • readme and explain_refusal tell RTX 20–40 users to use a patched nvngx_dlssnr.dll and set HKLM\...\NGXCore\EnableSignatureOverride=1. That turns off NGX signature checking for every game on the PC. I don't think upstream should document or support that.
  • Per the thread, NR should go through NGX, cross-platform. Brett-D's path uses NVIDIA's own NR headers and needs neither Streamline nor the reconstructed struct, which looks like the better base.

Release and CI. These need to come out of the feature PRs:

  • --accept-nvidia-license in both workflows, and the prebuilt hookshot_vk.dll shipped in the Windows package with NGX statically linked. That changes main's "each player accepts NVIDIA's licence in the Builder" model, and it's the maintainer's call.
  • Repository.cs, the HOOKSHOT_REPOSITORY plumbing in setup.c, hos_update.c, linux_update.py and version.py, .releaserc.json (feat → patch), changelog.txt and the fork's version bumps. That's fork release machinery.
  • prebuilt_renderer() in make_game.py: the Builder stops compiling the renderer on the player's PC.

Unrelated behaviour changes that should be their own PRs:

  • nn_vi.c: the vsync event now follows the display's refresh rate by default instead of 60. That changes pacing for everyone on a high-refresh monitor, with no opt-in.
  • HOS_DISPLAY_VRR, HOS_FPS_FORCE and the 120 Hz HLE.
  • The ParLock per-site counters, plus the always-on atomic counters in texture_touch_quick and gpu_buffer_bind, which sit on hot paths.

Linux. FSR 4 (vk_ffx) and Streamline are Windows-only stubs, and FSR 3.1 is the only new path that compiles on Linux. CI never ran on this PR (head is the fork's main, and there are no checks), so there's no evidence either way that the Linux build or tests/run_all.py pass. It also conflicts with main (39 commits behind).

On #1008 vs this: I'd take #1008's architecture as the base for main: the TemporalEngine on #841's inputs, the right colour handling, and it runs on Linux. That makes #1008 the FSR 4 path, so vk_ffx.cpp here would duplicate it. From this PR, the unique and valuable parts are the FSR 3.1 upscaler, as an engine on vk_temporal (with the fixes above), and FSR 3.1 frame interpolation (vk_fsr3fi.cpp) plus the Frame generation method row. Those are a great first split PR. NR should come separately over NGX.

Can you recheck the recent NR/upscale/frame-gen work on my fork? It should be a complete implementation on AMD and NVIDIA

> Thanks for this. There's real work in here, especially the FSR 3.1 frame interpolation, which no other PR has. I read the hand-written integration against current main and skipped the vendored SDK sources. Provenance and licence notes for `third_party/ffx-api` and `third_party/fidelityfx-sdk` look fine: MIT, pinned commits, unmodified. > > I agree with the split NotRexed asked for. Below is what I found, so each piece can land cleanly. > > **Bugs in the FSR 3.1 upscaler (`gpu/vk/vk_fsr3.cpp`, `vk_draw.cpp` seam)** > > * **Resize leaves the new images uninitialised.** `prepare()` remakes every internal image when the render or output size changes, but `first_evaluation` is only reset by `shutdown()`. On the next `upscale()`, `first` is false, so the new images never get their UNDEFINED→GENERAL barrier or their clear. `lut_uploaded` also stays true, so the new `lanczos_lut` is never filled. After any size change (window resize, Render resolution, a dynamic-resolution change) the passes run on undefined layouts and an empty Lanczos LUT. > * **Resize frees images the GPU may still be using.** `make_image()` → `drop_image()` destroys the old images straight away, with no idle and no deferred free, while earlier command buffers can still reference them. `vk_dlssnr.cpp` already does this correctly with `device_wait_idle_locked()` under `present_mu`. `vk_ffx.cpp`'s `idle()` uses a bare `vkDeviceWaitIdle` from the replay thread. That breaks the external-sync rule your own comment in `vk_dlssnr.cpp` describes, because the present queue can be submitting at the same moment. > * **The blit isn't synchronised with the output write.** The last barrier in `fsr3::upscale()` has dst `FRAGMENT|COMPUTE / SHADER_READ`, but the seam then reads `fsr3::output_image()` with `vkCmdBlitImage`, which is `TRANSFER / TRANSFER_READ`. The blit isn't ordered after the RCAS/accumulate write. Nothing orders the blit's write to the game's target before the game's next reader either. Separately, B10G11R11 isn't guaranteed `BLIT_DST`, so the format feature should be checked once. > * **Colour space.** The network's input is the square root of the tonemapped colour, and main's DLSS path (#841, `dlss_out.comp`) squares the result back to linear before writing the network's output. This PR gives FSR 3.1 and FSR 4 `dw().imgs[0]` / `dw().srcs[0]` directly and blits the result into the target without squaring. If I'm reading main right, the FSR picture comes out in the wrong transfer function. It also says `FFX_UPSCALE_ENABLE_HIGH_DYNAMIC_RANGE` for an input that isn't linear HDR. > > **Duplicate inputs.** `nx2/oot_camera.py` plus `vk_camera_motion.cpp` add a second camera hook and a camera-only motion pass, but main already has #841's jitter (`nx2/oot_jitter.py`) and motion vectors with the skinned actors' own motion. `oot_camera.py` also changes the lifted C for everyone, at four projection sites every frame. #1008's `vk_temporal.cpp` moves #841's chain behind an engine interface. FSR 3.1 should plug in there as one more engine, so there's one jitter in the game and FSR gets actor motion too. > > **Upscaler values clash with #1008.** Both PRs extend the saved `dlss` key past DLAA with different meanings: here 3 = FSR 3.1 and 4 = FSR 4, in #1008 3 = FSR 4 and 4 = FSR 4 Native AA. Whichever lands second has to renumber. I'd suggest keeping #1008's 3/4 and adding FSR 3.1 as 5, so nobody's saved ini changes meaning between releases. > > **Teardown.** None of the new `shutdown()` functions (`ffx`, `fsr3`, `fsr3fi`, `dlssnr`, `dlssnr_ngx`, `streamline`, `dlssg`, `camera_motion`) is called anywhere. That avoids the exit-time `ffxDestroyContext`-from-a-static crash we found in #1008, but only because nothing is ever destroyed. If teardown gets wired up later, it needs to run before the device goes and never from a static destructor. > > **DLSS 5 NR.** This isn't ray reconstruction. It's NVIDIA's "neural rendering" uplift, run over the finished frame before the HUD. It worries me most for main: > > * The Streamline path's `DlssNrOptions` (GUID, struct version, layout) is reverse-engineered from a prerelease DLL, because the real header is only in NVIDIA's NDA SDK. The NGX-direct path uses `NVSDK_NGX_Feature_Reserved18` with guessed parameter names. > * readme and `explain_refusal` tell RTX 20–40 users to use a patched `nvngx_dlssnr.dll` and set `HKLM\...\NGXCore\EnableSignatureOverride=1`. That turns off NGX signature checking for every game on the PC. I don't think upstream should document or support that. > * Per the thread, NR should go through NGX, cross-platform. Brett-D's path uses NVIDIA's own NR headers and needs neither Streamline nor the reconstructed struct, which looks like the better base. > > **Release and CI.** These need to come out of the feature PRs: > > * `--accept-nvidia-license` in both workflows, and the prebuilt `hookshot_vk.dll` shipped in the Windows package with NGX statically linked. That changes main's "each player accepts NVIDIA's licence in the Builder" model, and it's the maintainer's call. > * `Repository.cs`, the `HOOKSHOT_REPOSITORY` plumbing in `setup.c`, `hos_update.c`, `linux_update.py` and `version.py`, `.releaserc.json` (`feat` → patch), `changelog.txt` and the fork's version bumps. That's fork release machinery. > * `prebuilt_renderer()` in `make_game.py`: the Builder stops compiling the renderer on the player's PC. > > **Unrelated behaviour changes that should be their own PRs:** > > * `nn_vi.c`: the vsync event now follows the display's refresh rate by default instead of 60. That changes pacing for everyone on a high-refresh monitor, with no opt-in. > * `HOS_DISPLAY_VRR`, `HOS_FPS_FORCE` and the 120 Hz HLE. > * The ParLock per-site counters, plus the always-on atomic counters in `texture_touch_quick` and `gpu_buffer_bind`, which sit on hot paths. > > **Linux.** FSR 4 (`vk_ffx`) and Streamline are Windows-only stubs, and FSR 3.1 is the only new path that compiles on Linux. CI never ran on this PR (head is the fork's `main`, and there are no checks), so there's no evidence either way that the Linux build or `tests/run_all.py` pass. It also conflicts with main (39 commits behind). > > **On #1008 vs this:** I'd take #1008's architecture as the base for main: the TemporalEngine on #841's inputs, the right colour handling, and it runs on Linux. That makes #1008 the FSR 4 path, so `vk_ffx.cpp` here would duplicate it. From this PR, the unique and valuable parts are the FSR 3.1 upscaler, as an engine on `vk_temporal` (with the fixes above), and FSR 3.1 frame interpolation (`vk_fsr3fi.cpp`) plus the Frame generation method row. Those are a great first split PR. NR should come separately over NGX. Can you recheck the recent NR/upscale/frame-gen work on my fork? It should be a complete implementation on AMD and NVIDIA
NotRexed commented 2026-11-10 02:07:49 +00:00 (Migrated from github.com)

Thanks for splitting this up. FSR 3.1 upscaling and frame generation are now reviewed in #1386, and FSR 4.1 is in #1008, so closing this combined PR. For DLSS NR, please open it as its own PR; review asked for it through NGX rather than Streamline.

Thanks for splitting this up. FSR 3.1 upscaling and frame generation are now reviewed in #1386, and FSR 4.1 is in #1008, so closing this combined PR. For DLSS NR, please open it as its own PR; review asked for it through NGX rather than Streamline.
Commenting is not possible because the repository is archived.
No description provided.