feat(vk): AMD FSR 3.1 as the default Upscaler without matrix hardware #2110
Closed
addisonbair wants to merge 1 commit from
fsr-default into main
pull from: fsr-default
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
1 participant
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!2110
Loading…
Reference in a new issue
No description provided.
Delete branch "fsr-default"
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 GPUs without matrix hardware (AMD RDNA2 such as the Steam Deck, Intel), the game's own upscaler runs its network's matrix multiplies in a shader function. On the Steam Deck that single dispatch costs ~12 ms of the frame (#1000). Switching the Upscaler to AMD FSR 3.1 removes it: 11.9 → 13.9 fps docked in the #1000 measurements, and the network dispatch drops out of the GPU profile. Today a Deck user has to find that menu row themselves.
What changes
coopmat_software(), i.e.mma_software) and FSR 3.1 is supported, an Upscaler nobody has chosen defaults to AMD FSR 3.1. A line in the log says so.hookshot_options.iniyet, or a file from beforeoptions_version=5. Older files wrotedlss=whether or not it was chosen, which is the same reasoning as theoptions_version4 step for Descriptor reuse. Saving now writesoptions_version=5, so a choice made in the menu after this is kept.create_device, after the push-descriptor limit is read, becausefsr3::supported()needs that limit and caches its answer.Testing
tests/run_all.py: the same results on cleanmain(1a43a1e) and with the patch. Every failure is the same on both and comes from tools missing in my container (glslang etc.); none are new.options_version=5,dlss=0→ kept (chosen)options_version=4,dlss=0→ FSR 3.1options_version=4,dlss=1→ kept (not the game's own)🤖 Generated with Claude Code
Heads-up: this conflicts with main now. Could you rebase onto main and resolve the conflicts? Thanks!
The logic holds up, and the reasoning matches the
options_version4 step. I checked the ordering:menu_init()runs frompick_device()beforecreate_device(), soupscaler_unchosenis already set whenmenu_upscaler_default()runs at the end ofcreate_device()(gpu/vk/vk_main.cpp:501).coopmat_init()has run anddev.max_push_descriptorsis read, sofsr3::supported()gives an answer it can cache.fsr3_wanted()still gives way to an upscaler chosen through the environment (temporal_env_chosen()).The menu tests that read
vk_menu.cppandvk_main.cpppass at this head (51 checks).What it still needs:
gpu/vk/vk_menu.cppandgpu/vk/vk_menu.h, as @hckrman101 noted. Main has moved a lot there: FSR 4 (#2342), DLSS frame generation and others. When you rebase, check thatupscaler_rows::GAME/FSR3and the row indices still mean the same thing. Also check that no other PR has takenoptions_version=5in the meantime. CI hasn't run on this PR yet (only the title check), so it will get its first full run after the rebase.docs/workflow.mdand the main hardware this targets. So far the testing is headless start-up on Intel Arc and NVIDIA, plus fps numbers taken from #1000. This changes what every Deck and Intel player sees on first start, so please add a run on a Deck (or an RDNA2 card) showing the picture with FSR 3.1 by default. CONTRIBUTING asks for screenshots when a change shows on screen. A before/after at the same spot, plus the log line, would cover it.gpu/vk/vk_menu.cpp:39adds a second#include "vk_fsr3.h"; it's already included on line 41. The comment aboveoptions_version(line 1260) lists what 2, 3 and 4 mean, so add 5 ("the Upscaler: settled once the device is known, see menu_upscaler_default").The logic is right (
coopmat_init()runs before the new call, andmenu_env_on'sversion < sinceleaves Descriptor reuse alone), but the scope is wider than the description says:vk_coopmat.cpp:342). NVIDIA is only unchanged for RTX. Existing users withoptions_version4 who chose the game's upscaler are switched once.RX_VK_MMA_SOFTWARE=1on RTX makes FSR 3.1 permanent.vk_fsr3.his included twice invk_menu.cpp.vk_menu.cpp(options_version=4at:1430, migration at:3113),vk_menu.handvk_coopmat.cpp.options_version=5is also used by #2119 and #2197.Whether this should cover every non-matrix GPU or only Deck/RDNA2 is a maintainer call.
Thanks for the rebase. The new
upscaler_defaultflag is a nice answer to two of Joey-Magnus's earlier points: anRX_VK_MMA_SOFTWARE=1test run on RTX no longer makes FSR 3.1 stick, and the default is worked out again on another GPU until the player touches the row. The duplicatevk_fsr3.hinclude is gone, and theoptions_versioncomment now covers the new step. I also checked the other ways the Upscaler can change: the launcher bridge goes throughset_row, so it clears the flag too. Presets don't touchopts.dlss.One thing breaks it, though:
create_devicenow runs beforedev.max_push_descriptorsis read (it's set in theif (dev.push_descriptor)block a few lines below, and nowhere else). When the matrices run in software and no Upscaler has been chosen,fsr3::supported()is asked while the limit is still 0. It fails the< 15check, and becausedev.deviceis already set it caches thatfalsefor the whole run. So on the Deck and on Intel, FSR 3.1 is never picked by default. Worse, it also drops out of the Upscaler row for that run, which is a regression from main. The description says the call runs after the limit is read, and Joey's review of the first version said the same, so I think the rebase moved it. Moving the call after the push-descriptor block (just beforereturn true;) fixes it. Details inline.options_version=6is also used by #2119 (still open). Whichever lands second needs to bump to 7 and move itsversion < Ncheck with it.options_version=5throughout, and the tests in it were run before the rebase. Please update them, and re-run the Intel "no options file → FSR 3.1" case after the fix. It would have caught the problem above.CI has only run the title check so far, so the full build and tests haven't run on this head yet.
dev.max_push_descriptorsis still 0 here: it's read in theif (dev.push_descriptor)block below. When the flag is set and the matrices run in software,fsr3::supported()logs "fewer than 15 (0)" and cachesfalsefor the run (itsstatic const bool). That turns FSR 3.1 off on exactly the GPUs this targets, including in the menu. Moving this line after that block, just beforereturn true;, fixes it.Closing this one: on current main it makes the Steam Deck slower, the opposite of what it was for.
I did the Deck check you asked for, and also measured what each upscaler costs. Setup: main (
eaef1460game, this PR's renderer for both rows, only the Upscaler row changed), the first-start Minimum preset, the docked profile (what a first start sets), the standing Kokiri scene at a 1200 MHz GPU clock, two passes each:The handheld profile shows the same thing (2048x1152: 14.1 vs 13.2 fps, +5 ms GPU).
The default itself works on the Deck. "Upscaler AMD FSR 3.1 by default" is logged on a first start, again on the next start from the file it wrote, and from a file main wrote. Intel ARL behaves the same in start-up checks. The pictures are equivalent.
The reason the premise no longer holds: the ~12 ms this was meant to save was the game's TAAU network on v2.0.14, where FSR 3.1 really was a win on the Deck (#1000). On current main, AMD runs a cheap bilinear stand-in in its place (the context of #1439), so on these GPUs FSR 3.1 only adds cost. For image quality on AMD, #1439 (FSR 1 EASU + RCAS over the stand-in, ~0.5 ms) looks like the better path. I couldn't measure Intel in-game here (pipelines fail with -13 on this ARL iGPU), so I have no evidence to narrow it to Intel either.
Thanks for the careful reviews. The ordering bug you caught would have been a real regression.
🤖 Generated with Claude Code
github-sync referenced this pull request2026-11-12 06:22:58 +00:00