Repository navigation
fix(vk): DLSS comes back after a feature that was not made, and frame generation takes the multiplier its sets were made for - #2658
Conversation
… generation takes the multiplier its sets were made for - vk_framegen.cpp: framegen_record took the multiplier from the row again after ensure_size had made the sets; a step up in the menu (the display thread) in between copied the game's frame into an image that was never made. It takes fg.mult. - vk_dlss.cpp: a feature that was not made (NotRexed#2550) was asked for again only when the output, preset or HDR changed. The quality mode is in the key, release() clears it, and temporal_reset_failure clears it (dlss_retry). - vk_dlss.cpp: with retry (NotRexed#2574) a failing evaluation logged on every frame for good. Its line is spaced as the chain's reason is, and after 30 in a row the feature is made again once. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
|
A Windows test of the frame-generation race in the first part of this PR. Current
The three
With this PR, no crash: three rounds of 2x → 3x → 4x and back in the menu, in a window: 11 swapchain remakes (4, 5 and 6 images), the game ran on and exited normally. This PR also held up for the second case. At 4x before play, the game went from fullscreen to a window and back 25 times each ( These are small counts: one crash per case on Not tested: Linux, AMD and Intel; the DLSS retry part of this PR (no failed feature creation here). 🤖 Generated with Claude Code |
|
The race in the first part happens in the game: a crash on Windows when stepping the multiplier up, at the copy this PR fixes.
With the build's So it isn't only a window seen in reading: one step up was enough here. 🤖 Generated with Claude Code |
Joey-Magnus
left a comment
There was a problem hiding this comment.
I merged this into current main and ran the DLSS/framegen/present/temporal/HDR checks (run_all.py dlss framegen present temporal hdr upscale: 26 passed, 4 skipped for Vulkan headers). The test_hdr_encode failure on this head was main's own (kEngine's retry, fixed by #2648), so a re-run should clear it.
The framegen fix is right and matters. ensure_size builds the sets for fg.mult, and framegen_record re-read multiplier() afterwards, so a menu step on the display thread in between made the last vkCmdCopyImage target a frame that was never created. Taking fg.mult at gpu/vk/vk_framegen.cpp:791 closes that. Jiro131 and polackangry both reproduced the nvoglv64.dll read at 0x590 in framegen_record on main, and neither saw it with this change.
On DLSS: adding the quality mode to the refused key, clearing refused in release() (vk_dlss.cpp:481) and calling dlss_retry from temporal_reset_failure look correct. The key's mode bits (8-10) don't overlap the preset bits. Note that the release after 30 failed evaluations (:469) fires only once per run of the same error code, which I think is what you want. I found no open PR touching these same lines (#2788 and #2665 change other parts of these files).
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…e generation Port three upstream NVIDIA fixes that the fork did not have: - 1bf4284 (NotRexed#2658): the quality mode joins the DLSS refusal key, release() and the menu's scaling rows clear a refused feature, a failing evaluation is logged when its result changes and every 600th time and remakes the feature after 30 failures in a row, and frame generation reads the multiplier its sets were made for instead of the menu again. - 6cdee4c: a fixed frame-generation multiplier makes no more frames than the display can show (RX_VK_FRAMEGEN_UNCAPPED=1 keeps the old count), and the display thread leaves a made frame out when the game's next frame is already waiting. - f3dd448 (NotRexed#2145): switching from scaled DLSS to DLAA waits up to three scene frames for the native scene, then uses native AA at the size the scene keeps; the engine's native-AA intent is part of feature reuse. builder/rust/tests/nvidia_parity.rs checks all three game-free, with compiled fixtures for fixed_frames and the DLAA transition/reuse, and pins the already-ported Reflex submit IDs, V-Sync Auto and both NGX runtimes. No NVIDIA hardware was available here.
After one failed DLSS feature creation, DLSS stays off until the player changes the DLSS model or the output size; and stepping the Frame generation multiplier up in the menu can make a frame be copied into an image that does not exist. Both are in code that #2550 and #2574 touched, found by reading the merged result.
What changed
Frame generation: the multiplier is read once (
vk_framegen.cpp).framegen_recordcalledmultiplier()again afterensure_sizehad made the sets forfg.mult. The menu runs on the display thread (menu_tickfrompresent_image), the record on the replay thread, with a wait for a free set in between. A step from 2x to 3x in that window givesm = fg.mult + 1, and the lastvkCmdCopyImagetargetsset->frame[fg.mult], a null image, which the display thread then presents. It takesfg.multnow, and reads the Auto test once for the same reason.DLSS:
refusedis cleared where a retry should happen (vk_dlss.cpp). Since #2550 a creation that fails returns 0 withs.refused = key, and the key is the output size, preset and HDR. The old feature is already let go, so from then on:release()leftrefusedset).#2574's
temporal_reset_failuredoes not help there: the chain'sfailedflag is not what holds DLSS off. Now the quality mode is part of the key,release()clearsrefused, andtemporal_reset_failureclears it too (dlss_retry, called with the chain's lock held, aspreparehas it).DLSS: a failing evaluation no longer logs on every frame (
vk_dlss.cpp). Withretry = true(#2574) an evaluation that fails every frame wroteits evaluation failed60 times a second for the rest of the run. The line is spaced like the chain's own reason (when the result changes, and every 600th time), and after 30 failures in a row the feature is let go once sopreparemakes a new one.How it was tested
tests/run_all.py: with fix: main's source checks pass again (15 red since #2574, #2617 and others), and the three bugs behind them #2656 (which makes main's checks pass) and this together, 468 passed, 0 failed, 22 skipped. On this branch alone the 15 checks that are red on main stay red and nothing else fails.test_present_source_crop's fixture setsfg.multin itsensure_sizestand-in, as the real one does.feature 4 made (again after it was let go ...).Not tested
Review notes that are not fixed here, for whoever owns them: FSR 4's engine still has the permanent latch #2574 removed for DLSS (
vk_fsr4.cpppreparereturns -1, noretry); with Native HDR, frame generation's images are RGBA8 (vk_framegen.cppensure_size), so the game's 10-bit PQ picture passes through 8 bits; DLSS-G's feature keeps the render size it was created with when the Render resolution changes.🤖 Generated with Claude Code