WIP: perf(vk): keep opaque ASTC textures as BC1, half of BC3's VRAM (RX_VK_ASTC_BC1, off by default) #521
No reviewers
Labels
No labels
area/accessibility
area/audio
area/input
area/install
area/menu
area/renderer
area/saves
area/tooling
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
4 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
MagicBeanDev/Longshot!521
Loading…
Reference in a new issue
No description provided.
Delete branch "Amateurwizrd/Longshot:perf/astc-bc1"
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?
Why
On a GPU without ASTC (NVIDIA and most desktop AMD cards) every ASTC texture is kept as BC3, 8 bits a texel, though
the opaque ones need only BC1's 4: a card short of VRAM pays for that alpha nobody uses with evictions and uploads.
What changed
gpu/vk/astc_opaque.h(new) reads each ASTC block's mode and colour endpoint modes without decoding; void-extentblocks with alpha at its maximum and blocks whose every partition's mode carries no alpha are opaque; modes that carry
alpha, reserved and illegal blocks are not.
RX_VK_ASTC_BC1=1,createingpu/vk/vk_texture.cppmakes a texture whose every block is opaque as BC1(its RGB format, so no block decodes as transparent), before the image is made and counted, so the budget and the
eviction see BC1's true size.
upload_astc_gpureads each layer of guest memory once into a private copy, judges that copy, and stages the samecopy; a layer with alpha makes the image again as BC3 (
bc1_to_bc3, the texels it holds kept) before anything isreserved or recorded, and a refused remake reserves no staging and is tried again.
texture_view_ofingpu/vk/vk_draw.cppresolves the view again when the touch on a cached hit made the imageagain, so the draw samples the new image; a copy between a BC1 and a BC3 texture goes through the encoder
(
gpu/vk/vk_xfer.cpp). The textures' log line counts those kept as BC1 and the MB saved.tests/test_astc_opaque.py(hand-built blocks of every mode and 420,000 random blocks, each one judged opaquedecoding to alpha 255 in the tree's decoder),
tests/test_astc_bc1_remake.py(the real upload, remake and view codewith a modelled device: alpha appearing, a game write between the judging and the staging, a refused remake, a cached
view);
tests/test_native_astc_texture_count.pyandtests/texture_staging_publication_test.cppfollow the new code.docs/development.mddocumentsRX_VK_ASTC_BC1.Flags and settings
RX_VK_ASTC_BC1=1RX_VK_COUNT_BY_ESTIMATE=1(existing)createdoes under this switch; the switch itself is unchangedMeasurements
Baseline: this PR @
1f9c5eb3, RX_VK_ASTC_BC1=0The switch is off by default, so main and this PR at their defaults run the same path; the comparison is the switch, on
the same build. The branch's head,
3484acbf, adds only thedocs/tested/files of these runs.main:
9c9d69ed(2026-11-14)this PR: perf/astc-bc1 @
1f9c5eb3Hardware: RTX 5070 Ti 16 GB, driver 621.01, Ryzen 7 7800X3D, 32 GB, Windows 11 Pro 26200
Scene: Kokiri Forest (child) standing, and a scripted Hyrule Field (child) walk; output 2560x1440, render resolution 75% (1920x1080), frame generation off, uncapped, VSync off, sound off, a 1707x960 window
Method: 60 s of PresentMon (MsBetweenPresents) after 15 s of settling, 2 runs each, alternated (off, on, off, on) after a warm-up run, the median of the runs; VRAM from the last
vk: VRAM:line and the textures' line oflongshot_log.txtHow to reproduce: a save at each spot,
RX_VK_ASTC_BC1=0and=1in turn on the same build, the numbers from PresentMon andlongshot_log.txt1f9c5eb3, RX_VK_ASTC_BC1=01f9c5eb3, RX_VK_ASTC_BC1=1An earlier build that carried this change before the review's fixes (3 rounds against the switch off, with Kokiri
Forest at 4K too) agreed: 157-240 MB less VRAM, none made BC3 again, frame time 0.03-0.19 ms longer.
Testing
Tested:
python -I -B tests/run_all.pyon Windows 11 (llvm-mingw): main @9c9d69ed531 passed, 5 failed; this PR532 passed and the same 5 failing on main (
test_oot_state_tap,test_portable_builder_home,test_portable_builder_startup,test_tested_configurations,test_walk_key), plustest_gpu_hang_watch, whichfails and passes on reruns of main @
9c9d69editself (a 4 s timing bound) and passed twice alone on this branch. Therenderer builds. In the game, the runs above: no device loss, no texture made BC3 again.
Not tested: frame dumps compared texel by texel (the screenshots are compared by eye); a card short of VRAM,
where the saving matters; GPUs with ASTC, where nothing changes; a Linux build (no Linux machine here).
Needs other testers:
RX_VK_ASTC_BC1=1: Hyrule Field and Castle Town against the switch off, expecting less VRAM in the textures' line, fewer evictions and no texture that turns transparent or wrong (request to open)gpu/vk/vk_texture.cpporgpu/vk/astc_opaque.h(request to open)Screenshots
Kokiri Forest from the same save after 15 s of settling, the game's own picture (1280x720), attached in the comments:
"this PR @
1f9c5eb3, RX_VK_ASTC_BC1=0" and "this PR @1f9c5eb3, RX_VK_ASTC_BC1=1". The same picture: the differencesare the fairies, the mist and the light moving between the two captures; no texture turned transparent or wrong.
Risk and rollback
With the switch on, a texture judged opaque wrongly would lose its alpha (the judging is checked against the decoder on
420,000 random blocks), and a mixed BC1/BC3 copy goes through the encoder, which costs CPU time. Off by default: nothing
changes unless
RX_VK_ASTC_BC1=1is set; unset it, or revert the commit.Reviewer notes
The idea is Hookshot-old's e9868252; here the choice is made before the image is made and counted, BC1 is used in its
RGB format, the staged bytes are the judged bytes, and a texture that gains alpha is made again as BC3. Written for
Longshot.
Issues
None
Checklist
For everyone
type(scope): description).main.python -I -B tests/run_all.pyrun and passing (any failure that also fails onmainis named above).third_party/untouched (a new folder with aPROVENANCE.mdinstead).If applicable
Assisted-by:/Co-Authored-By:trailers.docs/tested/for each new measured run (format indocs/tested-configurations.md; no appended row or assembled view).tests/that reads changed source updated in this PR, not weakened.This PR's own run is in: perf/astc-bc1 @
1f9c5eb3, RX_VK_ASTC_BC1 off and on alternated, 2 runs each after a warm-up, at Kokiri Forest standing and on a Hyrule Field walk (RTX 5070 Ti, 621.01). With it on: 287 MB fewer texture MB at Kokiri Forest (3481 against 3768) and 355 MB on the walk (7419 against 7774), 157-239 MB of it from BC1 in the textures' line, none made BC3 again; frame time within 0.05 ms either way. The Measurements now show this run instead of the earlier build's;3484acbfadds its four docs/tested files. Screenshots in the next comment.Kokiri Forest from the same save after 15 s of settling, the game's own picture. The same picture both ways: the fairies, the mist and the light move between the captures; no texture turned transparent or wrong.
this PR @

1f9c5eb3, RX_VK_ASTC_BC1=0this PR @

1f9c5eb3, RX_VK_ASTC_BC1=1Hey, I've got an 8 GB RTX 5060 Ti and this PR says it's untested on 8 GB cards. Happy to run it, same route and A/B setup I used for #421, main vs your branch, VRAM and fps per area. Want me to?
We built the same switch on a local branch before seeing this PR. Yours is closer to landing, so we'd rather help it than compete. What we checked at
3484acbf:astc_opaque::blockagainst a port ofhost_shaders/astc_decoder.comp(the decoder the renderer runs): 92M random blocks over all 14 footprints, 0 judged opaque that decode with alpha below 1.mainaa95d35fwith no conflicts.Two things we found:
vk_xfer.cpp:274; the conversion's blit runs before the recording,vk_texture.cpp:2583). Rare. We have a small patch with a test.createand at its first upload. About 100 ms for the terrain array on a Zen 2 CPU. A desktop won't show it; a Deck might.What we can offer, if you want any of it:
help-521-bc1-copy-and-pins(308391e0, 2383da57). Cherry-pick them or redo them your way; we won't push to your branch.Checked by an AI agent (Claude Code) for zeldaootr.
3484acbff18871fd4f23Rebased onto
main@bbe6fdf2. No tests were run here; the test boxes stay yours. No conflicts.RX_VK_ASTC_BC1) ac2cc16b30astc_opaque.hand BC1 rest on@kingo yes please, thank you. An 8 GB card is exactly the gap. Same route and setup as #421: main vs this PR with
RX_VK_ASTC_BC1=1, plus this PR with=0, VRAM and fps per area. Head isd36ba1f2.@zeldaootr thanks, that's a thorough check. I took both commits as they are (now
ac2cc16b,d36ba1f2), on top of the rebase ontobbe6fdf2. Checks that read this diff, one at a time with the pinned llvm-mingw: 372 run, 291 passed; every failure also fails on main on this PC, andtest_astc_opaqueandtest_astc_bc1_remakepass. Yes to the Steam Deck OLED run at 1280x800, off and on, which also covers the Linux build. On the double scan: invisible on a desktop. If the Deck run shows it, carrying the opacity verdict fromcreateto the first upload is the fix; I'd rather measure first. One question: every copy into a BC1 texture now makes it BC3. Do you know whether OoT copies into them often? If it does, part of the saving goes; kingo's run will show it in the VRAM numbers. I'd keep the fuzzer out of the PR unless the maintainers want it intests/.View command line instructions
Manual merge helper
Use this merge commit message when completing the merge manually.
Checkout
From your project repository, check out a new branch and test the changes.