fix(vk): let a catch-up go on only past met waits, not every stopped queue #449
No reviewers
Labels
No labels
accessibility
autorelease: pending
autorelease: tagged
bug
dependencies
documentation
duplicate
enhancement
github_actions
good first issue
help wanted
invalid
question
testing wanted
wontfix
No milestone
No assignees
1 participant
Due date
No due date set.
Dependencies
No dependencies set
Reference
MagicBeanDev/Hookshot!449
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/catchup-stopped-queues"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What this fixes
One-frame flashes in Kokiri Forest once the game runs at speed. The scene goes black, grey or blown out for a frame, with the HUD and Navi still drawn on top. It often alternates with normal frames for several seconds. This may be what #145, #305 and #307 describe.
Why
In sync mode,
wait_queue_empty()callssync_drain(2), which forces every queue stopped at an event wait past its wait. The callers are a queue finish, an invalidate that reads back GPU-written data, and a pool's mapping changing.The work those waits are for is mostly not submitted yet, because the thread that's waiting is the one that would submit it. As a test, holding the waiter for up to 20 ms let only 32 of about 3,600 stopped queues go on by themselves. Forced past its wait, the stopped submission's lit passes read results before they're made.
A frame probe (
RX_VK_PROBE=2) of the dark frames showed:At low frame rates the other queue's work had always arrived first, so this only shows once the game runs fast. For us that was after the udmabuf change.
Change
gpu/vk/vk_replay.cpp: in sync mode, a catch-up now onlyschedule()s what can go on, meaning waits that are met. Stopped work still goes on, as before, with:sync_watch'shold_ms.RX_VK_CATCHUP_FORCE=1forces, as before.This complements #430, which does the same for releases (drain 1).
Tested
RX_VK_FRAMELOG) of 70 s of Kokiri gameplay, counting frames that differ from both neighbours but match the frame two back.finish()that needs stopped work waits on the timeline untilsync_watchmoves it, but that never showed up as lost frames.drain(0), 114-362 per run. #430's readback refresh may cover what remains.foliage-linux-updaterrelease with this patch.main: rebased onto currentmain, wherehookshot_vkbuilds. I have not run a fullmainbuild.Analysis and patch made with Claude (Anthropic); I ran every test on my machine.
🤖 Generated with Claude Code
Tested on Intel Arc B390 (Core Ultra X7 358H iGPU), Linux, Mesa 26.2.5 ANV, kernel 7.2.15, Hyprland (Wayland). This fixes the flashing here.
Setup: release
no-visual-studio(e40306e) built with the Linux AppImage. I applied this PR's diff toe40306eand rebuilt onlyhookshot_vk.so(RX_VK_ONLY=1 RX_RELEASE=1 nx2/build.py --standalone, the AppImage's clang, headers at the versionsdeps.shpins), then swapped it into the game folder. Test: Kokiri Forest save, standing still outside Link's house, 30 sRX_VK_FRAMELOG, counted withscripts/framelog.py. Default settings otherwise.e40306ereleasee40306e+ this PRhookshot_vk.sowithout the patch, so part of that difference could come from my build, not the PR.Thanks for the fix!
Tested on an RTX 4080 / Windows 11 / Ryzen 9 7900X:
main4cfa08fwith this PR merged, warm caches, Kokiri Forest standing still, 60 sRX_VK_FRAMELOGper run, windowed 1280x720, frame generation off. One run per build, plus two runs of plainmain.main(2 runs)main+ #449No regression in fps, no white frames or device lost; 0 flashes in this run. Plain
mainbarely flickers on this card, so this can't confirm the fix, only that it does no harm here.waits gone pastdropped from 403-553 on main to 147.