perf(vk): integrated GPUs keep every large ASTC texture as BC3, whatever the driver allows them #775

Open
Yeetbot90 wants to merge 1 commit from Yeetbot90/Longshot:perf/igpu-astc-bc3 into main
Contributor

Type: perf · Risk: low · Tested on: Windows 11, RX 9070 XT (the same rule forced by its switch); game-free checks · Needs: Windows, an integrated GPU on a PC with 24 GB of RAM or more (AMD 680M/780M/880M/890M, Intel Arc graphics in Core Ultra), and a Steam Deck

Why

Integrated GPUs on PCs with plenty of RAM kept the finer ASTC textures (UI, characters) as RGBA8, four times the size of BC3, against a texture budget of 4 GB or less. Cards the driver allows under 8.5 GB keep every large decoded ASTC texture as BC3 (issue 519, then 8 GB cards); an integrated GPU was judged by the same allowance, though that is the system RAM the game and Windows use, and it reads its textures through the same memory as the CPU. On this PC (32 GB of RAM) the Ryzen 9 7900X's graphics are allowed 10,232 MB, so the rule never applied there; integrated GPUs on 16 GB PCs (Unity's UHD Graphics laptop: 7.2 GB allowed) already had every one as BC3. Memory filling up over play is the worklist's top row; see NotRexed/Hookshot#993.

What changed

Every integrated GPU keeps every large decoded ASTC texture as BC3, whatever the driver allows it; cards keep the rule they had.

  • textures: all(allowed, integrated) in gpu/vk/astc_bc_policy.h (true for an integrated GPU, else all_by_vram(allowed) as before), asked where vk_texture.cpp decides which ASTC textures become BC3; the log line says when an integrated GPU is why.
  • tests: tests/test_astc_bc_policy.cpp (an integrated GPU allowed 10 GB, unknown, or under 8.5 GB; cards as before), tests/test_astc_bc_policy.py (the call and the device type it is given).

Measurements

Verdict: in Kokiri Forest every large ASTC texture as BC3 holds about 930 MB less decoded ASTC (2,496-2,532 MB against 1,579-1,587 MB) and 390-640 MB less VRAM in use, at the same GPU time and frame rate, in every pair. Measured on a discrete card with the rule forced; on an integrated GPU itself it is untested.

Hardware: Windows 11 (26200), RX 9070 XT (AMD 26.10.1), Ryzen 9 7900X, 32 GB; headless (HOS_HEADLESS=1)
Build: the nightly-182-5274fb72 renderer (main before this PR), RX_VK_ASTC_BC_ALL=1 (the rule this PR gives integrated GPUs) against RX_VK_ASTC_BC_ALL=0 (what such a GPU does on main); RX_VK_FRAMEGEN=0, HOS_FPS_MAX=1000
Baseline: main's renderer with RX_VK_ASTC_BC_ALL=0 against =1, not main against this PR: this PR changes the rule only on integrated GPUs, and this PC's integrated GPU loses the device when the GPU decodes Kokiri Forest's terrain (#489), so the rule this PR gives integrated GPUs was forced by its switch on the discrete card; the switch is the same code path the PR turns on
Scene: Kokiri Forest outside Link's house: the save loaded by scripted input, a 2.5 s walk, then the camera turning; the frame rate from the game's own vi: lines over the window 62-92 s after the start, the memory from the last vk: VRAM: and textures: lines
Method: the arms alternated, seven runs of 96 s; one more BC3 run ran during a build on this PC and is left out; nothing else running in the others
How to reproduce: start the game twice with the same save and settings, once with RX_VK_ASTC_BC_ALL=1 and once with =0, and compare the textures: decoded ASTC lines after the area loads

Before, RX_VK_ASTC_BC_ALL=0 (main's rule on such a GPU): main @ 5274fb72 After, RX_VK_ASTC_BC_ALL=1 (this PR's rule): main @ 5274fb72
Decoded ASTC (MB) 2,510 / 2,523 / 2,532 / 2,496 1,579 / 1,587 / 1,586
All textures (MB) 4,346 / 4,076 / 4,178 / 4,650 3,496 / 3,288 / 3,183
VRAM in use (MB) 8,431 / 8,559 / 8,433 / 8,432 8,047 / 8,047 / 7,920
GPU time a frame (ms) 6.9 / 6.8 / 7.1 / 7.2 7.0 / 7.1 / 7.1
Game fps 79.5 / 84.2 / 80.5 / 79.8 79.0 / 81.0 / 80.6
Frames over 20 ms in the 30 s 5 / 6 / 6 / 8 55 / 9 / 8 (the 55 once, not again)
tests/test_astc_bc_policy.py (this PR's version; After: this PR @ 129a7c07) fails passes

The runs in order: off, on, off, off, on, on, off (the values above in that order within each arm). Game fps: the median of the game's own vi: lines over the last 30 s (frame generation off). The scene is CPU-bound on this PC (about 6 cores busy), so the frame rate says nothing of what BC3 saves an integrated GPU in bandwidth.

off (run 4): vk: textures: decoded ASTC 2532 MB, ...
on (run 5):  vk: textures: decoded ASTC 1587 MB, ...

tests/run_all.py: 540 passed, 18 failed, 35 skipped on main @ aa95d35f and on this PR @ 129a7c07: the same 18 (this worktree's setup: packaging, the builder's preflight, release; none reads the changed files). tests/test_astc_bc_policy.py (this PR's version) fails on main (vk_texture.cpp no longer has: astc_bc_policy::all(allowed, integrated)) and passes here.

Flags and settings

No new switch.

Flag What it is Before this PR After this PR Effect Helps / doesn't help / untested Recommendation
RX_VK_ASTC_BC_ALL=1/0 Every large ASTC texture as BC3 (1), or the finer ones as RGBA8 (0), on any GPU unset: under 8.5 GB allowed unset: under 8.5 GB allowed, or an integrated GPU On integrated GPUs allowed 8.5 GB or more, the finer ASTC textures as BC3 Helps: memory (930 MB less in Kokiri Forest). Untested: on an integrated GPU itself Unset

Testing

Tested: On this PC: the game in Kokiri Forest on the RX 9070 XT with the rule forced on and off (Measurements), the screenshots looked at for damage; tests/test_astc_bc_policy.py fails on main's source and passes here; tests/run_all.py on main and on this PR. The renderer builds with llvm-mingw.

Screenshots from the measured runs (1024 x 576 captures of the 2560 x 1440 output; the camera turns all the time, so they are not the same view): left, the finer ASTC textures as RGBA8 (run 1, main's rule on such a GPU); right, every large one as BC3 (run 2, this PR's rule). No damage in the UI, Link's clothes, the fairy or the minimap.

RGBA8 (main's rule) BC3 (this PR's rule)
RGBA8 BC3

Not tested: The game on an integrated GPU allowed 8.5 GB or more with this PR: this PC's integrated GPU loses the device when the GPU decodes Kokiri Forest's terrain (that is #489, a separate fix). The cost of the extra BC3 encoding (one compute pass a texture at load) on an integrated GPU, and how the finer textures look as BC3 at 720p-1080p. Not built on Linux (one line of portable C++).

Must be tested:

  • Windows, an AMD 780M/880M/890M or Intel Core Ultra graphics on a PC with 24 GB of RAM or more, by hand: play Kokiri Forest and Castle Town's market on main and on this PR, expecting all large ASTC textures kept as BC3 with an integrated GPU in longshot_log.txt, several hundred MB less decoded ASTC in its textures: lines, and no damaged UI, faces or clothes on screen (test request T-YJLE)
  • Steam Deck (Linux, RADV), by hand: the same two areas on main and on this PR, expecting the log's all large ASTC textures kept as BC3 line on this PR (on main only if the Deck is allowed under 8.5 GB), less decoded ASTC where main lacked it, and no damaged UI, faces or clothes (test request T-U7L2)

Risks

What could break: On integrated GPUs allowed 8.5 GB or more, the finer ASTC textures (UI, characters, faces) are BC3 now: 8 bits a texel against the ASTC's own 3.6-8, so gradients and edges can band or block a little, as they already do on 4-8 GB cards and on integrated GPUs with 16 GB of RAM. Each one takes a GPU encode at load, so a load on a weak integrated GPU can take a little longer.

Turning it off: RX_VK_ASTC_BC_ALL=0, or revert the commit.

Compatibility: Nothing changes: no save, options, cache or interface change. The Steam Deck counts as an integrated GPU.

Issues

See NotRexed/Hookshot#993 (memory filling up over play, the worklist's top row); issue 519 set the rule for small cards.

Checklist

Everyone

  • One topic.
  • The title is a Conventional Commit (type(scope): description) of the status line's type.
  • Why gives the reason plainly and links the issues that fit (the tracker searched).
  • Measurements has a verdict, or one line saying why there is nothing to measure.
  • Testing names what was tested, what wasn't, and what must still be tested, where and how.
  • Rebased on current main.
  • python -I -B tests/run_all.py passes (any failure that also fails on main is named).
  • No game files, dumps, build output or generated files.
  • third_party/ untouched (a new folder with a PROVENANCE.md instead).
  • The license is OK: GPL-3.0-or-later, nothing incompatible and nothing decompiled.

When it applies

  • AI assistance recorded with Assisted-by: / Co-Authored-By: trailers.
  • A game-free test added for the fix, failing on main and passing here.
  • A check under tests/ that reads changed source updated in this PR, not weakened.
**Type:** perf · **Risk:** low · **Tested on:** Windows 11, RX 9070 XT (the same rule forced by its switch); game-free checks · **Needs:** Windows, an integrated GPU on a PC with 24 GB of RAM or more (AMD 680M/780M/880M/890M, Intel Arc graphics in Core Ultra), and a Steam Deck ## Why Integrated GPUs on PCs with plenty of RAM kept the finer ASTC textures (UI, characters) as RGBA8, four times the size of BC3, against a texture budget of 4 GB or less. Cards the driver allows under 8.5 GB keep every large decoded ASTC texture as BC3 (issue 519, then 8 GB cards); an integrated GPU was judged by the same allowance, though that is the system RAM the game and Windows use, and it reads its textures through the same memory as the CPU. On this PC (32 GB of RAM) the Ryzen 9 7900X's graphics are allowed 10,232 MB, so the rule never applied there; integrated GPUs on 16 GB PCs (Unity's UHD Graphics laptop: 7.2 GB allowed) already had every one as BC3. Memory filling up over play is the worklist's top row; see [NotRexed/Hookshot#993](https://github.com/NotRexed/Hookshot/issues/993). ## What changed Every integrated GPU keeps every large decoded ASTC texture as BC3, whatever the driver allows it; cards keep the rule they had. - textures: `all(allowed, integrated)` in `gpu/vk/astc_bc_policy.h` (true for an integrated GPU, else `all_by_vram(allowed)` as before), asked where `vk_texture.cpp` decides which ASTC textures become BC3; the log line says when an integrated GPU is why. - tests: `tests/test_astc_bc_policy.cpp` (an integrated GPU allowed 10 GB, unknown, or under 8.5 GB; cards as before), `tests/test_astc_bc_policy.py` (the call and the device type it is given). ## Measurements **Verdict:** in Kokiri Forest every large ASTC texture as BC3 holds about 930 MB less decoded ASTC (2,496-2,532 MB against 1,579-1,587 MB) and 390-640 MB less VRAM in use, at the same GPU time and frame rate, in every pair. Measured on a discrete card with the rule forced; on an integrated GPU itself it is untested. Hardware: Windows 11 (26200), RX 9070 XT (AMD 26.10.1), Ryzen 9 7900X, 32 GB; headless (`HOS_HEADLESS=1`) Build: the nightly-182-5274fb72 renderer (main before this PR), `RX_VK_ASTC_BC_ALL=1` (the rule this PR gives integrated GPUs) against `RX_VK_ASTC_BC_ALL=0` (what such a GPU does on main); `RX_VK_FRAMEGEN=0`, `HOS_FPS_MAX=1000` Baseline: main's renderer with `RX_VK_ASTC_BC_ALL=0` against `=1`, not main against this PR: this PR changes the rule only on integrated GPUs, and this PC's integrated GPU loses the device when the GPU decodes Kokiri Forest's terrain (#489), so the rule this PR gives integrated GPUs was forced by its switch on the discrete card; the switch is the same code path the PR turns on Scene: Kokiri Forest outside Link's house: the save loaded by scripted input, a 2.5 s walk, then the camera turning; the frame rate from the game's own `vi:` lines over the window 62-92 s after the start, the memory from the last `vk: VRAM:` and `textures:` lines Method: the arms alternated, seven runs of 96 s; one more BC3 run ran during a build on this PC and is left out; nothing else running in the others How to reproduce: start the game twice with the same save and settings, once with `RX_VK_ASTC_BC_ALL=1` and once with `=0`, and compare the `textures: decoded ASTC` lines after the area loads | | Before, RX_VK_ASTC_BC_ALL=0 (main's rule on such a GPU): main @ 5274fb72 | After, RX_VK_ASTC_BC_ALL=1 (this PR's rule): main @ 5274fb72 | |---|---|---| | Decoded ASTC (MB) | 2,510 / 2,523 / 2,532 / 2,496 | 1,579 / 1,587 / 1,586 | | All textures (MB) | 4,346 / 4,076 / 4,178 / 4,650 | 3,496 / 3,288 / 3,183 | | VRAM in use (MB) | 8,431 / 8,559 / 8,433 / 8,432 | 8,047 / 8,047 / 7,920 | | GPU time a frame (ms) | 6.9 / 6.8 / 7.1 / 7.2 | 7.0 / 7.1 / 7.1 | | Game fps | 79.5 / 84.2 / 80.5 / 79.8 | 79.0 / 81.0 / 80.6 | | Frames over 20 ms in the 30 s | 5 / 6 / 6 / 8 | 55 / 9 / 8 (the 55 once, not again) | | `tests/test_astc_bc_policy.py` (this PR's version; After: this PR @ 129a7c07) | fails | passes | The runs in order: off, on, off, off, on, on, off (the values above in that order within each arm). Game fps: the median of the game's own `vi:` lines over the last 30 s (frame generation off). The scene is CPU-bound on this PC (about 6 cores busy), so the frame rate says nothing of what BC3 saves an integrated GPU in bandwidth. ``` off (run 4): vk: textures: decoded ASTC 2532 MB, ... on (run 5): vk: textures: decoded ASTC 1587 MB, ... ``` `tests/run_all.py`: 540 passed, 18 failed, 35 skipped on main @ aa95d35f and on this PR @ 129a7c07: the same 18 (this worktree's setup: packaging, the builder's preflight, release; none reads the changed files). `tests/test_astc_bc_policy.py` (this PR's version) fails on main (`vk_texture.cpp no longer has: astc_bc_policy::all(allowed, integrated)`) and passes here. ### Flags and settings No new switch. | Flag | What it is | Before this PR | After this PR | Effect | Helps / doesn't help / untested | Recommendation | |---|---|---|---|---|---|---| | `RX_VK_ASTC_BC_ALL=1/0` | Every large ASTC texture as BC3 (1), or the finer ones as RGBA8 (0), on any GPU | unset: under 8.5 GB allowed | unset: under 8.5 GB allowed, or an integrated GPU | On integrated GPUs allowed 8.5 GB or more, the finer ASTC textures as BC3 | Helps: memory (930 MB less in Kokiri Forest). Untested: on an integrated GPU itself | Unset | ## Testing **Tested:** On this PC: the game in Kokiri Forest on the RX 9070 XT with the rule forced on and off (Measurements), the screenshots looked at for damage; `tests/test_astc_bc_policy.py` fails on main's source and passes here; `tests/run_all.py` on main and on this PR. The renderer builds with llvm-mingw. Screenshots from the measured runs (1024 x 576 captures of the 2560 x 1440 output; the camera turns all the time, so they are not the same view): left, the finer ASTC textures as RGBA8 (run 1, main's rule on such a GPU); right, every large one as BC3 (run 2, this PR's rule). No damage in the UI, Link's clothes, the fairy or the minimap. | RGBA8 (main's rule) | BC3 (this PR's rule) | |---|---| | ![RGBA8](https://git.magicbean.dev/attachments/ddcf5fe1-0865-45a7-bf70-6d61dfbe509f) | ![BC3](https://git.magicbean.dev/attachments/db4aaf0c-46b7-4965-b5f4-4949a81697e3) | **Not tested:** The game on an integrated GPU allowed 8.5 GB or more with this PR: this PC's integrated GPU loses the device when the GPU decodes Kokiri Forest's terrain (that is #489, a separate fix). The cost of the extra BC3 encoding (one compute pass a texture at load) on an integrated GPU, and how the finer textures look as BC3 at 720p-1080p. Not built on Linux (one line of portable C++). **Must be tested:** - Windows, an AMD 780M/880M/890M or Intel Core Ultra graphics on a PC with 24 GB of RAM or more, by hand: play Kokiri Forest and Castle Town's market on main and on this PR, expecting `all large ASTC textures kept as BC3` with `an integrated GPU` in `longshot_log.txt`, several hundred MB less `decoded ASTC` in its `textures:` lines, and no damaged UI, faces or clothes on screen (test request T-YJLE) - Steam Deck (Linux, RADV), by hand: the same two areas on main and on this PR, expecting the log's `all large ASTC textures kept as BC3` line on this PR (on main only if the Deck is allowed under 8.5 GB), less `decoded ASTC` where main lacked it, and no damaged UI, faces or clothes (test request T-U7L2) ## Risks **What could break:** On integrated GPUs allowed 8.5 GB or more, the finer ASTC textures (UI, characters, faces) are BC3 now: 8 bits a texel against the ASTC's own 3.6-8, so gradients and edges can band or block a little, as they already do on 4-8 GB cards and on integrated GPUs with 16 GB of RAM. Each one takes a GPU encode at load, so a load on a weak integrated GPU can take a little longer. **Turning it off:** `RX_VK_ASTC_BC_ALL=0`, or revert the commit. **Compatibility:** Nothing changes: no save, options, cache or interface change. The Steam Deck counts as an integrated GPU. ## Issues See [NotRexed/Hookshot#993](https://github.com/NotRexed/Hookshot/issues/993) (memory filling up over play, the worklist's top row); issue 519 set the rule for small cards. ## Checklist ### Everyone - [x] One topic. - [x] The title is a Conventional Commit (`type(scope): description`) of the status line's type. - [x] Why gives the reason plainly and links the issues that fit (the tracker searched). - [x] Measurements has a verdict, or one line saying why there is nothing to measure. - [x] Testing names what was tested, what wasn't, and what must still be tested, where and how. - [x] Rebased on current `main`. - [x] `python -I -B tests/run_all.py` passes (any failure that also fails on `main` is named). - [x] No game files, dumps, build output or generated files. - [x] `third_party/` untouched (a new folder with a `PROVENANCE.md` instead). - [x] The license is OK: GPL-3.0-or-later, nothing incompatible and nothing decompiled. ### When it applies - [x] AI assistance recorded with `Assisted-by:` / `Co-Authored-By:` trailers. - [x] A game-free test added for the fix, failing on `main` and passing here. - [x] A check under `tests/` that reads changed source updated in this PR, not weakened.
perf(vk): integrated GPUs keep every large ASTC texture as BC3, whatever the driver allows them
Some checks are pending
CI / Conventional Commit title (pull_request) Blocked by required conditions
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Blocked by required conditions
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Blocked by required conditions
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Blocked by required conditions
CI / Workflow lint (actionlint) (pull_request) Blocked by required conditions
Guide screenshots / Guide images and local UI source review (pull_request) Blocked by required conditions
Third-party parts / As their notes say (pull_request) Blocked by required conditions
Third-party parts / The same as upstream (pull_request) Blocked by required conditions
PR description / Description follows the template (pull_request_target) Successful in 3s
Website / Website on Cloudflare (pull_request_target) Has been skipped
129a7c077f
Cards the driver allows under 8.5 GB keep every large decoded ASTC texture as BC3, the finer blocks (UI, characters) too;
others keep those as RGBA8, four times the size. An integrated GPU was judged by the same allowance, though that is the
system RAM the game and Windows use, its textures are held to at most 6 GB of it, and it reads them through the same
memory as the CPU. On a PC with 32 GB of RAM the graphics of a Ryzen 9 7900X are allowed 10232 MB, so the finer ones
stayed RGBA8 there against a 4096 MB texture budget; integrated GPUs on 16 GB PCs (7.2 GB allowed) already had all as BC3.

astc_bc_policy::all(allowed, integrated) says yes for every integrated GPU and asks all_by_vram for the rest.
RX_VK_ASTC_BC_ALL=0 keeps the finer ones as RGBA8, as before. In Kokiri Forest (RX 9070 XT, RX_VK_ASTC_BC_ALL=1 against
0 for the same rule) decoded ASTC went from 2510 to 1579 MB and textures from 4346 to 3496 MB, at the same GPU time.

Co-Authored-By: Cursor <[email protected]>
Some checks are pending
CI / Conventional Commit title (pull_request) Blocked by required conditions
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Blocked by required conditions
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Blocked by required conditions
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Blocked by required conditions
CI / Workflow lint (actionlint) (pull_request) Blocked by required conditions
Guide screenshots / Guide images and local UI source review (pull_request) Blocked by required conditions
Third-party parts / As their notes say (pull_request) Blocked by required conditions
Third-party parts / The same as upstream (pull_request) Blocked by required conditions
PR description / Description follows the template (pull_request_target) Successful in 3s
Website / Website on Cloudflare (pull_request_target) Has been skipped
This pull request doesn't have enough approvals yet. 0 of 1 approvals granted.
Some workflows are waiting to be reviewed.
This branch is out-of-date with the base branch
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u 'perf/igpu-astc-bc3:Yeetbot90-perf/igpu-astc-bc3'
git switch 'Yeetbot90-perf/igpu-astc-bc3'
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
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/Longshot!775
No description provided.