Skip to content

fix(vk): upload ASTC textures re-encoded as BC3 over several submissions - #900

Closed
ZurielAtr wants to merge 1 commit into
NotRexed:mainfrom
ZurielAtr:fix/bc-upload-parts
Closed

ZurielAtr wants to merge 1 commit into
NotRexed:mainfrom
ZurielAtr:fix/bc-upload-parts

Conversation

@ZurielAtr

@ZurielAtr ZurielAtr commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

What changed

An ASTC texture kept as BC3 is decoded, resized on AMD (#705) and encoded on the GPU. All of it went into one upload
command buffer, so into one submission.

Hyrule Field's two terrain material arrays are 1365 x 1365 x 90 with 11 levels; on AMD they become BC3 at 1536 x 1536
with 8 levels. They are evicted while Link is in Castle Town and made again when he comes back. That is about 570 M texels
of decode, blit and encode in a single submission.

Now upload_astc_gpu records runs of layers, each with all its levels, while the recording's share lasts:

  • The share is RX_VK_BC_PART_MTEXELS: 16 M texels by default, or 0 for everything at once, as before.
  • Each call records at least one run, so every call makes progress.
  • The remaining layers wait in bc_pending. texture_bc_continue() records more of them at the start of each following
    recording.
  • While layers are waiting, a submission is split every 16 draws instead of every 120. The arrays finish within a frame
    or two.
  • Until then, the texture shows what its image held for the missing layers. That happens during the scene change.

The run arithmetic is in gpu/vk/bc_parts.h. A texture that is destroyed while some of its layers are waiting is taken
off the list.

Why

That single submission ran past Windows' 2-second GPU timeout. Windows reset the driver ("AMD Software detected a driver
timeout"), and Hookshot logged device lost. When it happened, the VRAM was not full: 6.5 of 7.2 GB.

How it was tested

RX 7700S Laptop (8 GB), Ryzen 7 7735HS, Adrenalin 26.10.1, Windows 11, v2.0.5.

  • Before: going from Castle Town to Hyrule Field reset the driver 3 times out of 3. In the log, both arrays were made
    again right before each reset. Then came a 10-12 s GPU wait, submit ... failed (-4) and device lost.
  • After: Castle Town to Hyrule Field and back several times, with no reset and no device lost.

Game-free check: tests/test_bc_parts.py compiles tests/test_bc_parts.cpp. It simulates the upload across recordings
and checks that every layer goes in exactly once and in order. It covers the terrain array (12 recordings at 16 M texels),
no budget (one recording), a larger budget, and only a few dirty layers. It also checks that the upload and the replay still
use the parts. It is listed in tests/run_all.py with --cxx g++. python -I -B tests/run_all.py: everything passes
here except nx2/test_nup_paths.py and tests/test_fps_overlay_order.py, which fail the same way on a clean main on
this machine.

Note: this PR and #899 each add one line at the same place in tests/run_all.py's ARGS. Whichever is
merged second needs a one-line rebase.

🤖 Generated with Claude Code

An ASTC texture kept as BC3 was decoded, (on AMD) resized and encoded on the GPU in one upload command buffer. Hyrule
Field's two terrain material arrays (1365 x 1365 x 90, 11 levels, BC3 at 1536 x 1536 x 8 levels on AMD) are evicted
in Castle Town and made again when Link comes back: ~570 M texels of decode, blit and encode in one submission. On an
RX 7700S (8 GB, Adrenalin 26.10.1, Windows 11) that ran past Windows' 2-second limit three times out of three: the
driver was reset ("AMD Software detected a driver timeout") and the device lost, with VRAM not full.

upload_astc_gpu now records runs of layers (each with all its levels) while the recording's share lasts,
RX_VK_BC_PART_MTEXELS (16 M texels; 0: all at once, as before), at least one run per call; the layers left wait in
bc_pending and texture_bc_continue() records more at the start of each next recording. While some wait, a submission
is split every 16 draws instead of 120, so they are in within a frame or two. Until then the texture shows what its
image held for those layers, during the scene change. The run arithmetic is in gpu/vk/bc_parts.h.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Assisted-by: Claude Opus 5.5
@NotRexed

NotRexed commented Nov 9, 2026

Copy link
Copy Markdown
Owner

Closing to keep the queue clear — please rebase on current main and reopen; thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants