fix(vk): a mesh fallback program with bigger payloads reuses the record arena #551

Open
zeldaootr wants to merge 2 commits from zeldaootr/Longshot:mesh-fallback-records-shared into main
Contributor

Type: fix · Risk: low · Tested on: Linux x86-64 (game-free); Steam Deck OLED, SteamOS 3.9.5, RADV (two testers' runs) · Needs: none

Why

On GPUs that draw mesh shaders through the compute fallback (by default Linux AMD cards, the Steam Deck among them), each program needing a bigger payload buffer made another 64 MB record buffer that nothing used again, so video memory went for nothing over a session.

How to reproduce

Seen on: Linux x86-64, game-free (the real fallback_buffers_of with stand-in Vulkan calls); in the game, a Steam Deck OLED (RADV, the compute fallback by default), where the leftover arenas show as about 80 to 195 MB more GPU memory than with the fix
Settings and switches: defaults (the compute mesh fallback is the default on RADV)
Steps: on main aa95d35f with this PR's test added (6e6a3fb7), run python -I -B tests/test_fallback_buffer_cleanup.py --cxx g++: two programs of different payload sizes on one thread
Expected: both use the one record arena
Actual: FAIL payload_growth_keeps_records: a bigger payload made another record arena

What changed

A mesh fallback program whose payload needs a bigger buffer now reuses the thread's 64 MB record arena instead of making another one, so video memory no longer grows by an arena for each such program.

  • vk: fallback_buffers_of() in gpu/vk/vk_draw.cpp gives a new payload buffer the newest pair's record buffer when it is big enough (it always is: every program takes the same fixed area), instead of making another; on a failure later in the function the shared buffer is not freed.
  • tests: tests/fallback_buffer_cleanup_test.cpp gets payload_growth_keeps_records (a program with bigger payloads must keep the records buffer and its address) and shared_records_payload_failure (a growth that shares the arena and then cannot make its payload, or gets no address for it, leaves the shared arena and the set before it alone; it passes on main too, where nothing is shared, and guards the fix's clean-up), run by tests/test_fallback_buffer_cleanup.py.

Measurements

Verdict: fixed: one record arena instead of two in the game-free test (two interleaved rounds); on two testers' Steam Decks about 80 MB less held besides textures (dukenheimer, a 5-minute route) and 81 and 195 MiB less GPU memory on a still view (p0lux), fps not lower.

Hardware: Linux x86-64 server (Ubuntu 24.04), no GPU or game used; gcc 13.3, clang 23.1.5
Scene: no game: the game-free check
Method: python3 -I -B tests/test_fallback_buffer_cleanup.py --cxx g++ at the test-only commit 6e6a3fb7 (main aa95d35f plus the test) and at ba2cbea0, twice each, alternating
How to reproduce: check out each commit and run the command above

Before: main @ aa95d35f (with the test, 6e6a3fb7) After: this PR @ ba2cbea0
record arenas made for 2 programs of different payload sizes (both rounds the same) 2 1
6e6a3fb7 r1: FAIL payload_growth_keeps_records: a bigger payload made another record arena
6e6a3fb7 r1: PASS shared_records_payload_failure
6e6a3fb7 r1: fallback initialization: 11 cases, 1 failed (exit 1)
ba2cbea0 r1: PASS payload_growth_keeps_records
ba2cbea0 r1: PASS shared_records_payload_failure
ba2cbea0 r1: fallback initialization: 11 cases, 0 failed (exit 0)
(round 2 the same on both commits)

In the game, two testers' Steam Deck OLED runs (RADV VANGOGH, SteamOS 3.9.5, 16 GB, the compute fallback), each against main without this PR:

  • dukenheimer, test request T-YHDU (pass), 2026-11-15 (#551 (comment)): this PR's head e8faf57e (the same change, on main 7ff5256e) against main 7ff5256e, Mesa 26.2.0-devel, Game Mode, docked, stock clocks, at that Deck's own Auto defaults (1280x720 output, 50% render resolution, the game's own upscaler, frame generation off, VRAM budget 2.2 GB). Two 5-minute runs each, interleaved, through Kokiri Forest, Hyrule Field and Kokiri again, the same inputs every run. What the renderer holds besides textures (from the vk: VRAM: lines) was lower at all three spots: a median of 1,221 MB (1,151 to 1,289) with this PR against 1,298 MB (1,283 to 1,355) on main, about 80 MB less, about one of the 64 MB arenas this PR stops leaving (the lines do not name them). The raw "used" figures move in 64 to 128 MB steps and the textures differ by up to about 320 MB between runs, so they are noisy: the means were lower with the PR at each spot (Kokiri 4,341 against 4,469 MB, the Field 4,054 against 4,278, Kokiri again 4,278 against 4,598), and one PR run was above one main run in the first area. fps 20.3 and 20.7 with it, 19.9 and 20.2 on main: not lower. The arrival pictures match in all runs, nothing missing (flicker cannot be judged from stills). No crash, device loss or fault. That Deck ran short of memory in every run (about 4 GB swapped), so its vk: memory: working set says little.
  • p0lux, 2026-11-15 (#551 (comment)): a still heavy view loaded from a save (about 2,150 draws a frame), headless; the renderer alone swapped in one game folder built from main 9e6f231d, with and without this PR and #472 together (d4c9070b, e8faf57e and 18243506 cherry-picked), on top of other open PRs that tester plays with, the same in both; two starts a build, in both orders. The GPU memory the driver counts for the game (drm-memory-gtt + drm-memory-vram of its fdinfo) at the end of a 720-present span: 4,258 against 4,177 MiB (-81) and 4,356 against 4,161 MiB (-195); fps 33.41 / 30.82 without, 33.40 / 31.16 with. The build with the change gave the same figure on both starts (16 MiB apart), the one without moved by about 100 MiB between starts (4,349 on a third start), which fits one to three 64 MB record buffers made or not. No fatal line and no GPU timeout in the kernel log on the four starts. #472 makes no buffer, so the tester reads the memory difference as this PR's, but the two were not built apart.

Flags and settings

None

Testing

Tested: Linux x86-64, game-free. The new test fails on the test-only commit 6e6a3fb7 and passes at ba2cbea0 (this branch rebased onto main aa95d35f), twice each, alternating, and under tests/run_all.py with g++ 13.3 and with clang 23.1.5 at both commits. At the tip, the 109 checks that read gpu/vk/vk_draw.cpp or the changed test: 106 passed, 1 skipped, and 2 failed that fail or are skipped by OS on main aa95d35f too (test_pipeline_tour; test_shader_module_guard, a Windows-only check run here by name). Before the rebase the same at d4c9070b and e8faf57e (main 7ff5256e). Steam Deck: dukenheimer's T-YHDU run and p0lux's still-view run, in Measurements.

Not tested: How many payload growths a session sees in this game, so how much memory it saves in general (64 MB of video memory for each growth, per recording thread). GPUs that use the fallback other than the Deck's, and Windows (where the fallback is not the default).

Must be tested: None

Risks

What could break: pairs that share a record buffer now use it from more than one program; that was already the design (one records area for every program, each draw clearing its slots behind a barrier). The pairs are never freed one by one, so no buffer is freed twice.

Turning it off: revert the commit

Compatibility: Nothing changes

Issues

None filed.

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. Onto main aa95d35f, no conflict; the test and fix commits are the same changes as before (git patch-id).
  • python -I -B tests/run_all.py passes (any failure that also fails on main is named). The full suite on main aa95d35f (Linux, g++ 13.3, the Vulkan headers set): 528 passed, 15 failed, 50 skipped; on this branch the new test and the 109 checks that read the changed files ran, with no failure that main does not have (see Testing). The 15 that fail on main: test_appimage_player_build, test_bake_portability, test_cpm_discovery, test_crash_dialog, test_env_on, test_lift_cache, test_lift_cleanup_error, test_make_game_cache, test_mods_size_table, test_options_budget_once, test_pipeline_tour, test_readback_late, test_vk_pgo, test_walk_key and nx2/test_texture_init_barrier.py.
  • 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.
  • Numbers from the same PC, scene and settings, at least 2 interleaved runs each, the median reported.
  • 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.
  • Host code builds on both Windows (llvm-mingw) and Linux, with UTF-8 paths. Not built whole after the rebase; gpu/vk/vk_draw.cpp at ba2cbea0 checked whole (-fsyntax-only -Wall -Wextra, the build's defines) with clang 23.1.5 for Linux and llvm-mingw 20261104 for Windows: the same diagnostics as main aa95d35f's (102 and 103), none new; on Linux both stop at the same narrowing error in a line this PR does not touch. Before the rebase, the combined branch 27553c83 linked longshot_vk.dll (llvm-mingw 20261104, RX_VK_ONLY=1 RX_RELEASE=1 RX_TARGET=windows) and longshot_vk.so.
**Type:** fix · **Risk:** low · **Tested on:** Linux x86-64 (game-free); Steam Deck OLED, SteamOS 3.9.5, RADV (two testers' runs) · **Needs:** none ## Why On GPUs that draw mesh shaders through the compute fallback (by default Linux AMD cards, the Steam Deck among them), each program needing a bigger payload buffer made another 64 MB record buffer that nothing used again, so video memory went for nothing over a session. ## How to reproduce **Seen on:** Linux x86-64, game-free (the real `fallback_buffers_of` with stand-in Vulkan calls); in the game, a Steam Deck OLED (RADV, the compute fallback by default), where the leftover arenas show as about 80 to 195 MB more GPU memory than with the fix **Settings and switches:** defaults (the compute mesh fallback is the default on RADV) **Steps:** on `main` aa95d35f with this PR's test added (6e6a3fb7), run `python -I -B tests/test_fallback_buffer_cleanup.py --cxx g++`: two programs of different payload sizes on one thread **Expected:** both use the one record arena **Actual:** `FAIL payload_growth_keeps_records: a bigger payload made another record arena` ## What changed A mesh fallback program whose payload needs a bigger buffer now reuses the thread's 64 MB record arena instead of making another one, so video memory no longer grows by an arena for each such program. - vk: `fallback_buffers_of()` in `gpu/vk/vk_draw.cpp` gives a new payload buffer the newest pair's record buffer when it is big enough (it always is: every program takes the same fixed area), instead of making another; on a failure later in the function the shared buffer is not freed. - tests: `tests/fallback_buffer_cleanup_test.cpp` gets `payload_growth_keeps_records` (a program with bigger payloads must keep the records buffer and its address) and `shared_records_payload_failure` (a growth that shares the arena and then cannot make its payload, or gets no address for it, leaves the shared arena and the set before it alone; it passes on main too, where nothing is shared, and guards the fix's clean-up), run by `tests/test_fallback_buffer_cleanup.py`. ## Measurements **Verdict:** fixed: one record arena instead of two in the game-free test (two interleaved rounds); on two testers' Steam Decks about 80 MB less held besides textures (dukenheimer, a 5-minute route) and 81 and 195 MiB less GPU memory on a still view (p0lux), fps not lower. Hardware: Linux x86-64 server (Ubuntu 24.04), no GPU or game used; gcc 13.3, clang 23.1.5 Scene: no game: the game-free check Method: `python3 -I -B tests/test_fallback_buffer_cleanup.py --cxx g++` at the test-only commit 6e6a3fb7 (main aa95d35f plus the test) and at ba2cbea0, twice each, alternating How to reproduce: check out each commit and run the command above | | Before: main @ aa95d35f (with the test, 6e6a3fb7) | After: this PR @ ba2cbea0 | |---|---|---| | record arenas made for 2 programs of different payload sizes (both rounds the same) | 2 | 1 | ``` 6e6a3fb7 r1: FAIL payload_growth_keeps_records: a bigger payload made another record arena 6e6a3fb7 r1: PASS shared_records_payload_failure 6e6a3fb7 r1: fallback initialization: 11 cases, 1 failed (exit 1) ba2cbea0 r1: PASS payload_growth_keeps_records ba2cbea0 r1: PASS shared_records_payload_failure ba2cbea0 r1: fallback initialization: 11 cases, 0 failed (exit 0) (round 2 the same on both commits) ``` In the game, two testers' Steam Deck OLED runs (RADV VANGOGH, SteamOS 3.9.5, 16 GB, the compute fallback), each against main without this PR: - **dukenheimer, test request T-YHDU (pass)**, 2026-11-15 (https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/551#issuecomment-21282): this PR's head e8faf57e (the same change, on main 7ff5256e) against main 7ff5256e, Mesa 26.2.0-devel, Game Mode, docked, stock clocks, at that Deck's own Auto defaults (1280x720 output, 50% render resolution, the game's own upscaler, frame generation off, VRAM budget 2.2 GB). Two 5-minute runs each, interleaved, through Kokiri Forest, Hyrule Field and Kokiri again, the same inputs every run. What the renderer holds besides textures (from the `vk: VRAM:` lines) was lower at all three spots: a median of 1,221 MB (1,151 to 1,289) with this PR against 1,298 MB (1,283 to 1,355) on main, about 80 MB less, about one of the 64 MB arenas this PR stops leaving (the lines do not name them). The raw "used" figures move in 64 to 128 MB steps and the textures differ by up to about 320 MB between runs, so they are noisy: the means were lower with the PR at each spot (Kokiri 4,341 against 4,469 MB, the Field 4,054 against 4,278, Kokiri again 4,278 against 4,598), and one PR run was above one main run in the first area. fps 20.3 and 20.7 with it, 19.9 and 20.2 on main: not lower. The arrival pictures match in all runs, nothing missing (flicker cannot be judged from stills). No crash, device loss or fault. That Deck ran short of memory in every run (about 4 GB swapped), so its `vk: memory:` working set says little. - **p0lux**, 2026-11-15 (https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/551#issuecomment-24165): a still heavy view loaded from a save (about 2,150 draws a frame), headless; the renderer alone swapped in one game folder built from main 9e6f231d, with and without this PR and https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/472 together (d4c9070b, e8faf57e and 18243506 cherry-picked), on top of other open PRs that tester plays with, the same in both; two starts a build, in both orders. The GPU memory the driver counts for the game (`drm-memory-gtt` + `drm-memory-vram` of its fdinfo) at the end of a 720-present span: 4,258 against 4,177 MiB (-81) and 4,356 against 4,161 MiB (-195); fps 33.41 / 30.82 without, 33.40 / 31.16 with. The build with the change gave the same figure on both starts (16 MiB apart), the one without moved by about 100 MiB between starts (4,349 on a third start), which fits one to three 64 MB record buffers made or not. No fatal line and no GPU timeout in the kernel log on the four starts. #472 makes no buffer, so the tester reads the memory difference as this PR's, but the two were not built apart. ### Flags and settings None ## Testing **Tested:** Linux x86-64, game-free. The new test fails on the test-only commit 6e6a3fb7 and passes at ba2cbea0 (this branch rebased onto `main` aa95d35f), twice each, alternating, and under `tests/run_all.py` with g++ 13.3 and with clang 23.1.5 at both commits. At the tip, the 109 checks that read `gpu/vk/vk_draw.cpp` or the changed test: 106 passed, 1 skipped, and 2 failed that fail or are skipped by OS on `main` aa95d35f too (`test_pipeline_tour`; `test_shader_module_guard`, a Windows-only check run here by name). Before the rebase the same at d4c9070b and e8faf57e (main 7ff5256e). Steam Deck: dukenheimer's T-YHDU run and p0lux's still-view run, in Measurements. **Not tested:** How many payload growths a session sees in this game, so how much memory it saves in general (64 MB of video memory for each growth, per recording thread). GPUs that use the fallback other than the Deck's, and Windows (where the fallback is not the default). **Must be tested:** None ## Risks **What could break:** pairs that share a record buffer now use it from more than one program; that was already the design (one records area for every program, each draw clearing its slots behind a barrier). The pairs are never freed one by one, so no buffer is freed twice. **Turning it off:** revert the commit **Compatibility:** Nothing changes ## Issues None filed. ## 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`. Onto main aa95d35f, no conflict; the test and fix commits are the same changes as before (`git patch-id`). - [x] `python -I -B tests/run_all.py` passes (any failure that also fails on `main` is named). The full suite on main aa95d35f (Linux, g++ 13.3, the Vulkan headers set): 528 passed, 15 failed, 50 skipped; on this branch the new test and the 109 checks that read the changed files ran, with no failure that `main` does not have (see Testing). The 15 that fail on main: `test_appimage_player_build`, `test_bake_portability`, `test_cpm_discovery`, `test_crash_dialog`, `test_env_on`, `test_lift_cache`, `test_lift_cleanup_error`, `test_make_game_cache`, `test_mods_size_table`, `test_options_budget_once`, `test_pipeline_tour`, `test_readback_late`, `test_vk_pgo`, `test_walk_key` and `nx2/test_texture_init_barrier.py`. - [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] Numbers from the same PC, scene and settings, at least 2 interleaved runs each, the median reported. - [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. - [x] Host code builds on both Windows (llvm-mingw) and Linux, with UTF-8 paths. Not built whole after the rebase; `gpu/vk/vk_draw.cpp` at ba2cbea0 checked whole (`-fsyntax-only -Wall -Wextra`, the build's defines) with clang 23.1.5 for Linux and llvm-mingw 20261104 for Windows: the same diagnostics as `main` aa95d35f's (102 and 103), none new; on Linux both stop at the same narrowing error in a line this PR does not touch. Before the rebase, the combined branch 27553c83 linked `longshot_vk.dll` (llvm-mingw 20261104, `RX_VK_ONLY=1 RX_RELEASE=1 RX_TARGET=windows`) and `longshot_vk.so`.
Assisted-by: Claude
vk: a mesh fallback payload that grows keeps the thread's record arena
Some checks failed
beanstalk/approval Test farm not requested
Website / Website on Cloudflare (pull_request_target) Has been skipped
PR description / Description follows the template (pull_request_target) Successful in 5s
CI / Conventional Commit title (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been cancelled
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been cancelled
CI / Workflow lint (actionlint) (pull_request) Has been cancelled
Third-party parts / As their notes say (pull_request) Has been cancelled
Third-party parts / The same as upstream (pull_request) Has been cancelled
e8faf57e94
Assisted-by: Claude
Author
Contributor

Filled in: the full game-free suite on the combined branch, the Windows and Linux builds, and the test request T-YHDU. Still work in progress until a Steam Deck run is in.

Filled in: the full game-free suite on the combined branch, the Windows and Linux builds, and the test request T-YHDU. Still work in progress until a Steam Deck run is in.
Contributor

Test request T-YHDU: pass

Built from this PR's head e8faf57e (on main 7ff5256e); the comparison is main 7ff5256e. Setup and method below.

Result

run build fps: Kokiri / Field / Kokiri again vk: VRAM: used, MB, at each area's last line of it held besides textures, MB
1 main 20.3 / 19.5 / 19.9 4,277 / 4,278 / 4,790 1,339 / 1,286 / 1,285
2 main + #551 19.9 / 21.2 / 19.8 4,405 / 4,086 / 4,278 1,182 / 1,289 / 1,218
5 main + #551 20.3 / 20.5 / 22.2 4,277 / 4,022 / 4,278 1,151 / 1,224 / 1,225
6 main 19.3 / 20.6 / 22.0 4,661 / 4,278 / 4,406 1,283 / 1,311 / 1,355

"Held besides textures" is from the same line: used, minus the free space in its blocks, minus the textures.

  • VRAM. The raw "used" figures move in 64-128 MB block steps, and the textures (2.2 to 2.6 GB) differ by up to ~320 MB between
    runs at the same spot, so the lines are noisy. At the same spots the means are lower with this PR:

    • Kokiri: 4,341 MB with it, 4,469 without;
    • the Field: 4,054 against 4,278;
    • Kokiri again: 4,278 against 4,598.

    In the first Kokiri area one run with the PR (4,405) is above one run of main (4,277) and below the other (4,661). What the renderer
    holds besides textures is lower at all three spots: a median of 1,221 MB (1,151 to 1,289) with this PR against 1,298 MB (1,283 to
    1,355) on main, about 80 MB less. That is about one of the 64 MB arenas this PR stops leaving, though these lines don't name them.

  • fps: 20.3 and 20.7 over the whole 5 minutes with this PR, 19.9 and 20.2 on main. Not lower.

  • Picture: the arrival pictures (Kokiri, the Field, Kokiri again) match across all six runs, the combined build's included. Nothing
    is missing; they differ only in Navi's place and in when the area title or the "Saving..." icon showed. Flicker can't be judged from
    stills, but nothing was missing in any.

  • Faults: none in the six runs (no crash, device lost or device fault, no stalled GPU). The kernel's amdgpu lines were only the
    display's "Losing delta precision while programming shaper LUT" notices, 6 a start, in every run.

  • Memory: at these settings this Deck ran short of memory in every run, with about 4 GB swapped and MemAvailable down to 280-880 MB.
    So the vk: memory: working set below swings with swapping and says little.

The last `vk: VRAM:` and `vk: memory:` lines of each run
run 1, main
vk: VRAM: 4790 MB used of 6013 MB allowed (1075 MB of it free in the blocks); textures 2430 MB (budget 2560 MB), 957 textures
vk: memory: working set 2670 MB (peak 9782), private 505 MB, staging 64 MB in 1 arenas
run 2, main + #551
vk: VRAM: 4278 MB used of 5729 MB allowed (696 MB of it free in the blocks); textures 2364 MB (budget 2560 MB), 915 textures
vk: memory: working set 2732 MB (peak 6978), private 436 MB, staging 64 MB in 1 arenas
run 5, main + #551
vk: VRAM: 4278 MB used of 5818 MB allowed (766 MB of it free in the blocks); textures 2287 MB (budget 2560 MB), 885 textures
vk: memory: working set 2791 MB (peak 8763), private 501 MB, staging 64 MB in 1 arenas
run 6, main
vk: VRAM: 4406 MB used of 5821 MB allowed (664 MB of it free in the blocks); textures 2387 MB (budget 2560 MB), 904 textures
vk: memory: working set 3062 MB (peak 10042), private 587 MB, staging 64 MB in 1 arenas

Setup

  • Steam Deck OLED: AMD Custom APU 0932 (RADV VANGOGH), 16 GB; Mesa 26.2.0-devel git-5c65d4fc31; SteamOS 3.9.5 (build 20261023.100),
    kernel 7.2.7-valve2. Game Mode, docked, stock clocks.
  • Builds: main 7ff5256e; main + this PR alone (the renderer built from the PR's head); and a combined build of main + #550 to #558,
    merged in order, all clean. All built for x86-64-v3 with the release play profile and LLVM 23.1.5. One test folder (warm caches) with
    the binaries swapped; the shader caches' stamp is the same for all three.
  • Settings: main's own defaults on this Deck, the options file its first start wrote. Quality preset Auto (this PC), output
    1280x720, Render resolution 50% (640x360), the game's own upscaler, frame generation off, VRAM budget 2.2 GB.
  • The same 5 minutes each run, through the control bridge: Continue into Kokiri Forest, 110 s there, the debug teleport to
    HyruleField_Child (the Lost Woods bridge), 110 s, the teleport back to KokiriForest_Child, 50 s.
    • Link stood at each arrival point while the camera turned round, one way then the other: the same inputs every run. Walking set
      off events that blocked the teleports.
    • The game autosaves at each arrival, so every run continued from the same Kokiri arrival point.
  • Measured: fps is the bridge's status every 5 s (the game's frames over the last second), averaged per area. A picture at each
    arrival.
  • Order: main, main + #551, combined, combined, main + #551, main.

The arrival pictures, all six runs (Kokiri, the Field, Kokiri again):

arrival pictures

Test request T-YHDU: pass Built from this PR's head e8faf57e (on main 7ff5256e); the comparison is main 7ff5256e. Setup and method below. **Result** | run | build | fps: Kokiri / Field / Kokiri again | `vk: VRAM:` used, MB, at each area's last line | of it held besides textures, MB | |---|---|---|---|---| | 1 | main | 20.3 / 19.5 / 19.9 | 4,277 / 4,278 / 4,790 | 1,339 / 1,286 / 1,285 | | 2 | main + #551 | 19.9 / 21.2 / 19.8 | 4,405 / 4,086 / 4,278 | 1,182 / 1,289 / 1,218 | | 5 | main + #551 | 20.3 / 20.5 / 22.2 | 4,277 / 4,022 / 4,278 | 1,151 / 1,224 / 1,225 | | 6 | main | 19.3 / 20.6 / 22.0 | 4,661 / 4,278 / 4,406 | 1,283 / 1,311 / 1,355 | "Held besides textures" is from the same line: used, minus the free space in its blocks, minus the textures. - **VRAM.** The raw "used" figures move in 64-128 MB block steps, and the textures (2.2 to 2.6 GB) differ by up to ~320 MB between runs at the same spot, so the lines are noisy. At the same spots the means are lower with this PR: - Kokiri: 4,341 MB with it, 4,469 without; - the Field: 4,054 against 4,278; - Kokiri again: 4,278 against 4,598. In the first Kokiri area one run with the PR (4,405) is above one run of main (4,277) and below the other (4,661). What the renderer holds besides textures is lower at all three spots: a median of 1,221 MB (1,151 to 1,289) with this PR against 1,298 MB (1,283 to 1,355) on main, about 80 MB less. That is about one of the 64 MB arenas this PR stops leaving, though these lines don't name them. - **fps:** 20.3 and 20.7 over the whole 5 minutes with this PR, 19.9 and 20.2 on main. Not lower. - **Picture:** the arrival pictures (Kokiri, the Field, Kokiri again) match across all six runs, the combined build's included. Nothing is missing; they differ only in Navi's place and in when the area title or the "Saving..." icon showed. Flicker can't be judged from stills, but nothing was missing in any. - **Faults:** none in the six runs (no crash, device lost or device fault, no stalled GPU). The kernel's amdgpu lines were only the display's "Losing delta precision while programming shaper LUT" notices, 6 a start, in every run. - **Memory:** at these settings this Deck ran short of memory in every run, with about 4 GB swapped and MemAvailable down to 280-880 MB. So the `vk: memory:` working set below swings with swapping and says little. <details><summary>The last `vk: VRAM:` and `vk: memory:` lines of each run</summary> ``` run 1, main vk: VRAM: 4790 MB used of 6013 MB allowed (1075 MB of it free in the blocks); textures 2430 MB (budget 2560 MB), 957 textures vk: memory: working set 2670 MB (peak 9782), private 505 MB, staging 64 MB in 1 arenas run 2, main + #551 vk: VRAM: 4278 MB used of 5729 MB allowed (696 MB of it free in the blocks); textures 2364 MB (budget 2560 MB), 915 textures vk: memory: working set 2732 MB (peak 6978), private 436 MB, staging 64 MB in 1 arenas run 5, main + #551 vk: VRAM: 4278 MB used of 5818 MB allowed (766 MB of it free in the blocks); textures 2287 MB (budget 2560 MB), 885 textures vk: memory: working set 2791 MB (peak 8763), private 501 MB, staging 64 MB in 1 arenas run 6, main vk: VRAM: 4406 MB used of 5821 MB allowed (664 MB of it free in the blocks); textures 2387 MB (budget 2560 MB), 904 textures vk: memory: working set 3062 MB (peak 10042), private 587 MB, staging 64 MB in 1 arenas ``` </details> **Setup** - Steam Deck OLED: AMD Custom APU 0932 (RADV VANGOGH), 16 GB; Mesa 26.2.0-devel git-5c65d4fc31; SteamOS 3.9.5 (build 20261023.100), kernel 7.2.7-valve2. Game Mode, docked, stock clocks. - **Builds:** main 7ff5256e; main + this PR alone (the renderer built from the PR's head); and a combined build of main + #550 to #558, merged in order, all clean. All built for x86-64-v3 with the release play profile and LLVM 23.1.5. One test folder (warm caches) with the binaries swapped; the shader caches' stamp is the same for all three. - **Settings:** main's own defaults on this Deck, the options file its first start wrote. Quality preset Auto (this PC), output 1280x720, Render resolution 50% (640x360), the game's own upscaler, frame generation off, VRAM budget 2.2 GB. - **The same 5 minutes each run, through the control bridge:** Continue into Kokiri Forest, 110 s there, the debug teleport to HyruleField_Child (the Lost Woods bridge), 110 s, the teleport back to KokiriForest_Child, 50 s. - Link stood at each arrival point while the camera turned round, one way then the other: the same inputs every run. Walking set off events that blocked the teleports. - The game autosaves at each arrival, so every run continued from the same Kokiri arrival point. - **Measured:** fps is the bridge's status every 5 s (the game's frames over the last second), averaged per area. A picture at each arrival. - **Order:** main, main + #551, combined, combined, main + #551, main. The arrival pictures, all six runs (Kokiri, the Field, Kokiri again): ![arrival pictures](https://git.magicbean.dev/attachments/275042ba-a9a6-49f5-97dd-32d61bf6bc62)
Author
Contributor

Thank you for the Deck run, dukenheimer: your result is in the description as you reported it, including its limits. Marking this ready for review.

Thank you for the Deck run, dukenheimer: your result is in the description as you reported it, including its limits. Marking this ready for review.
zeldaootr changed title from WIP: fix(vk): a mesh fallback program with bigger payloads reuses the record arena to fix(vk): a mesh fallback program with bigger payloads reuses the record arena 2026-11-15 00:25:10 +00:00
Contributor

A second Steam Deck run, on a still view, where the driver's own count shows the saving.

Setup: Steam Deck OLED (RADV VANGOGH, SteamOS 3.9.5, 16 GB), the compute fallback, headless. A still heavy view (about 2,150 draws a frame) loaded from a save; memory read at the end of a 720-present span on the settled view. The two builds are the renderer alone, swapped in one game folder built from main 9e6f231d.

before with #551 and #472
GPU memory the driver counts for the game (drm-memory-gtt + drm-memory-vram of its fdinfo), pair 1 4,258 MiB 4,177 MiB (-81)
the same, pair 2 (other order) 4,356 MiB 4,161 MiB (-195)
fps 33.41 / 30.82 33.40 / 31.16

The build with the change gives the same figure on both starts (16 MiB apart). The one without moves by about 100 MiB from one start to the next (4,258 and 4,356 here, 4,349 on a start this morning), which fits one to three 64 MB record buffers made or not, depending on the start. No fatal line and no GPU timeout in the kernel log on the four starts.

Limits: the two builds differ by this PR and #472 together (d4c9070b, e8faf57e and 18243506 cherry-picked), on top of main 9e6f231d plus the open PRs I play with (#223, #384, #387, #391, #567, #568, #590 and a local change), the same in both. #472 makes no buffer, so I read the memory difference as this PR's, but the two were not built apart. Two starts a build.

A second Steam Deck run, on a still view, where the driver's own count shows the saving. **Setup:** Steam Deck OLED (RADV VANGOGH, SteamOS 3.9.5, 16 GB), the compute fallback, headless. A still heavy view (about 2,150 draws a frame) loaded from a save; memory read at the end of a 720-present span on the settled view. The two builds are the renderer alone, swapped in one game folder built from main 9e6f231d. | | before | with #551 and #472 | |---|---|---| | GPU memory the driver counts for the game (`drm-memory-gtt` + `drm-memory-vram` of its fdinfo), pair 1 | 4,258 MiB | 4,177 MiB (-81) | | the same, pair 2 (other order) | 4,356 MiB | 4,161 MiB (-195) | | fps | 33.41 / 30.82 | 33.40 / 31.16 | The build with the change gives the same figure on both starts (16 MiB apart). The one without moves by about 100 MiB from one start to the next (4,258 and 4,356 here, 4,349 on a start this morning), which fits one to three 64 MB record buffers made or not, depending on the start. No fatal line and no GPU timeout in the kernel log on the four starts. **Limits:** the two builds differ by this PR and #472 together (d4c9070b, e8faf57e and 18243506 cherry-picked), on top of main 9e6f231d plus the open PRs I play with (#223, #384, #387, #391, #567, #568, #590 and a local change), the same in both. #472 makes no buffer, so I read the memory difference as this PR's, but the two were not built apart. Two starts a build.
Author
Contributor

Thank you, p0lux, for the still-view Deck run: it is in the description as you reported it (81 and 195 MiB less GPU memory, fps not lower, built together with #472, which makes no buffer), beside dukenheimer's T-YHDU run. Rebased onto main aa95d35f with no conflict (the same two changes, git patch-id) and the description moved to the current template.
The test was run again on the new base (two arenas at the test-only commit, one at the tip, two rounds, g++ and clang); both Deck runs still hold: main has not changed fallback_buffers_of() since 7ff5256e, and since p0lux's base 9e6f231d only #761 (Arc cards' occlusion copy) and #742 (an agents skill) landed.

Thank you, p0lux, for the still-view Deck run: it is in the description as you reported it (81 and 195 MiB less GPU memory, fps not lower, built together with #472, which makes no buffer), beside dukenheimer's T-YHDU run. Rebased onto `main` aa95d35f with no conflict (the same two changes, `git patch-id`) and the description moved to the current template. The test was run again on the new base (two arenas at the test-only commit, one at the tip, two rounds, g++ and clang); both Deck runs still hold: `main` has not changed `fallback_buffers_of()` since 7ff5256e, and since p0lux's base 9e6f231d only #761 (Arc cards' occlusion copy) and #742 (an agents skill) landed.
zeldaootr force-pushed mesh-fallback-records-shared from e8faf57e94
Some checks failed
beanstalk/approval Test farm not requested
Website / Website on Cloudflare (pull_request_target) Has been skipped
PR description / Description follows the template (pull_request_target) Successful in 5s
CI / Conventional Commit title (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 1/2) (pull_request) Has been cancelled
CI / Python source checks (ubuntu-24.04, part 2/2) (pull_request) Has been cancelled
CI / SPIR-V fixtures (global narrow load/store, direct surface atomics, F2I immediate) (pull_request) Has been cancelled
CI / Workflow lint (actionlint) (pull_request) Has been cancelled
Third-party parts / As their notes say (pull_request) Has been cancelled
Third-party parts / The same as upstream (pull_request) Has been cancelled
to ba2cbea046
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
Website / Website on Cloudflare (pull_request) Blocked by required conditions
PR description / Description follows the template (pull_request_target) Successful in 4s
2026-11-15 16:43:45 +00:00
Compare
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
Website / Website on Cloudflare (pull_request) Blocked by required conditions
PR description / Description follows the template (pull_request_target) Successful in 4s
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 'mesh-fallback-records-shared:zeldaootr-mesh-fallback-records-shared'
git switch 'zeldaootr-mesh-fallback-records-shared'
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
3 participants
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!551
No description provided.