docs(tested): RX_VK_WB_MAX_KB=1024 and RX_VK_RECORDER_OWN=1 measured on an RX 9070 XT with a Ryzen 9 7900X #753

Open
Yeetbot90 wants to merge 2 commits from Yeetbot90/Longshot:docs/tested-wb-own-rx9070xt into main
Contributor

Type: docs · Risk: low · Tested on: Windows 11, RX 9070 XT · Needs: none

Why

RX_VK_WB_MAX_KB and RX_VK_RECORDER_OWN are both off by default until they show a gain on more machines, and results from other hardware are asked for. This adds one machine with a fast GPU and a 12-core CPU: on an RX 9070 XT with a Ryzen 9 7900X in Kokiri Forest, neither switch changes the frame rate, because the scene is CPU-bound there (GPU 7.6 ms of an 11.9 ms frame). Each still does what it says: RX_VK_WB_MAX_KB=1024 writes back 16 MB a frame instead of 68 (GPU time 0.3 ms lower), and RX_VK_RECORDER_OWN=1 removes about 40% of the replay's waits for the recorder thread.

What changed

Two run files under docs/tested/, one per switch, each with every run of both arms. No code, and no README change (#547 is rewriting the RX_VK_WB_MAX_KB paragraph).

  • docs/tested/2026-11-15-wb-max-yeetbot90-run01.md
  • docs/tested/2026-11-15-recorder-own-yeetbot90-run01.md

Measurements

Verdict: no fps or CPU difference beyond the run-to-run spread for either switch on this machine. The write-back switch takes 0.3 ms off the GPU's frame and 52 MB a frame off the write-back; the recorder switch takes about 43 ms in 10 s off the replay's waits for the recorder.

Hardware: Windows 11 (26200), RX 9070 XT 16 GB, AMD 26.10.1 (LLPC, Vulkan driver 0x8001a0), Ryzen 9 7900X (12 cores, 24 threads), 32 GB
Build: longshot nightly-182-5274fb72 (source d09e5b6e), its renderer built from source at 5274fb72 with the shipped profile; same DLL for every run, the switches set by environment
Scene: Kokiri Forest outside Link's house (an early save). Headless (HOS_HEADLESS=1: offscreen presents 1920x1080, output 2560x1440), Auto settings, frame rate unlocked (HOS_FPS_MAX=1000), Threaded rendering Auto (the recorder thread is on: 24 threads)
Method: scripted input loads the save (A presses at 20-36 s), walks 2.5 s, then turns the camera for 40 s. Measured over a fixed 30 s window 62-92 s after the start: fps and frame times from RX_VK_FRAME_LOG, CPU from the process's CPU time over the window; GPU time, written-back MB and the recorder's waits from the log's last lines of the run (median). Arms alternated in each round, order rotated between rounds.
How to reproduce: the switches in longshot_env.txt, load a save in Kokiri Forest, turn the camera with the frame rate unlocked, and read the log's vk: a frame: mirrors, vk: GPU time and vk: recorder: lines.

Baseline: the same renderer (main @ 5274fb72) with the switch unset, measured in the same series as the switch. Main against this PR was not the comparison because both are opt-in switches of code already on main; the PR adds no code.

Medians (the write-back series: 3 runs an arm; the recorder series: pairs 2-4, 3 runs an arm):

Before, write-back series: main @ 5274fb72 After, RX_VK_WB_MAX_KB=1024: main @ 5274fb72 Before, recorder series: main @ 5274fb72 After, RX_VK_RECORDER_OWN=1: main @ 5274fb72
fps 81.84 82.13 84.11 83.93
1% low fps 49.22 47.52 50.39 49.80
CPU cores 5.92 5.93 5.94 5.95
GPU ms a frame 7.6 7.3 7.6 7.6
written back MB a frame 68.0 16.4 68.2 68.3
replay waited for the recorder, ms in 10 s 109 109 102 63

Every run, RX_VK_WB_MAX_KB=1024, 3 alternating pairs:

run fps 1% low 99th pct ms CPU cores GPU ms a frame written back MB a frame
unset, 1 81.84 49.22 16.22 5.92 7.6 68.0
1024, 1 82.13 49.11 16.91 5.95 7.4 16.4
1024, 2 80.37 44.57 18.33 5.79 7.3 16.4
unset, 2 81.74 48.62 17.30 5.86 7.7 68.1
unset, 3 84.04 50.26 16.78 5.94 7.6 68.0
1024, 3 84.46 47.52 16.58 5.93 7.3 16.4
median unset 81.84 / 1024 82.13 unset 7.6 / 1024 7.3 unset 68.0 / 1024 16.4

Every run, RX_VK_RECORDER_OWN=1, 4 alternating pairs; pair 1 is left out of the medians because both of its runs were disturbed (1% low 29.5 and 31.0 fps against about 50 in every other run), and is shown:

run fps 1% low 99th pct ms CPU cores replay waited for the recorder (ms in 10 s)
unset, 1 (left out) 80.37 29.50 18.08 5.81 100
OWN, 1 (left out) 82.32 30.98 16.41 5.86 61
OWN, 2 83.59 49.94 16.72 5.97 63
unset, 2 84.17 50.02 16.73 5.96 109
unset, 3 84.11 50.39 16.47 5.91 101
OWN, 3 84.08 49.64 16.84 5.86 62
OWN, 4 83.93 49.80 16.93 5.95 63
unset, 4 83.97 50.82 16.87 5.94 102
median (pairs 2-4) unset 84.11 / OWN 83.93 unset 5.94 / OWN 5.95 unset 102 / OWN 63
unset: vk: a frame: mirrors 89 (867 MB): 9.22 MB synced in 1338.2 copies, 68.30 MB written back
1024:  vk: a frame: mirrors 91 (868 MB): 7.50 MB synced in 1128.6 copies, 16.18 MB written back
1024:  vk: write-backs left out (600 submits): 1058, 4322.6 MB; 26 bindings followed, 40 ranges the CPU read, 0 resets; CPU reads or writes of one left out: 0 so far
unset: vk: recorder: 5394606 packets run in 10.0 s (busy 1.13 s, spun idle 3.00 s, slept 3954 times, 918 of them under 200 us), 0 calls made directly (no room); the replay waited for it 36749 times, 100.39 ms in all, the longest 0.09 ms; vkResetDescriptorPool 13402/54.63 ms (max 0.08), vkEndCommandBuffer 13402/29.77 ms (max 0.09), ...
OWN:   vk: recorder: 5434006 packets run in 10.0 s (busy 1.13 s, spun idle 3.08 s, slept 4018 times, 994 of them under 200 us), 0 calls made directly (no room); the replay waited for it 23862 times, 60.79 ms in all, the longest 0.13 ms; vkEndCommandBuffer 13549/30.88 ms (max 0.09), replay_mu unlock 10122/29.28 ms (max 0.13), ...

Also tried, not proposed: the recorder spends about 3 s in 10 s spinning idle against 1.1 s of work, so I tried letting it spin only while a thread holds replay_mu and sleep at once between replays (the unlock already waits for it to finish). Spin idle fell only from 2.87 to 2.6 s, while its sleeps tripled (most under 200 µs) and the replay's waits for it rose from about 105 to 137 ms in 10 s. Replays come almost back to back here, so nearly all the spin is inside them. One pair only, then dropped; noted so nobody repeats it.

Flags and settings

None changed. Results for two existing opt-in switches:

Flag What it is Before this PR After this PR Effect Helps / doesn't help / untested Recommendation
RX_VK_WB_MAX_KB=1024 Leaves out the write-back of the parts of large GPU-written bindings the CPU doesn't touch off off (unchanged) 68 → 16 MB written back a frame, GPU 7.6 → 7.3 ms; no fps change (CPU-bound) Helps: RX 5600 XT (#547). Doesn't help fps: RTX 3060 Ti, RX 580 (README), RX 9070 XT with a 7900X (here). Untested: GPU-bound fast cards, Linux No change from this run; it adds a GPU-time saving on a card where the frame doesn't depend on it
RX_VK_RECORDER_OWN=1 A recording slot's own resets at its reuse without waiting for the recorder thread off off (unchanged) about 40% fewer replay waits for the recorder; no fps change Earlier: +2.0% fps on an RX 9070 XT with a Ryzen 7 5700X3D, n=2 (#162). Here: no change with a 7900X. Untested: NVIDIA, Intel, Linux No change from this run

Testing

Tested: 14 game runs as above, headless with scripted input on this PC. python -I -B tests/test_tested_configurations.py: the two new files validate; its one failure (test_cli_ascii_pipe_emits_the_arrow_containing_source_as_utf8, CRLF against LF) fails the same way with the two files taken out, on this Windows checkout. python -I -B tests/run_all.py: 530 passed, 21 failed, 42 skipped. The failures are this PC's (Windows, llvm-mingw, no Linux tools); none reads docs/tested/ except test_tested_configurations.py above, so none depends on this PR.

Not tested: with a window (all runs headless); other areas; with the frame rate capped; Linux.

Must be tested: None (docs only).

Risks

What could break: nothing; two documentation files.

Turning it off: 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.
  • python -I -B tests/run_all.py passes (any failure that also fails on main is named): 21 failures of this Windows PC, none touching these files (Testing).
  • 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 file in docs/tested/ for each new measured run (format in docs/tested-configurations.md).
**Type:** docs · **Risk:** low · **Tested on:** Windows 11, RX 9070 XT · **Needs:** none ## Why `RX_VK_WB_MAX_KB` and `RX_VK_RECORDER_OWN` are both off by default until they show a gain on more machines, and results from other hardware are asked for. This adds one machine with a fast GPU and a 12-core CPU: on an RX 9070 XT with a Ryzen 9 7900X in Kokiri Forest, **neither switch changes the frame rate**, because the scene is CPU-bound there (GPU 7.6 ms of an 11.9 ms frame). Each still does what it says: `RX_VK_WB_MAX_KB=1024` writes back 16 MB a frame instead of 68 (GPU time 0.3 ms lower), and `RX_VK_RECORDER_OWN=1` removes about 40% of the replay's waits for the recorder thread. ## What changed Two run files under `docs/tested/`, one per switch, each with every run of both arms. No code, and no README change ([#547](https://git.magicbean.dev/MagicBeanDev/Longshot/pulls/547) is rewriting the `RX_VK_WB_MAX_KB` paragraph). - `docs/tested/2026-11-15-wb-max-yeetbot90-run01.md` - `docs/tested/2026-11-15-recorder-own-yeetbot90-run01.md` ## Measurements **Verdict:** no fps or CPU difference beyond the run-to-run spread for either switch on this machine. The write-back switch takes 0.3 ms off the GPU's frame and 52 MB a frame off the write-back; the recorder switch takes about 43 ms in 10 s off the replay's waits for the recorder. Hardware: Windows 11 (26200), RX 9070 XT 16 GB, AMD 26.10.1 (LLPC, Vulkan driver 0x8001a0), Ryzen 9 7900X (12 cores, 24 threads), 32 GB Build: longshot nightly-182-5274fb72 (source d09e5b6e), its renderer built from source at 5274fb72 with the shipped profile; same DLL for every run, the switches set by environment Scene: Kokiri Forest outside Link's house (an early save). Headless (`HOS_HEADLESS=1`: offscreen presents 1920x1080, output 2560x1440), Auto settings, frame rate unlocked (`HOS_FPS_MAX=1000`), Threaded rendering Auto (the recorder thread is on: 24 threads) Method: scripted input loads the save (A presses at 20-36 s), walks 2.5 s, then turns the camera for 40 s. Measured over a fixed 30 s window 62-92 s after the start: fps and frame times from `RX_VK_FRAME_LOG`, CPU from the process's CPU time over the window; GPU time, written-back MB and the recorder's waits from the log's last lines of the run (median). Arms alternated in each round, order rotated between rounds. How to reproduce: the switches in `longshot_env.txt`, load a save in Kokiri Forest, turn the camera with the frame rate unlocked, and read the log's `vk: a frame: mirrors`, `vk: GPU time` and `vk: recorder:` lines. Baseline: the same renderer (main @ 5274fb72) with the switch unset, measured in the same series as the switch. Main against this PR was not the comparison because both are opt-in switches of code already on main; the PR adds no code. Medians (the write-back series: 3 runs an arm; the recorder series: pairs 2-4, 3 runs an arm): | | Before, write-back series: main @ 5274fb72 | After, RX_VK_WB_MAX_KB=1024: main @ 5274fb72 | Before, recorder series: main @ 5274fb72 | After, RX_VK_RECORDER_OWN=1: main @ 5274fb72 | |---|---|---|---|---| | fps | 81.84 | 82.13 | 84.11 | 83.93 | | 1% low fps | 49.22 | 47.52 | 50.39 | 49.80 | | CPU cores | 5.92 | 5.93 | 5.94 | 5.95 | | GPU ms a frame | 7.6 | 7.3 | 7.6 | 7.6 | | written back MB a frame | 68.0 | 16.4 | 68.2 | 68.3 | | replay waited for the recorder, ms in 10 s | 109 | 109 | 102 | 63 | Every run, `RX_VK_WB_MAX_KB=1024`, 3 alternating pairs: | run | fps | 1% low | 99th pct ms | CPU cores | GPU ms a frame | written back MB a frame | |---|---|---|---|---|---|---| | unset, 1 | 81.84 | 49.22 | 16.22 | 5.92 | 7.6 | 68.0 | | 1024, 1 | 82.13 | 49.11 | 16.91 | 5.95 | 7.4 | 16.4 | | 1024, 2 | 80.37 | 44.57 | 18.33 | 5.79 | 7.3 | 16.4 | | unset, 2 | 81.74 | 48.62 | 17.30 | 5.86 | 7.7 | 68.1 | | unset, 3 | 84.04 | 50.26 | 16.78 | 5.94 | 7.6 | 68.0 | | 1024, 3 | 84.46 | 47.52 | 16.58 | 5.93 | 7.3 | 16.4 | | **median** | unset 81.84 / 1024 82.13 | | | | unset 7.6 / 1024 7.3 | unset 68.0 / 1024 16.4 | Every run, `RX_VK_RECORDER_OWN=1`, 4 alternating pairs; pair 1 is left out of the medians because both of its runs were disturbed (1% low 29.5 and 31.0 fps against about 50 in every other run), and is shown: | run | fps | 1% low | 99th pct ms | CPU cores | replay waited for the recorder (ms in 10 s) | |---|---|---|---|---|---| | unset, 1 (left out) | 80.37 | 29.50 | 18.08 | 5.81 | 100 | | OWN, 1 (left out) | 82.32 | 30.98 | 16.41 | 5.86 | 61 | | OWN, 2 | 83.59 | 49.94 | 16.72 | 5.97 | 63 | | unset, 2 | 84.17 | 50.02 | 16.73 | 5.96 | 109 | | unset, 3 | 84.11 | 50.39 | 16.47 | 5.91 | 101 | | OWN, 3 | 84.08 | 49.64 | 16.84 | 5.86 | 62 | | OWN, 4 | 83.93 | 49.80 | 16.93 | 5.95 | 63 | | unset, 4 | 83.97 | 50.82 | 16.87 | 5.94 | 102 | | **median (pairs 2-4)** | unset 84.11 / OWN 83.93 | | | unset 5.94 / OWN 5.95 | unset 102 / OWN 63 | ``` unset: vk: a frame: mirrors 89 (867 MB): 9.22 MB synced in 1338.2 copies, 68.30 MB written back 1024: vk: a frame: mirrors 91 (868 MB): 7.50 MB synced in 1128.6 copies, 16.18 MB written back 1024: vk: write-backs left out (600 submits): 1058, 4322.6 MB; 26 bindings followed, 40 ranges the CPU read, 0 resets; CPU reads or writes of one left out: 0 so far unset: vk: recorder: 5394606 packets run in 10.0 s (busy 1.13 s, spun idle 3.00 s, slept 3954 times, 918 of them under 200 us), 0 calls made directly (no room); the replay waited for it 36749 times, 100.39 ms in all, the longest 0.09 ms; vkResetDescriptorPool 13402/54.63 ms (max 0.08), vkEndCommandBuffer 13402/29.77 ms (max 0.09), ... OWN: vk: recorder: 5434006 packets run in 10.0 s (busy 1.13 s, spun idle 3.08 s, slept 4018 times, 994 of them under 200 us), 0 calls made directly (no room); the replay waited for it 23862 times, 60.79 ms in all, the longest 0.13 ms; vkEndCommandBuffer 13549/30.88 ms (max 0.09), replay_mu unlock 10122/29.28 ms (max 0.13), ... ``` **Also tried, not proposed:** the recorder spends about 3 s in 10 s spinning idle against 1.1 s of work, so I tried letting it spin only while a thread holds `replay_mu` and sleep at once between replays (the unlock already waits for it to finish). Spin idle fell only from 2.87 to 2.6 s, while its sleeps tripled (most under 200 µs) and the replay's waits for it rose from about 105 to 137 ms in 10 s. Replays come almost back to back here, so nearly all the spin is inside them. One pair only, then dropped; noted so nobody repeats it. ### Flags and settings None changed. Results for two existing opt-in switches: | Flag | What it is | Before this PR | After this PR | Effect | Helps / doesn't help / untested | Recommendation | |---|---|---|---|---|---|---| | `RX_VK_WB_MAX_KB=1024` | Leaves out the write-back of the parts of large GPU-written bindings the CPU doesn't touch | off | off (unchanged) | 68 → 16 MB written back a frame, GPU 7.6 → 7.3 ms; no fps change (CPU-bound) | Helps: RX 5600 XT (#547). Doesn't help fps: RTX 3060 Ti, RX 580 (README), RX 9070 XT with a 7900X (here). Untested: GPU-bound fast cards, Linux | No change from this run; it adds a GPU-time saving on a card where the frame doesn't depend on it | | `RX_VK_RECORDER_OWN=1` | A recording slot's own resets at its reuse without waiting for the recorder thread | off | off (unchanged) | about 40% fewer replay waits for the recorder; no fps change | Earlier: +2.0% fps on an RX 9070 XT with a Ryzen 7 5700X3D, n=2 (#162). Here: no change with a 7900X. Untested: NVIDIA, Intel, Linux | No change from this run | ## Testing **Tested:** 14 game runs as above, headless with scripted input on this PC. `python -I -B tests/test_tested_configurations.py`: the two new files validate; its one failure (`test_cli_ascii_pipe_emits_the_arrow_containing_source_as_utf8`, CRLF against LF) fails the same way with the two files taken out, on this Windows checkout. `python -I -B tests/run_all.py`: 530 passed, 21 failed, 42 skipped. The failures are this PC's (Windows, llvm-mingw, no Linux tools); none reads `docs/tested/` except `test_tested_configurations.py` above, so none depends on this PR. **Not tested:** with a window (all runs headless); other areas; with the frame rate capped; Linux. **Must be tested:** None (docs only). ## Risks **What could break:** nothing; two documentation files. **Turning it off:** 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`. - [x] `python -I -B tests/run_all.py` passes (any failure that also fails on `main` is named): 21 failures of this Windows PC, none touching these files (Testing). - [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 file in `docs/tested/` for each new measured run (format in `docs/tested-configurations.md`).
docs(tested): RX_VK_WB_MAX_KB=1024 and RX_VK_RECORDER_OWN=1 measured on an RX 9070 XT with a Ryzen 9 7900X
Some checks failed
PR description / Description follows the template (pull_request_target) Successful in 16s
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
Website / Website on Cloudflare (pull_request) Has been cancelled
58b871f83a
Both switches are off by default until they show a gain on more machines. On an RX 9070 XT with a
Ryzen 9 7900X in Kokiri Forest (CPU-bound, about 84 fps unlocked) neither changes the frame rate:
WB_MAX_KB cuts the write-back from 68 to 16 MB a frame and 0.3 ms of GPU time, RECORDER_OWN cuts the
replay's waits for the recorder from about 105 to 62 ms in 10 s.

Assisted-by: Claude Opus 5.5 (Cursor)
Co-Authored-By: Claude <[email protected]>
Co-authored-by: Cursor <[email protected]>
Merge branch 'main' into docs/tested-wb-own-rx9070xt
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 6s
Website / Website on Cloudflare (pull_request_target) Has been skipped
e2d508173a
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 6s
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 'docs/tested-wb-own-rx9070xt:Yeetbot90-docs/tested-wb-own-rx9070xt'
git switch 'Yeetbot90-docs/tested-wb-own-rx9070xt'
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!753
No description provided.