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

Closed
ZurielAtr wants to merge 1 commit from fix/bc-upload-parts into main
ZurielAtr commented 2026-11-09 00:42:01 +00:00 (Migrated from github.com)

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

## 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](https://claude.com/claude-code)
NotRexed commented 2026-11-09 05:31:00 +00:00 (Migrated from github.com)

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

Closing to keep the queue clear — please rebase on current main and reopen; thanks!
Commenting is not possible because the repository is archived.
No description provided.