fix(vk): RX_VK_PASS_TIMING names the mesh fallback's compute and the indirect mesh argument conversion #864

Open
zeldaootr wants to merge 2 commits from zeldaootr/Longshot:pass-timing-names-fallback into main
Contributor

Type: fix · Risk: low · Tested on: Linux, Steam Deck (RADV VANGOGH), the labels in a profile run; the game-free checks on Linux · Needs: none

Why

On a GPU that runs task and mesh programs as compute shaders (the mesh fallback: every Steam Deck by default, Linux AMD, cards without mesh shaders), RX_VK_PASS_TIMING did not time the fallback's work before each of its draws, nor the copy of an indirect mesh draw's arguments. That GPU time showed only as unnamed time between the spans, and its barriers as barrier (other): on a Steam Deck in Hyrule Field we reported it as 9.8 ms of gaps between command buffers and aimed work at the wrong thing. Named, it is the fallback (4.2 ms a frame in the profile below).

How to reproduce

Seen on: Steam Deck, SteamOS, RADV VANGOGH (Mesa)
Settings and switches: defaults (Automatic mesh shaders: the compute path on Linux AMD), RX_VK_PASS_TIMING=2
Steps: stand in Hyrule Field for 600 presents and read the GPU pass timing block in longshot_log.txt
Expected: the fallback's fills, barriers and compute dispatches, and the indirect mesh argument copies, each under a kind of their own in by kind
Actual: neither appears: their time is counted in ms between them: glue the spans do not name, and the fallback's full barriers as barrier (other)

What changed

Two spans for RX_VK_PASS_TIMING. The work fallback_record puts before each fallback draw is one span labelled fallback prog <key> (kind fallback), and mesh_indirect_convert's copies and barriers one labelled meshconv. Each opens right after end_pass, which closes the pass's own span, so no pass loses its timing. Log text only: nothing changes with the switch off.

  • vk: fallback_record and mesh_indirect_convert in gpu/vk/vk_draw.cpp open a GprofSpan (gpu/vk/vk_gprof.h) after end_pass
  • docs: RX_VK_PASS_TIMING's row in docs/development.md names the two kinds; vk_gprof.h's header says which work they hold
  • tests: tests/test_pass_timing_fallback.py checks that both spans exist, open after end_pass and before the first command they cover, and are documented. It fails on main

Measurements

Verdict: nothing to measure: the change adds two labels to an opt-in diagnostic (RX_VK_PASS_TIMING) and does nothing with the switch off. With it on, the spans add two timestamps per fallback draw and per indirect mesh draw, as every other labelled span does.

Flags and settings

None: RX_VK_PASS_TIMING is unchanged as a switch; its report names two more kinds.

Testing

Tested:

  • The labels in the game: a Steam Deck (SteamOS, AMD Custom GPU 0932, RADV VANGOGH), 1280x800, Hyrule Field, RX_VK_PASS_TIMING=2, on 2026-11-14, from a build with this change (the same patch, with the span as a local struct rather than GprofSpan) and the narrow-barrier work beside it, switched off. The fallback's time is named, and only 0.37 ms a frame is left between spans:
vk:   recordings' command buffers: 28.36 ms from the first timestamp to the last in 10.5 a frame (27.99 ms in spans, 0.37 ms between them: glue the spans do not name)
vk:     m fallback    4.174 ms  14.7%     24.0 spans      24.0 items     0.00 MB    173.6 us a span
vk:     m meshconv    0.260 ms   0.9%     20.0 spans      20.0 items     0.00 MB     13.0 us a span
vk:   m   1.427 ms     0.5 x   2952.7 us       0.5 items    0.00 MB  fallback prog 43ec86f35fd937b9
  • The game-free checks on Linux, with g++ and with clang: tests/test_pass_timing_fallback.py fails at the test's commit on main and passes here. The 120 checks that read vk_draw.cpp, vk_gprof.h or docs/development.md, through tests/run_all.py, give the same results as on main @ aa95d35f: 7 fail on both on this PC (test_bake_portability, test_crash_dialog, test_make_game_cache, test_pipeline_tour, test_shader_module_guard, test_vk_pgo, test_walk_key), and test_pipeline_cache_save fails now and then on both, a timed wait.
  • gpu/vk/vk_draw.cpp with -fsyntax-only -Wall -Wextra for Linux (clang) and Windows (llvm-mingw): the same diagnostics as on main.

Not tested: the full tests/run_all.py (this PC was shared and loaded); this exact commit in the game: the build that showed the labels had the earlier form of the same span.

Must be tested:

  • None: with RX_VK_PASS_TIMING off nothing is recorded differently, and with it on the labels were seen on a Steam Deck.

Risks

What could break: with RX_VK_PASS_TIMING on, a pass that a fallback draw or meshconv ends is timed as before, as the spans open after end_pass; nothing changes with it off.

Turning it off: leave RX_VK_PASS_TIMING unset (the default), or revert the commit.

Compatibility: Nothing changes.

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 94abdd57 (head 26cabcbe) with no conflict, with the commit subjects made Conventional Commits, which CI's lint job now checks for every commit, on a base that has CI's config (#417); each commit's change is the same as before by git patch-id. The commits named in this description are from before this rebase: 02de4b8b is now b4768a56, f4e53b0a is now 26cabcbe. Re-run on 94abdd57: test_pass_timing_fallback fails at the test-only commit b4768a56 and passes at the head, with g++ 13.3 and clang 23.1.5; of the 123 checks that are this PR's or read its files (g++ 13.3), 115 pass, 1 skips (a tool this PC lacks), the 6 that fail fail on main 94abdd57 too (test_crash_dialog, test_pipeline_tour, test_shader_module_guard, test_vk_occlusion_queries, test_vk_pgo, test_walk_key), and test_pipeline_cache_save failed once in that loaded run (a timed wait) and passed twice alone at the head and on main.
  • python -I -B tests/run_all.py passes (any failure that also fails on main is named). 526 passed, 18 failed, 50 skipped on Linux with g++. 15 of the failures also fail on main on this PC: 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_options_budget_once, test_pipeline_tour, test_readback_late, test_vk_pgo, test_walk_key, nx2/test_texture_init_barrier and test_mods_size_table. The other three (test_pipeline_cache_save, test_appimage_package_retry, test_oot_state_tap) failed in the full run on a busy PC and pass when run alone, 2 of 2; none reads a changed file.
  • 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.
  • Switches documented (docs/development.md; the README for a menu row) and shipped at their recommended value.
  • A game-free test added for the fix, failing on main and passing here.
  • Host code builds on both Windows (llvm-mingw) and Linux, with UTF-8 paths.
  • Docs updated.
**Type:** fix · **Risk:** low · **Tested on:** Linux, Steam Deck (RADV VANGOGH), the labels in a profile run; the game-free checks on Linux · **Needs:** none ## Why On a GPU that runs task and mesh programs as compute shaders (the mesh fallback: every Steam Deck by default, Linux AMD, cards without mesh shaders), `RX_VK_PASS_TIMING` did not time the fallback's work before each of its draws, nor the copy of an indirect mesh draw's arguments. That GPU time showed only as unnamed time between the spans, and its barriers as `barrier (other)`: on a Steam Deck in Hyrule Field we reported it as 9.8 ms of gaps between command buffers and aimed work at the wrong thing. Named, it is the fallback (4.2 ms a frame in the profile below). ## How to reproduce **Seen on:** Steam Deck, SteamOS, RADV VANGOGH (Mesa) **Settings and switches:** defaults (Automatic mesh shaders: the compute path on Linux AMD), `RX_VK_PASS_TIMING=2` **Steps:** stand in Hyrule Field for 600 presents and read the `GPU pass timing` block in `longshot_log.txt` **Expected:** the fallback's fills, barriers and compute dispatches, and the indirect mesh argument copies, each under a kind of their own in `by kind` **Actual:** neither appears: their time is counted in `ms between them: glue the spans do not name`, and the fallback's full barriers as `barrier (other)` ## What changed Two spans for `RX_VK_PASS_TIMING`. The work `fallback_record` puts before each fallback draw is one span labelled `fallback prog <key>` (kind `fallback`), and `mesh_indirect_convert`'s copies and barriers one labelled `meshconv`. Each opens right after `end_pass`, which closes the pass's own span, so no pass loses its timing. Log text only: nothing changes with the switch off. - vk: `fallback_record` and `mesh_indirect_convert` in `gpu/vk/vk_draw.cpp` open a `GprofSpan` (`gpu/vk/vk_gprof.h`) after `end_pass` - docs: `RX_VK_PASS_TIMING`'s row in `docs/development.md` names the two kinds; `vk_gprof.h`'s header says which work they hold - tests: `tests/test_pass_timing_fallback.py` checks that both spans exist, open after `end_pass` and before the first command they cover, and are documented. It fails on `main` ## Measurements **Verdict:** nothing to measure: the change adds two labels to an opt-in diagnostic (`RX_VK_PASS_TIMING`) and does nothing with the switch off. With it on, the spans add two timestamps per fallback draw and per indirect mesh draw, as every other labelled span does. ### Flags and settings None: `RX_VK_PASS_TIMING` is unchanged as a switch; its report names two more kinds. ## Testing **Tested:** - The labels in the game: a Steam Deck (SteamOS, AMD Custom GPU 0932, RADV VANGOGH), 1280x800, Hyrule Field, `RX_VK_PASS_TIMING=2`, on 2026-11-14, from a build with this change (the same patch, with the span as a local struct rather than `GprofSpan`) and the narrow-barrier work beside it, switched off. The fallback's time is named, and only 0.37 ms a frame is left between spans: ``` vk: recordings' command buffers: 28.36 ms from the first timestamp to the last in 10.5 a frame (27.99 ms in spans, 0.37 ms between them: glue the spans do not name) vk: m fallback 4.174 ms 14.7% 24.0 spans 24.0 items 0.00 MB 173.6 us a span vk: m meshconv 0.260 ms 0.9% 20.0 spans 20.0 items 0.00 MB 13.0 us a span vk: m 1.427 ms 0.5 x 2952.7 us 0.5 items 0.00 MB fallback prog 43ec86f35fd937b9 ``` - The game-free checks on Linux, with g++ and with clang: `tests/test_pass_timing_fallback.py` fails at the test's commit on `main` and passes here. The 120 checks that read `vk_draw.cpp`, `vk_gprof.h` or `docs/development.md`, through `tests/run_all.py`, give the same results as on `main` @ aa95d35f: 7 fail on both on this PC (`test_bake_portability`, `test_crash_dialog`, `test_make_game_cache`, `test_pipeline_tour`, `test_shader_module_guard`, `test_vk_pgo`, `test_walk_key`), and `test_pipeline_cache_save` fails now and then on both, a timed wait. - `gpu/vk/vk_draw.cpp` with `-fsyntax-only -Wall -Wextra` for Linux (clang) and Windows (llvm-mingw): the same diagnostics as on `main`. **Not tested:** the full `tests/run_all.py` (this PC was shared and loaded); this exact commit in the game: the build that showed the labels had the earlier form of the same span. **Must be tested:** - None: with `RX_VK_PASS_TIMING` off nothing is recorded differently, and with it on the labels were seen on a Steam Deck. ## Risks **What could break:** with `RX_VK_PASS_TIMING` on, a pass that a fallback draw or `meshconv` ends is timed as before, as the spans open after `end_pass`; nothing changes with it off. **Turning it off:** leave `RX_VK_PASS_TIMING` unset (the default), or revert the commit. **Compatibility:** Nothing changes. ## 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 94abdd57 (head 26cabcbe) with no conflict, with the commit subjects made Conventional Commits, which CI's lint job now checks for every commit, on a base that has CI's config (https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/417); each commit's change is the same as before by `git patch-id`. The commits named in this description are from before this rebase: 02de4b8b is now b4768a56, f4e53b0a is now 26cabcbe. Re-run on 94abdd57: `test_pass_timing_fallback` fails at the test-only commit b4768a56 and passes at the head, with g++ 13.3 and clang 23.1.5; of the 123 checks that are this PR's or read its files (g++ 13.3), 115 pass, 1 skips (a tool this PC lacks), the 6 that fail fail on main 94abdd57 too (`test_crash_dialog`, `test_pipeline_tour`, `test_shader_module_guard`, `test_vk_occlusion_queries`, `test_vk_pgo`, `test_walk_key`), and `test_pipeline_cache_save` failed once in that loaded run (a timed wait) and passed twice alone at the head and on main. - [x] `python -I -B tests/run_all.py` passes (any failure that also fails on `main` is named). 526 passed, 18 failed, 50 skipped on Linux with g++. 15 of the failures also fail on `main` on this PC: `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_options_budget_once`, `test_pipeline_tour`, `test_readback_late`, `test_vk_pgo`, `test_walk_key`, `nx2/test_texture_init_barrier` and `test_mods_size_table`. The other three (`test_pipeline_cache_save`, `test_appimage_package_retry`, `test_oot_state_tap`) failed in the full run on a busy PC and pass when run alone, 2 of 2; none reads a changed file. - [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] Switches documented (docs/development.md; the README for a menu row) and shipped at their recommended value. - [x] A game-free test added for the fix, failing on `main` and passing here. - [x] Host code builds on both Windows (llvm-mingw) and Linux, with UTF-8 paths. - [x] Docs updated.
It fails on main: `fallback_record`'s fills, barriers and dispatches and `mesh_indirect_convert`'s copies and barriers run outside any span, so on a GPU that takes the compute fallback (a Steam Deck by default) their GPU time shows only as the gap between spans.

Assisted-by: Claude
RX_VK_PASS_TIMING names the mesh fallback's compute and the indirect mesh argument conversion
Some checks failed
Website / Website on Cloudflare (pull_request_target) Has been skipped
PR description / Description follows the template (pull_request_target) Successful in 4s
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
Guide screenshots / Guide images and local UI source review (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
f4e53b0aff
Both were untimed, so on a GPU that runs task and mesh programs as compute shaders their dispatches, fills and barriers showed as time between spans. Now `fallback prog <key>` (kind `fallback`) spans each fallback draw's work after its pass ends, and `meshconv` spans `mesh_indirect_convert`.

Assisted-by: Claude
zeldaootr force-pushed pass-timing-names-fallback from f4e53b0aff
Some checks failed
Website / Website on Cloudflare (pull_request_target) Has been skipped
PR description / Description follows the template (pull_request_target) Successful in 4s
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
Guide screenshots / Guide images and local UI source review (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 26cabcbe07
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 19:16:42 +00:00
Compare
Author
Contributor

Rebased onto main 94abdd57 (head 26cabcbe), with no conflict; the commit subjects are now Conventional Commits, which CircleCI's lint job checks for every commit of a pull request (#417), and the base has the CI's config, which a fork's pull request needs at its own head. No other change: each commit's change is the same as before by git patch-id.
Re-run on 94abdd57: test_pass_timing_fallback fails at the test-only commit b4768a56 and passes at the head, with g++ 13.3 and clang 23.1.5; of the 123 checks that are this PR's or read its files (g++ 13.3), 115 pass, 1 skips (a tool this PC lacks), the 6 that fail fail on main 94abdd57 too (test_crash_dialog, test_pipeline_tour, test_shader_module_guard, test_vk_occlusion_queries, test_vk_pgo, test_walk_key), and test_pipeline_cache_save failed once in that loaded run (a timed wait) and passed twice alone at the head and on main. The description names the new commits.

Rebased onto `main` 94abdd57 (head 26cabcbe), with no conflict; the commit subjects are now Conventional Commits, which CircleCI's lint job checks for every commit of a pull request (https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/417), and the base has the CI's config, which a fork's pull request needs at its own head. No other change: each commit's change is the same as before by `git patch-id`. Re-run on 94abdd57: `test_pass_timing_fallback` fails at the test-only commit b4768a56 and passes at the head, with g++ 13.3 and clang 23.1.5; of the 123 checks that are this PR's or read its files (g++ 13.3), 115 pass, 1 skips (a tool this PC lacks), the 6 that fail fail on main 94abdd57 too (`test_crash_dialog`, `test_pipeline_tour`, `test_shader_module_guard`, `test_vk_occlusion_queries`, `test_vk_pgo`, `test_walk_key`), and `test_pipeline_cache_save` failed once in that loaded run (a timed wait) and passed twice alone at the head and on main. The description names the new commits.
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 'pass-timing-names-fallback:zeldaootr-pass-timing-names-fallback'
git switch 'zeldaootr-pass-timing-names-fallback'
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!864
No description provided.