fix(vk): report GPU resource waits beyond recording-slot reuse #2897

Open
github-sync wants to merge 4 commits from github/pr/2897 into main
Owner

@mooki000 opened this pull request on GitHub · 2026-11-12 18:55 UTC · original

Why

The old “GPU-bound wait” measured recording-slot reuse only: capture late-page, readback and other resource waits could be invisible while it read zero. This is a reporting fix, not a change to how the game runs. Refs #995, where a report today shows the old figure reading 0.0 ms on a GPU-limited card (comment).

Change

  • Keep the old value and label it “recording slots only”; add host time in GPU resource waits, split into fences, timelines, idle calls and blocking query reads.
  • Measure the same native calls after the existing recorder boundary. Nested waits count once; polls and Reflex pacing are excluded. Scheduling, synchronization, rendering and settings are unchanged.
  • This is elapsed host time summed across threads, not frame time, GPU utilization or CPU execution. Descheduling contributes; do not add it to the old value or containing phase timers.
  • Recorder/CPU locks, display pacing/acquire, startup’s cooperative-matrix probe and hidden submit/present blocking are outside its scope.

What was measured

Hyrule Field, RTX 4090/NVIDIA 615.78.08, i9-13900K, Arch Linux 7.2.15; headless 5120×2880, render 100%, no frame generation, cap 240. Two ordinary 95-second runs; complete log blocks in seconds 45–75:

Build Old slot value New resource waits
main 51da0464 0.010 ms/frame not recorded
counter 9d786cf1 (source 7acafacf) 0.000 ms/frame 2.927 ms/frame

The changed build reports 2.93 ms/frame (2.916 in timelines) while the old figure reads 0.0 ms. Both runs ended at the time limit without fatal/kernel faults. Competing CPU load differed (mean 21.94 versus 2.33 cores): this proves a reporting gap, not a speed gain or an isolated GPU bottleneck.

Checks and limits

  • Rebased on 9b6072cd, head bfa7e18d (the only conflict was the shared results table; both sides' rows kept). Runtime patch changed lines match old 203356e8; only an additional test-fixture CRT define was needed. The rebased runtime was not rebuilt or run.
  • On the rebased head, test_gpu_wait_stats.py (50 checks), test_recorder_sync.py and test_reflex_swapchain_lifetime.py pass with GCC and Clang. Windows-target syntax passes for 3 captured fixtures; later runtime-dependent variants and Windows execution are not covered.
  • Branch/title preflight passes; upstream advanced one commit to 3c2d80cf3 during the checks and the branch still merges cleanly.
  • Before-rebase negative control: the same accounting fixture executes with main’s old macros and fails 9 of 50 checks on both compilers; it does not merely fail to compile.
  • Earlier full suite: 474 passed, 2 failed, 20 skipped. The missing Reflex-fixture header was repaired; test_fs_links.py had GCC killed, cause unproven. No new full-suite pass is claimed.
  • Not measured: alternating instrumentation-overhead proof or the CPU-limited control; no paired timing proof or speed claim. Two clock reads and an atomic update around nonpolling waits have unmeasured overhead.
  • A full run of the project's checks in my fork, Windows included, is green on these commits (the three new or changed tests run there on Windows too). No Windows gameplay, AMD/Intel run, live Reflex/frame generation, deliberate driver-failure or long-session proof.
  • Main’s merged #2683 reports nested trace phases; this native-call sum has a different scope and must not be added to them.

Assisted-by: GPT-6 Astra
Co-Authored-By: GPT-6 Astra [email protected]

> [@mooki000](https://github.com/mooki000) opened this pull request on GitHub · 2026-11-12 18:55 UTC · [original](https://github.com/NotRexed/Hookshot/pull/2897) ## Why The old “GPU-bound wait” measured recording-slot reuse only: capture late-page, readback and other resource waits could be invisible while it read zero. This is a reporting fix, not a change to how the game runs. Refs [#995](https://git.magicbean.dev/MagicBeanDev/Hookshot/issues/995), where a report today shows the old figure reading 0.0 ms on a GPU-limited card ([comment](https://git.magicbean.dev/MagicBeanDev/Hookshot/issues/995)). ## Change - Keep the old value and label it “recording slots only”; add `host time in GPU resource waits`, split into fences, timelines, idle calls and blocking query reads. - Measure the same native calls after the existing recorder boundary. Nested waits count once; polls and Reflex pacing are excluded. Scheduling, synchronization, rendering and settings are unchanged. - This is elapsed host time summed across threads, not frame time, GPU utilization or CPU execution. Descheduling contributes; do not add it to the old value or containing phase timers. - Recorder/CPU locks, display pacing/acquire, startup’s cooperative-matrix probe and hidden submit/present blocking are outside its scope. ## What was measured Hyrule Field, RTX 4090/NVIDIA 615.78.08, i9-13900K, Arch Linux 7.2.15; headless 5120×2880, render 100%, no frame generation, cap 240. Two ordinary 95-second runs; complete log blocks in seconds 45–75: | Build | Old slot value | New resource waits | |---|---:|---:| | main `51da0464` | 0.010 ms/frame | not recorded | | counter `9d786cf1` (source `7acafacf`) | 0.000 ms/frame | 2.927 ms/frame | The changed build reports **2.93 ms/frame** (2.916 in timelines) while the old figure reads **0.0 ms**. Both runs ended at the time limit without fatal/kernel faults. Competing CPU load differed (mean 21.94 versus 2.33 cores): this proves a reporting gap, not a speed gain or an isolated GPU bottleneck. ## Checks and limits - Rebased on `9b6072cd`, head `bfa7e18d` (the only conflict was the shared results table; both sides' rows kept). Runtime patch changed lines match old `203356e8`; only an additional test-fixture CRT define was needed. The rebased runtime was **not rebuilt or run**. - On the rebased head, `test_gpu_wait_stats.py` (50 checks), `test_recorder_sync.py` and `test_reflex_swapchain_lifetime.py` pass with GCC and Clang. Windows-target syntax passes for 3 captured fixtures; later runtime-dependent variants and Windows execution are not covered. - Branch/title preflight passes; upstream advanced one commit to `3c2d80cf3` during the checks and the branch still merges cleanly. - Before-rebase negative control: the same accounting fixture executes with main’s old macros and fails 9 of 50 checks on both compilers; it does not merely fail to compile. - Earlier full suite: 474 passed, 2 failed, 20 skipped. The missing Reflex-fixture header was repaired; `test_fs_links.py` had GCC killed, cause unproven. No new full-suite pass is claimed. - **Not measured:** alternating instrumentation-overhead proof or the CPU-limited control; no paired timing proof or speed claim. Two clock reads and an atomic update around nonpolling waits have unmeasured overhead. - A full run of the project's checks in my fork, Windows included, is green on these commits (the three new or changed tests run there on Windows too). No Windows gameplay, AMD/Intel run, live Reflex/frame generation, deliberate driver-failure or long-session proof. - Main’s merged [#2683](https://git.magicbean.dev/MagicBeanDev/Hookshot/pulls/2683) reports nested trace phases; this native-call sum has a different scope and must not be added to them. Assisted-by: GPT-6 Astra Co-Authored-By: GPT-6 Astra <[email protected]> <!-- github-sync:item:2897 -->
Keep the old slot counter's value and clarify its scope. Log elapsed host time
inside fence, timeline, idle and waiting-query calls, after recorder drains, without
counting nested calls or Reflex pacing twice. A zero slot wait is not proof that
the GPU is idle.

Exercise the actual boundary macros and exact-clock accounting, including the
old-source negative control. Refs #995.

Assisted-by: GPT-6 Astra
Co-Authored-By: GPT-6 Astra <[email protected]>
Keep every retirement assertion and compile the production pacing exclusion.
No runtime code changes.

Assisted-by: GPT-6 Astra
Co-Authored-By: GPT-6 Astra <[email protected]>
Keep the ordinary run distinct from deferred paired timing evidence.

Assisted-by: GPT-6 Astra

Co-Authored-By: GPT-6 Astra <[email protected]>
The extracted fixture includes hookshot_env.h. Declare the project CRT policy before any header so Windows fixture compilation uses the same intended contract. Runtime code and assertions are unchanged.

Assisted-by: GPT-6 Astra
Co-Authored-By: GPT-6 Astra <[email protected]>
Commenting is not possible because the repository is archived.
No description provided.