fix(vk): a DLSS feature that fails to be made is made again at the next DLSS change, not never #2550

Merged
SirenityK merged 3 commits from fix/dlss-recover-failed-feature into main 2026-11-12 03:05:25 +00:00
SirenityK commented 2026-11-11 22:58:22 +00:00 (Migrated from github.com)

Switching the DLSS model quickly in the menu can turn DLSS off for the rest of the run: the picture falls back to the game's own upscale (sharp, aliased hair and edges), going back to the first model does nothing, and only a restart brings DLSS back, with no message saying so.

Why it happens

Each DLSS model change makes a new NGX feature; the one it replaces is let go 4 frames later (temporal_later). Switching faster than that keeps several alive at once: DLSS's own memory went from 143 MB to 1173 MB and VRAM to 7.6 of 6.8 GB, and NGX then refused the next one:

vk: NVIDIA DLSS: feature 19 made (preset L, was M (the DLSS model row); frame 129670, 3.7 ms of CPU): ... preset L
vk: NVIDIA DLSS: its feature was not made (0xbad00002) for 2560x1440 -> 2560x1440
vk: NVIDIA DLSS: the game's upscale runs (its feature was not made)
vk: NVIDIA DLSS: the game's upscale runs (it failed earlier)
vk: NVIDIA DLSS: the game's upscale runs (it failed earlier)

(0xbad00002 is NVSDK_NGX_Result_FAIL_PlatformError.) prepare returned -1 for a feature that was not made, and the chain (vk_temporal.cpp) takes -1 as a failed engine: engine.failed stays set for the run.

What changed

gpu/vk/vk_dlss.cpp prepare: a feature that is not made returns 0 (the game's upscale this frame) instead of -1, and remembers the preset, output and HDR it failed for. It is not tried again every frame (each try is a ~30 ms creation), but as soon as any of them changes, e.g. another DLSS model picked in the menu, it is made again. A success clears it.

tests/test_dlss_checks.py: checks that prepare no longer returns -1 for it and keeps the retry key.

Not in this PR: letting the replaced feature go sooner, so quick switching does not pile up video memory in the first place.

Screenshots

2560x1440, DLAA, after quick DLSS model switches. Before: the game's upscale for the rest of the run, whichever model is picked. After: DLSS back on the next model change.

Before After
Before After

Testing

RTX 3060 Ti LHR (8 GB), driver 32.0.16.1062, Windows 11, 2560x1440, DLAA, Kokiri Forest. The same change built onto v2.1.0's renderer (RX_VK_ONLY=1, the installed game's interface version), switching the DLSS model quickly in play:

vk: NVIDIA DLSS: feature 13 made (preset 0, was L (the DLSS model row); frame 16186, 29.2 ms of CPU): ...
vk: NVIDIA DLSS: its feature was not made (0xbad00002) for 2560x1440 -> 2560x1440
vk: NVIDIA DLAA: the game's upscale runs (its feature was not made)
vk: NVIDIA DLSS: feature 14 made (again after it was let go; frame 16197, 3.9 ms of CPU): ... preset M
vk: NVIDIA DLSS: feature 15 made (preset K, was M (the DLSS model row); frame 16199, 29.1 ms of CPU): ... preset K

DLSS came back on the next model change, without a restart, and kept working through feature 25. python -I -B tests/test_dlss_checks.py passes. tests/run_all.py on Windows: 387 passed, 5 failed (test_fpx_sticky, test_prepare_at_build, nx2/test_nup_paths, test_bake_portability, test_vram_budget_row), the same 5 failing on main without this change on this PC.

Switching the DLSS model quickly in the menu can turn DLSS off for the rest of the run: the picture falls back to the game's own upscale (sharp, aliased hair and edges), going back to the first model does nothing, and only a restart brings DLSS back, with no message saying so. ### Why it happens Each DLSS model change makes a new NGX feature; the one it replaces is let go 4 frames later (`temporal_later`). Switching faster than that keeps several alive at once: DLSS's own memory went from 143 MB to 1173 MB and VRAM to 7.6 of 6.8 GB, and NGX then refused the next one: ``` vk: NVIDIA DLSS: feature 19 made (preset L, was M (the DLSS model row); frame 129670, 3.7 ms of CPU): ... preset L vk: NVIDIA DLSS: its feature was not made (0xbad00002) for 2560x1440 -> 2560x1440 vk: NVIDIA DLSS: the game's upscale runs (its feature was not made) vk: NVIDIA DLSS: the game's upscale runs (it failed earlier) vk: NVIDIA DLSS: the game's upscale runs (it failed earlier) ``` (`0xbad00002` is `NVSDK_NGX_Result_FAIL_PlatformError`.) `prepare` returned -1 for a feature that was not made, and the chain (`vk_temporal.cpp`) takes -1 as a failed engine: `engine.failed` stays set for the run. ### What changed `gpu/vk/vk_dlss.cpp` `prepare`: a feature that is not made returns 0 (the game's upscale this frame) instead of -1, and remembers the preset, output and HDR it failed for. It is not tried again every frame (each try is a ~30 ms creation), but as soon as any of them changes, e.g. another DLSS model picked in the menu, it is made again. A success clears it. `tests/test_dlss_checks.py`: checks that `prepare` no longer returns -1 for it and keeps the retry key. Not in this PR: letting the replaced feature go sooner, so quick switching does not pile up video memory in the first place. ### Screenshots 2560x1440, DLAA, after quick DLSS model switches. Before: the game's upscale for the rest of the run, whichever model is picked. After: DLSS back on the next model change. | Before | After | |---|---| | ![Before](https://raw.githubusercontent.com/SirenityK/Hookshot/pr-assets/dlss-recover-before.png) | ![After](https://raw.githubusercontent.com/SirenityK/Hookshot/pr-assets/dlss-recover-after.png) | ### Testing RTX 3060 Ti LHR (8 GB), driver 32.0.16.1062, Windows 11, 2560x1440, DLAA, Kokiri Forest. The same change built onto v2.1.0's renderer (`RX_VK_ONLY=1`, the installed game's interface version), switching the DLSS model quickly in play: ``` vk: NVIDIA DLSS: feature 13 made (preset 0, was L (the DLSS model row); frame 16186, 29.2 ms of CPU): ... vk: NVIDIA DLSS: its feature was not made (0xbad00002) for 2560x1440 -> 2560x1440 vk: NVIDIA DLAA: the game's upscale runs (its feature was not made) vk: NVIDIA DLSS: feature 14 made (again after it was let go; frame 16197, 3.9 ms of CPU): ... preset M vk: NVIDIA DLSS: feature 15 made (preset K, was M (the DLSS model row); frame 16199, 29.1 ms of CPU): ... preset K ``` DLSS came back on the next model change, without a restart, and kept working through feature 25. `python -I -B tests/test_dlss_checks.py` passes. `tests/run_all.py` on Windows: 387 passed, 5 failed (`test_fpx_sticky`, `test_prepare_at_build`, `nx2/test_nup_paths`, `test_bake_portability`, `test_vram_budget_row`), the same 5 failing on `main` without this change on this PC.
Commenting is not possible because the repository is archived.
No description provided.