feat(vk): FXAA in place of the full-size anti-aliasing network where the GPU multiplies in software (RX_VK_TAAU_FULL_SIZE=1, off by default) #687
No reviewers
Labels
No labels
area/accessibility
area/audio
area/input
area/install
area/menu
area/renderer
area/saves
area/upscaling
beanstalk: approved @ 1697603
beanstalk: approved @ 2c5a62e
beanstalk: approved @ 4fd82b7
beanstalk: approved @ 64d6d09
beanstalk: approved @ 6f91fae
beanstalk: approved @ 70a78f9
beanstalk: approved @ 8015c9a
beanstalk: approved @ 8d361dc
beanstalk: approved @ 9d8356e
beanstalk: approved @ abf2227
beanstalk: approved @ d82f202
beanstalk: approved @ e5f1e40
beanstalk: approved @ ee8ab5f
ci: approved
good first issue
gpu/amd
gpu/igpu
gpu/intel
gpu/nvidia
help wanted
kind
bug
kind
chore
kind
docs
kind
feature
kind
performance
kind
question
needs measurements
platform/linux
platform/macos
platform/steam-deck
platform/windows
preview
priority
critical
priority
high
priority
low
regression
status
blocked
status
confirmed
status
duplicate
status
invalid
status
needs-info
status
wontfix
testing wanted
ci: approved
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
MagicBeanDev/Longshot!687
Loading…
Reference in a new issue
No description provided.
Delete branch "zeldaootr/Longshot:deck-native-aa-stand-in"
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?
Type: feat · Risk: low · Tested on: Steam Deck OLED (SteamOS, RADV), Linux game-free checks · Needs: Steam Deck (Linux, RADV)
Why
On a Steam Deck at its own resolution (1280x800, 100% render), the game's own anti-aliasing costs about a fifth of
every frame. At 100% the game runs a small neural network,
9dc98871eb7fc101, over the picture to smooth its edges.The Deck's GPU has no hardware for the network's matrix maths, so Longshot does it in software: one profiled Deck frame
spent 8.95 ms of its 44.7 ms there, and the network took about 15 s to compile the first time the game started at 100%.
Today a Deck player has two choices: no anti-aliasing at 50% render, or the most expensive anti-aliasing at native.
Longshot already has a cheap replacement for this kind of network: a linear upscale with FXAA on the edges, the default
on these GPUs for the game's 3/4 network. This PR lets a player use it for the full-size pass too, as an opt-in. It is a
picture trade the player should choose: slightly softer textures and weaker smoothing of long, shallow edges, for about
9 ms a frame.
What changed
RX_VK_TAAU_FULL_SIZE=1(inlongshot_env.txt, or the environment) makes the FXAA stand-in take the full-size networkas well. It only applies where the matrix multiplies run in software: AMD, Intel and older NVIDIA cards. With nothing
set, every GPU takes exactly the networks it took before. Native HDR with the PsychoV35 tone mapper keeps the network,
because the stand-in writes no RGBA16F picture yet.
gpu/vk/taau_default.h(new, no Vulkan) holds the rule.full_size()says when the switch applies, andkeys()gives the default key list (main's list unless the switch is on).
taau_keyingpu/vk/vk_draw.cpptakes its default from that header (the switch read withenv_on), and leavesthe full-size pass to the network while PsychoV35 is on. The first time it answers for the full-size pass it logs what
happens:
vk: the full-size network 9dc98871eb7fc101 is stood in for by FXAA (RX_VK_TAAU_FULL_SIZE), or... runs while PsychoV35 is on (RX_VK_TAAU_FULL_SIZE), once each. An explicitRX_VK_TAAU_KEYSstill goes over everything. Anetwork
taau_keymatches is never compiled (unchanged), so with the switch on the network's 15 s first-start compileis gone too.
taau_stand_inlabels the helper with the network it stands in for, not always the 3/4 network's key.taau_key's doc comment names both networks.tests/test_taau_default.py(new) checks the rule across a table of GPUs with the switch off and on: offequals main's list on every GPU, the Deck included.
tests/test_taau_env_lookup.py, which cutstaau_keyout of thesource, has seven new cases: unset,
=0,=1,=1withRX_VK_NO_F16,=1on a GPU with cooperative matrices,=1with PsychoV35 (and PsychoV35 turned on and off in play), and explicit keys with PsychoV35, each checking the logline and the helper's label.
docs/development.md(The GPU), and a sentence on the Upscaler in the README.Measurements
Verdict: helps. On a Steam Deck at 1280x800 and 100% render,
RX_VK_TAAU_FULL_SIZE=1gives +15.8% standing inHyrule Field (15.09 → 17.47 fps) and +10.4% with the camera turning (one run each), with 8.9 ms less GPU time a frame.
With the switch unset, the PR measures the same as main (15.09 against 15.09 fps). These numbers are from the
commits measured,
3fd27a04(the branch has been rebased since, with its renderer change the same: see Testing).Hardware: Steam Deck OLED, AMD Custom GPU 0932 (RADV VANGOGH), Mesa 26.2.0-devel, SteamOS 3.9.5, stock GPU clock (1040 MHz median in every run)
Scene: Hyrule Field standing (a Kokiri save, a teleport to the Field at the Lost Woods bridge, 20 s to settle, a 45 s sample); a turning camera in the Field (3 cycles of 420 game frames of pans with Link standing, the last 2 sampled); output 1280x800 (
oe: output resolution 1280x800in every log), render 100%, Quality preset Custom (quality_preset=0), frame generation off, Upscaler on the game's ownMethod: headless over ssh, no
longshot_env.txtexceptRX_VK_PRECOMPILE=0with warm caches; fps from the present trace, GPU time from the unprofiledvk: GPU timeline; 2 interleaved runs per arm standing (main, on, unset, then unset, on, main, with other arms of the same session between them), the median; one turning-camera run each for main and the switchHow to reproduce: the settings above, with and without
RX_VK_TAAU_FULL_SIZE=1Baseline: main is the same
scripts/dev_packs.pybase with no pack. Note: this PR's renderer change was measured applied on main9c9d69ed, not on its own main6c9edffe: its finalgpu/vkchange (git diff 6c9edffe 3fd27a04 -- gpu/vk:gpu/vk/taau_default.h,gpu/vk/vk_draw.cpp, and the comment ingpu/vk/shaders/taau_upscale.comp) applies cleanly there, and was built as a renderer-only pack on that base, the one the Deck had warm. The game binary is the same in every arm; onlylongshot_vk.sodiffers.9c9d69ed3fd27a04(switch unset)3fd27a049dc98871eb7fc101The run-to-run spread is 0.04-0.15 fps standing. The turning camera has one run per arm, so its spread is not known;
the session before measured +17.5% there (13.97 → 16.42 fps, the pre-review code), and the hitches over 100 ms on that
route come from texture streaming, which this switch does not touch. Every run had the GPU at 1040 MHz (median), no
device loss and no amdgpu kernel lines, and exited normally. In the standing runs the lowest available memory was
973-1912 MiB and the lowest swap free stayed above 5.0 GB. The pre-review code measured the same standing on the same
base the session before (14.94 → 17.34 fps).
Flags and settings
Adds one switch, off by default.
RX_VK_TAAU_FULL_SIZE9dc98871eb7fc101) where the multiplies run in software1: FXAA in its place1: about 9 ms less GPU time a frame on a Steam Deck at 1280x800 and 100% render, and no 15 s first-start compile; slightly softer textures and weaker smoothing of long shallow edges; no ghostingScreenshots
Same spot, standing in Hyrule Field at the Lost Woods bridge, Steam Deck OLED, 1280x800, 100% render. The crops are 2x,
left to right: Before: main @
9c9d69ed(the network) | After, RX_VK_TAAU_FULL_SIZE=1: this PR @3fd27a04(FXAA).Whole frame, Before: main @

9c9d69ed:Whole frame, After, RX_VK_TAAU_FULL_SIZE=1: this PR @

3fd27a04:the switch, those edges are soft and have no outline. Thin leaves and fine texture (moss, specks in the fog) are a little
softer.
shows the same dark wall.
compare an edge from shot to shot. Each turning frame with the switch shows the same soft edges as standing.
Testing
Tested: Linux, game-free:
tests/test_taau_default.pyandtests/test_taau_env_lookup.pywith g++ and clang. On thePR's first commit (the tests alone, against main's code)
test_taau_env_lookup.pybuilds main'staau_keyand fails on itschecks: in
full-on,full-on-psychov35andfull-keys-psychov35(the full-size pass never stood in for, nothinglogged) and
custom(the helper's label);test_taau_default.pydoes not compile there (main has nogpu/vk/taau_default.h). Both pass on the second. Run again after the rebase onto mainaa95d35f, with g++ 13.3 and with clang23.1.5: at
ba06a950(the tests alone) both fail the same way, and ate1bd95eeboth pass; at the headf69594e3, the 126 checksthat are this PR's or read its changed files: 119 pass, 1 skips (
test_precompile_compute_guard: noclang++on this PC'spath) and 6 fail, each on main
aa95d35ftoo:test_appimage_player_build,test_crash_dialog,test_pipeline_tour,test_shader_module_guard,test_vk_pgo,test_walk_key.gpu/vk/vk_draw.cppatf69594e3compiled whole(
-fsyntax-only -Wall -Wextra) for Linux (clang 23.1.5) and Windows (llvm-mingw 20261104): the same warnings as mainaa95d35f's, none new. Also
tests/test_taau_fxaa.py,tests/test_upscale_fallback.py,test_upscaler_rows,test_env_on(fails as on main) andtest_readme_menu_rows.tests/run_all.py, run whole before thereview fixes: 483 passed, 14 failed, 84 skipped (tools not on this PC's path).
The same 14 fail on main
6c9edffein the same environment (482 passed there; the new check is the difference):test_appimage_player_build,test_bake_portability,test_cpm_discovery,test_crash_dialog,test_crash_record,test_env_on,test_lift_cache,test_lift_cleanup_error,test_make_game_cache,test_pipeline_tour,test_readback_late,test_vk_pgo,test_vram_budget_row,test_walk_key.gpu/vk/vk_draw.cppcompiled whole for Linux(clang) and Windows (llvm-mingw). The stand-in itself is the one the 3/4 network already runs on these GPUs.
In the game: this PR's renderer change on a Steam Deck OLED (Linux build, RADV), the arms in Measurements, with and without
the switch: the log line, no compile of the network, the fps and the pictures above. The numbers in Measurements are from the
commits measured (3fd27a04's
gpu/vkchange on main9c9d69ed), measured again after the review fixes, in a session oftheir own: the log line once with the switch and not without, no compile of the network with it, and the same-spot
pictures. An earlier session measured the change before the review fixes the same way (14.94 → 17.34 fps).
The branch has been rebased twice since those runs. Onto main
e090cc48, where #608(PsychoV35 by default) overlapped it:
tests/test_taau_env_lookup.pykeeps #608's RGBA cases, run for the 3/4 network,and the comment hunk in
gpu/vk/shaders/taau_upscale.compwas left out. Then onto mainaa95d35f, with the commitsre-authored under the forge's noreply address and each commit's change identical to the
e090cc48ones bygit patch-id.The changed lines of
gpu/vk/vk_draw.cppandgpu/vk/taau_default.hare those of the measured3fd27a04, so theDeck numbers stand for this head (
f69594e3).Not tested: the PR's change on its own main (
aa95d35f) in the game: the Deck runs used it on main9c9d69ed(arenderer-only pack). Shimmer in motion, Game Mode, frame generation and precompile on. Not run either: Intel, NVIDIA GTX
16xx, AMD discrete cards with the switch on, and Native HDR with PsychoV35 and the switch on.
Must be tested:
RX_VK_TAAU_FULL_SIZE=1,expecting the log line
vk: the full-size network 9dc98871eb7fc101 is stood in for by FXAAand nocompute pipeline of 9dc98871eb7fc101compile, with the picture matching theRX_VK_TAAU_KEYSarm (Test Farm:@Beanstalk steamdeck, RX_VK_TAAU_FULL_SIZE=1 at 100% render in Hyrule Field)
Risks
What could break: only with the switch on. Under the game's dynamic resolution (Render resolution Auto), the 3D is
upscaled linearly with FXAA instead of by the network. If the stand-in cannot draw (no push descriptors), the network,
which was never compiled, is left out and the 3D is missing; the 3/4 stand-in has the same dependency, and every GPU that
runs it has push descriptors. Turning PsychoV35 on mid-game with the switch set starts the network's compile, with the 3D
missing until it is built, as at today's first start at 100%; the log then says
vk: the full-size network 9dc98871eb7fc101 runs while PsychoV35 is on. Removing the switch after a first start with it (the one that preparedthe shaders) has the same cost once: that preparation left the network out, and its record (
longshot_prepared.bin)does not say so, so the network compiles in play (about 14 s on a Steam Deck), with the 3D left out meanwhile. Telling it from the record would mean
folding the switch into the driver part's stamp, which makes the whole warm pass run again at each change of the switch,
either way, for one pipeline: not done here.
Threads:
taau_keyis also asked by the prepare's workers, so with the switch on they read PsychoV35's state(
scene_tonemap_on:dev.hdrand the menu's options) without a lock. The pipeline state list's workers already read itso (
scene_tonemap_for, throughseed_program_of); at worst a worker builds or leaves out the network by the state amoment before, which play then corrects (a compile, or a pipeline never used).
Turning it off: leave
RX_VK_TAAU_FULL_SIZEunset, or set it to0.Compatibility: Nothing changes: with the switch unset the same networks run on every GPU, and no option, save or cache
changes.
Reviewer notes
Related: #528 gives the same stand-in an RGBA16F output for
PsychoV35. It does not touch
taau_key; once it lands, the PsychoV35 carve-out here (intaau_key) can go.A menu choice (an "FXAA (fast)" value on the Upscaler row, shown only where the multiplies are emulated) was considered
and left out of this PR. The row's values are saved numbers that tests pin (
OFF == 6,kUpscalers == 7), and itsengine stepping,
upscaler()and the Render resolution steps all key on them. The key list is read once at the start,while a menu choice changes at any time, and a network that was stood in for has no pipeline to fall back on. On top of
that, the new strings need 13 translations in
gpu/vk/menu_i18n.h. That is a follow-up if players want it.Checklist
Everyone
type(scope): description) of the status line's type.main.python -I -B tests/run_all.pypasses (any failure that also fails onmainis named).third_party/untouched (a new folder with aPROVENANCE.mdinstead).When it applies
Assisted-by:/Co-Authored-By:trailers.mainand passing here.tests/that reads changed source updated in this PR, not weakened.RX_VK_TAAU_FULL_SIZE=1has the FXAA stand-in take the full-size network9dc98871eb7fc101; unset is as before eb387f7547RX_VK_TAAU_FULL_SIZE=1, FXAA in place of the full-size network where the multiplies run in software (off by default) 3fd27a04dbRX_VK_TAAU_FULL_SIZEon a Steam Deck OLED at 1280x800Pictures for the description. Steam Deck OLED, Hyrule Field at the Lost Woods bridge, 1280x800 at 100% render. Crops are 2x, left to right: main @
9c9d69ed(the network) | this PR @3fd27a04,RX_VK_TAAU_FULL_SIZE=1(FXAA).The arch edge and hanging vines against the fog:

The vines on the right:

The foliage:

Link:

Whole frame, main @

9c9d69ed:Whole frame, this PR @

3fd27a04withRX_VK_TAAU_FULL_SIZE=1:Captured by an AI agent (Claude Code) for zeldaootr.
The pictures are in the description now (same spot, main | the switch), and the eight measured runs are under docs/tested/ (commit
15b434e8). On top of #303's RX_VK_READBACK_EARLY=1 and RX_VK_READBACK_LATE=newest the same switch reads 21.35 fps against main's 15.09 on the same Deck and scene (two interleaved runs each; the build was #303's head and this change on main9c9d69ed), so the two savings add up.WIP: feat(vk): FXAA in place of the full-size anti-aliasing network where the GPU multiplies in software (RX_VK_TAAU_FULL_SIZE=1, off by default)to feat(vk): FXAA in place of the full-size anti-aliasing network where the GPU multiplies in software (RX_VK_TAAU_FULL_SIZE=1, off by default)15b434e86aff06fa036dRebased onto main
e090cc48. #608 rewrotetaau_stand_infor PsychoV35: its RGBA path is kept, with this PR's label (the program's own key) on top, and the check's fixture now has one PsychoV35 switch. The comment-only edit toshaders/taau_upscale.compis dropped, so no generated header changes. The check fails at the test commit in the same cases as before and passes at the tip (g++, clang), withtest_psychov35_taau. The Deck numbers are from before #608, which changes nothing with PsychoV35 off, the case measured. Open question for a reviewer: since #608 the stand-in can write the RGBA16F picture, so this PR's rule that the network runs while PsychoV35 is on may no longer be needed; it is kept as it was, the careful side.ff06fa036df69594e348Rebased onto
mainaa95d35f(headf69594e3); the commits are re-authored with the forge's noreply address: no code change, the same patches bygit patch-id.Tests re-run on the new base, g++ 13.3 and clang 23.1.5:
test_taau_defaultandtest_taau_env_lookupfail at the test-only commitba06a950and pass ate1bd95ee; of the 126 checks that are this PR's or read its files, 119 pass, 1 skips and the 6 that fail fail on main too. The Deck numbers stand (thevk_draw.cppandtaau_default.hlines are those of the measured3fd27a04); the description says so.View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.