fix(vk): bound the wait for shaders still translating, then leave the… #2586
Closed
SadTransGirl wants to merge 1 commit from
SadTransGirl/fix/bounded-translation-wait into main
pull from: SadTransGirl/fix/bounded-translation-wait
merge into: MagicBeanDev:main
MagicBeanDev:main
MagicBeanDev:github/pr/2893
MagicBeanDev:github/pr/2890
MagicBeanDev:github/pr/2887
MagicBeanDev:github/pr/2878
MagicBeanDev:github/pr/2875
MagicBeanDev:github/pr/2874
MagicBeanDev:github/pr/2873
MagicBeanDev:github/pr/2871
MagicBeanDev:github/pr/2756
MagicBeanDev:github/pr/2897
MagicBeanDev:github/pr/2896
MagicBeanDev:github/pr/2718
MagicBeanDev:github/pr/2842
MagicBeanDev:github/pr/2691
MagicBeanDev:github/pr/2895
MagicBeanDev:github/pr/2743
MagicBeanDev:github/pr/2765
MagicBeanDev:github/pr/2708
MagicBeanDev:github/pr/2732
MagicBeanDev:github/pr/2755
MagicBeanDev:github/pr/2817
MagicBeanDev:github/pr/2876
MagicBeanDev:release-please--branches--main
MagicBeanDev:release-please--branches--main--release-notes
MagicBeanDev:github/pr/2778
MagicBeanDev:github/pr/2888
MagicBeanDev:github/pr/2866
MagicBeanDev:github/pr/2877
MagicBeanDev:github/pr/2800
MagicBeanDev:github/pr/2829
MagicBeanDev:github/pr/2850
MagicBeanDev:github/pr/2889
MagicBeanDev:github/pr/2882
MagicBeanDev:github/pr/2860
MagicBeanDev:github/pr/2849
MagicBeanDev:github/pr/2886
MagicBeanDev:github/pr/2794
MagicBeanDev:github/pr/2840
MagicBeanDev:github/pr/2830
MagicBeanDev:github/pr/2834
MagicBeanDev:github/pr/2719
MagicBeanDev:github/pr/2742
MagicBeanDev:github/pr/2741
MagicBeanDev:github/pr/2820
MagicBeanDev:github/pr/2771
MagicBeanDev:github/pr/2859
MagicBeanDev:github/pr/2858
MagicBeanDev:github/pr/2823
MagicBeanDev:github/pr/2757
MagicBeanDev:github/pr/2769
MagicBeanDev:github/pr/2844
MagicBeanDev:github/pr/2843
MagicBeanDev:github/pr/2673
MagicBeanDev:github/pr/2855
MagicBeanDev:github/pr/2739
MagicBeanDev:github/pr/2807
MagicBeanDev:github/pr/2851
MagicBeanDev:github/pr/2789
MagicBeanDev:github/pr/2814
MagicBeanDev:github/pr/2818
MagicBeanDev:github/pr/2774
MagicBeanDev:github/pr/2772
MagicBeanDev:github/pr/2750
MagicBeanDev:github/pr/2786
MagicBeanDev:github/pr/2785
MagicBeanDev:github/pr/2782
MagicBeanDev:github/pr/2779
MagicBeanDev:github/pr/2775
MagicBeanDev:github/pr/2706
MagicBeanDev:github/pr/2766
MagicBeanDev:github/pr/2747
MagicBeanDev:github/pr/2759
MagicBeanDev:github/pr/2745
MagicBeanDev:github/pr/2740
MagicBeanDev:github/pr/2733
MagicBeanDev:github/pr/2725
MagicBeanDev:github/pr/2727
MagicBeanDev:github/pr/2728
MagicBeanDev:github/pr/2729
MagicBeanDev:github/pr/2721
MagicBeanDev:github/pr/2722
MagicBeanDev:github/pr/2715
MagicBeanDev:github/pr/2714
MagicBeanDev:github/pr/2707
MagicBeanDev:github/pr/2703
MagicBeanDev:github/pr/2705
MagicBeanDev:github/pr/2697
MagicBeanDev:github/pr/2679
MagicBeanDev:github/pr/2676
MagicBeanDev:github/pr/2669
MagicBeanDev:docs/what-hookshot-connects-to
MagicBeanDev:fix/hdr-encode-test
MagicBeanDev:fix/main-tests
MagicBeanDev:fix/play-cache-files
MagicBeanDev:perf/game-barrier-order
MagicBeanDev:feat/heap-lazy
MagicBeanDev:feat/texture-detail
MagicBeanDev:perf/astc-opaque-bc1
MagicBeanDev:fix/fs-dir-lock
MagicBeanDev:fix/framegen-native-kept
MagicBeanDev:fix/update-no-downgrade
MagicBeanDev:port/k10-gcn-f16-mirrors
MagicBeanDev:fix/framegen-mult-cap
MagicBeanDev:chore/release-as-2.1.1
MagicBeanDev:perf/pcache-load-switch
MagicBeanDev:fix/prepare-progress-log
MagicBeanDev:fix/update-closes-stale-game
MagicBeanDev:fix/hdr-scaled-sampled
MagicBeanDev:perf/first-start-preset
MagicBeanDev:perf/zero-upload
MagicBeanDev:fix/vcore-escape-2s
MagicBeanDev:test/fake-gh-atomic
MagicBeanDev:perf/batch-idle-flush
MagicBeanDev:test/finish-stub-a
MagicBeanDev:chore/record-2.1.0
MagicBeanDev:fix/main-red-tests
MagicBeanDev:fix/test-display-startup-driver-cache
MagicBeanDev:feat/mesh-shader-mode
MagicBeanDev:fix/menu-probes-at-startup
MagicBeanDev:fix/fps-counter-classic
MagicBeanDev:fix/test-log-batch-flake
MagicBeanDev:fix/narrow-screen-hud
MagicBeanDev:ci/prereleases
MagicBeanDev:release/v2.0.15
MagicBeanDev:hotfix/v2.0.15
MagicBeanDev:fix/present-ahead-replay
MagicBeanDev:release/v2.0.13
MagicBeanDev:fix/bracket-paths-2013
MagicBeanDev:fix/hdr-overlays-2013
MagicBeanDev:fix/fps-counter-scale-2013
MagicBeanDev:fix/stick-seen-at-rest
MagicBeanDev:hotfix/menu-fits-screen
MagicBeanDev:fix/f1-always-opens-menu
MagicBeanDev:fix/ini-keep-lines
MagicBeanDev:claude/cranky-pike-7cf247
MagicBeanDev:perf/texture-answer-flat
MagicBeanDev:fix/stamp-test-modules
MagicBeanDev:fix/appimage-fonts
MagicBeanDev:fix/display-awake
MagicBeanDev:release/v2.0.12
MagicBeanDev:fix/discord-windows
MagicBeanDev:rc/v2.0.12-tests
MagicBeanDev:fix/dlss-keep-feature
MagicBeanDev:rc/v2.0.12
MagicBeanDev:button-icons
No reviewers
Labels
Clear labels
accessibility
Barrier affecting people with disabilities
autorelease: pending
autorelease: tagged
bug
Something isn't working
dependencies
Pull requests that update a dependency file
documentation
Improvements or additions to documentation
duplicate
This issue or pull request already exists
enhancement
New feature or request
github_actions
Pull requests that update GitHub Actions code
good first issue
Good for newcomers
help wanted
Extra attention is needed
invalid
This doesn't seem right
question
Further information is requested
testing wanted
wontfix
This will not be worked on
No labels
accessibility
autorelease: pending
autorelease: tagged
bug
dependencies
documentation
duplicate
enhancement
github_actions
good first issue
help wanted
invalid
question
testing wanted
wontfix
Milestone
Clear milestone
No items
No milestone
Assignees
Clear assignees
No assignees
2 participants
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".
No due date set.
Dependencies
No dependencies set
Reference
MagicBeanDev/Hookshot!2586
Loading…
Reference in a new issue
No description provided.
Delete branch "SadTransGirl/fix/bounded-translation-wait"
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?
On a cold or changed program bank, a draw whose shader is still translating waits it out (#1573), which brings back the 0.2-3 s pauses at an area's first new programs. This adds an opt-in bound on that wait,
RX_VK_TRANSLATE_WAIT_MS, for people who see those first-visit freezes. Nothing changes by default.Change (off unless set):
RX_VK_TRANSLATE_WAIT_MS=<ms>(8 is the measured value), a draw whose shader is still translating and whose targets hold an earlier frame's picture waits for it at most that long a frame in all, on each recording thread, and is left out of the frame if it's still not done. The wait (jobs_wait_for) doesn't take the queued job onto the waiting thread: running it inline would block for its full 0.2-3 s and defeat the bound.RX_VK_PIPE_SKIP=0/2keep their meanings.gpu/vk/translate_wait.h,strtodwith an end check): anything but a number (8ms,off) is ignored with a warning instead of reading as 0, and the value in use is logged.PROF_EXACT(), aswait_fordoes.Why it's opt-in. An untranslated program can't be classified, so a translation slower than the bound is left out whether or not it writes memory: the case #1573 was merged to fix. Nothing visible came of it in the runs below, but that's one route on one NVIDIA card, and a missing write usually shows later and somewhere else. Off by default, testers on other machines and routes can try it, and the default can change once there's more than one machine's data.
Measured. RTX 4070 SUPER 12 GB (617.42), Windows 11, Ryzen 9 9950X3D, DLAA 2560x1440, unattended, from the title into Castle Town and out to Hyrule Field, two runs each. The build was this change's first version on main
c544828f(with #2585), where 8 ms was the default, againstRX_VK_TRANSLATE_WAIT_MS=-1:RX_VK_NO_PROGRAM_CACHE=1): fpsMost of the extra draws left out are in two bursts, the load into the field and the fade at its gate, where the screenshots are black either way. Screenshots every 60 frames showed nothing missing. At the first frame after the load, the run that waited out was missing the HUD (main's own skip of pipelines still building), and the bounded run had it. Those runs' wait counts (1,499-1,505 waited out against 7,999-9,409 bounded) still counted draws after the bound was spent as waits, which this version no longer does, so the summed time is the number to compare. Rows in
docs/tested-configurations.md.Tests.
tests/test_draw_side_effects.pycompiles the real draw decision and runs everyRX_VK_PIPE_SKIPmode with the switch unset,8,0and8ms: waited out unless set, bounded and then left out when set, no wait counted with a bound of 0, a non-number ignored. It also checks the parser. The checks that read the changed files pass, except two that fail the same way on plain main on this PC.Not changed. Compute dispatches still wait their translation out (the
jobs_wait(cp->ready)on the dispatch path invk_draw.cpp): a follow-up. It may be part of why frames over 250 ms only drop from 11 to 6-8.Not tested. AMD, Intel, Linux; other routes; whether a left-out draw's memory write is ever missed.
Part of #995.
Assisted-by: Claude Opus 5.5, Claude Mythos 5.2
🤖 Generated with Claude Code
WIP: fix(vk): bound the wait for shaders still translating, then leave the…to fix(vk): bound the wait for shaders still translating, then leave the…Thanks for picking this up: the first-visit pauses since #1573 are real, and a bound is a reasonable direction. I read the diff against main and I don't think it should go in as it is. The points, most important first:
RX_VK_PIPE_SKIP=2, but a translation that takes 0.2-3 s (the pauses this targets) is always over it.jobs_wait_forreturns false forms <= 0, so a new area with many new programs behaves likeRX_VK_PIPE_SKIP=2after the first slow one.jobs_waitruns the queued job on the waiting thread when it is still in the queue (the job-steal path, added because a new area queues a hundred jobs).jobs_wait_foronly waits, so with busy workers the translation itself finishes later than it does today.jobs_wait(cp->ready)invk_draw.cpp, so the same pause remains there.RX_VK_TRANSLATE_WAIT_MSgoes throughatof, so a typo reads as 0 and skips at once.One data point from my side: on a prepared install (NVIDIA, Linux) the "waits for shaders or pipelines" line reads 0.00 in 120 of 124 intervals of a long play session, so this only matters for a cold or changed program bank. That is also the test I'd want to see before this changes the default: one run with a cold program bank each way, comparing the summed waits, the draws left out, the frame times, and whether anything flashes or goes missing.
Ideas that would keep #1573's guarantee:
jobs_waitdoes), and bound only the wait for a job another worker already runs.-1) so people with the freezes can try it and report.Tested #2586 on the same PC: main
c544828f+ #2586, Castle Town to Hyrule Field, two runs each, RX_VK_TRANSLATE_WAIT_MS=-1 (as #1573) against the default 8 ms:atofreads a typo (8ms,off) as 0, which means the bound is spent immediately and every untranslated draw on persistent targets gets left out, i.e.RX_VK_PIPE_SKIP=2without telling anyone. Parse it withstrtodand an end-pointer check, fall back to the default with a warning, and log the value in use once, likeRX_VK_FALLBACK_PHI_LIMITdoes.Nit: once the budget is spent,
jobs_wait_forreturns at once and the draw is counted as a wait (and as a skip). That inflates the "waits for shaders or pipelines" count we compare against #1573. Counting it only when time was actually spent (budget_left > 0before the call) would keep the stat honest.PROF_EXACT()is also missing on this path, unlikewait_for.Thanks for the runs, that's the test I asked for and the numbers are encouraging: on a cold bank the bound gives about 8% more fps and about 40% fewer frames over 100 ms on that route, with nothing visibly missing (and the HUD at the first frame after the load is a nice catch). The code is unchanged since my comment, so here's where my points stand:
vk_draw.cpp. That's fine to leave for a follow-up, but please say so in the description. It may be part of why frames over 250 ms only drop from 11 to 6-8.atof(6): still open, see inline.What I'd like before this goes in:
RX_VK_TRANSLATE_WAIT_MSdefaulting to -1) and keep 8 as the documented setting for people with first-visit freezes. Then testers on AMD/Intel and on other routes can report, and we change the default once there's more than one machine's data. The other route would be the narrower skip from my comment: leave the draw out only when the previous translation of the same stages says it writes no memory, and keep 8 ms as the default.test_env_onchecks on both platforms are aboutHOS_FPS_LOGinhost/oot_high_fps.c, which this PR doesn't touch, and main's runs are green now. They aren't this PR's fault.Unrelated to #2585 (the VRAM squeeze in
vk_texture.cpp): no shared code, and either can land without the other.Thanks, all done in 80e43f44 (with main merged first):
RX_VK_TRANSLATE_WAIT_MSunset waits each translation out, as #1573; 8 is the documented value for people with first-visit freezes. The lost-write risk is in the description as the reason it's opt-in.atofis replaced bytranslate_wait::parse(strtodwith an end check,gpu/vk/translate_wait.h): a non-number is ignored with a warning, and the value in use is logged once.PROF_EXACT(). The test now checks the count, with a bound of 0 among the cases.HOS_FPS_LOGchecks should be green now.The narrower skip from your first comment (leave a draw out only when the previous translation of the same stages says it writes no memory) would be a good default later. I've kept this PR to the opt-in bound.
I merged 26ae0e7e into current main (clean) and ran tests/test_draw_side_effects.py, test_env_on, test_jobs_wait_runs_queued, test_jobs_failure, test_gpl_cold_library, test_ub_threads, test_fallback_depth_hold, test_shadow_mask_guard and test_reactive_mask. All pass.
hckrman101's points are handled in 80e43f44:
jobs_wait_for waits on the same done_cv that worker_loop notifies after each job, so a translation that finishes inside the bound wakes the draw at once. Leaving the job queued instead of running it inline is right here, as hckrman101 agreed.
One thing worth knowing, already in the docs row: RX_VK_TRANSLATE_WAIT_MS=0 behaves like RX_VK_PIPE_SKIP=2 for persistent targets, because the budget is spent before it starts. The lost-write risk stays the reason it's opt-in, and that is stated plainly. Approving as the opt-in it now is.