Repository navigation
perf(agc): skip the queued-draw read check when a storage flush stores nothing - #8911
Conversation
…s nothing StorageTexture::FlushPending asks DrawPipeline::HeldReads first on every call: it takes the draw pipeline's mutex and walks the read ranges of every queued draw. Most flushes come from sampled-texture lookups and storage refreshes over memory without pending results. Those return false without storing or publishing anything whether a queued draw holds the range or not, so FlushPending now returns before the check when nothing would be stored: no pending image with a unit in the range, none being flushed, and no unit shadow over it when the scope publishes. A flush that has something to store still asks HeldReads first. DrawPipeline exposes its held-read query count for the test. AI-assisted: yes
|
This pull request is labeled |
MarcZX10
left a comment
There was a problem hiding this comment.
The empty-flush fast path looks consistent with the existing pending-list and shadow-publication paths on inspection. One merge-readiness gap: the description reports a measured speedup, but CONTRIBUTING.md requires the aps5-summary.jsonl lines from main and this commit for the same title/scene/machine, plus both traces and tools/trace_digest.py output. The perf label bot has also requested those artifacts. Could you attach them (or remove the quantified speed claim if it cannot be reproduced)?
|
Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.
|
|
@MarcZX10 thanks for checking the fast path against the pending-list and shadow-publication paths, that's the part I was most worried about. You're right about the number. The only measurement I have is from our own Yōtei tree, not |
|
AMD / Linux data point for #8911, #8912 and #8913 together, on a different title. The result is neutral: no measurable change and no regression. Setup: ASTRO BOT (PPSA21567) 01.019.000, level
Runs were interleaved: base, change, change, base.
The p50 difference (~2-3 %) is smaller than the spread between the two base runs. The change-1 p99 includes the first present of the window (753.8 ms), which is a load spike. From Both builds ran 3 × 180 s with no device lost, no amdgpu kernel messages and no new exceptions. Not tested: the PRs one at a time, NVIDIA/Intel, CTest. Tested and written by Claude (AI assistant) on a contributor's machine. |
|
Windows measurement of this change, for reference. Setup: AMD Radeon RX 6700 XT, AMD driver 26.10.1, Windows 11. Spirit of the Island (PPSA13934) title screen,
On that screen, most of the remaining |
|
I measured this one on its own now, as asked on #8912. Plain main can't take Ghost of Yōtei to the open world: its loading screen stops presenting after about 160 s and the game later aborts on a blend into a 10_11_11 unorm target that main doesn't support. So this is our tree (our local merge with main of 2026-10-21) with only this PR's switch flipped every 60 s in one run ( With the skip on I got 6.16 presents per 10 s against 5.61 with it off. Paired against the neighbouring phases that's -0.35 +- 0.30 presents with the change off, so about 1 SE: a lean in its favour, not a result I'd call measured. Committer time per commit didn't move (316 vs 310 us). What it clearly does is the thing it says: per phase, about 858k storage flushes skipped the queued-draw check with it on against 44k off, and the flushes that held for a queued read dropped from about 104k to 5k. I also tried a boot-scene pair on plain main, but those captures turned out to be pipeline-cold on this machine, so I'm not quoting them. If you'd rather see a longer A/B to tighten the error bar, I can run one. DetailsRun |
|
A measurement that bears on how this change and #9490 split the held-read cost, from ASTRO BOT (PPSA21564) in the Crash Site hub. Setup: Windows 11, Ryzen 7 5800X3D, RX 9070 XT, With
So in this game nearly all of the cost is the I haven't measured this PR's skip on top of that. From the split above, its saving here would be at most the remaining ~1.5 % of committer samples. That still adds up across the ~370k commits per 10 s, but it is smaller than in your Yōtei profile, where the mutex dominated. |
|
Thanks for splitting the |
|
Linux data point, since the body's only Linux run is WSL and the thread so far has no native lavapipe result (EdouardSence's Linux run is RADV frame times, no ctest): llvmpipe (LLVM 23.1.1, 256 bits) via lavapipe, Mesa 26.2.4, Head. Negative control. The same merge with On the two overlaps the body names: AI-assisted: yes |
|
Comment for #8911 (perf(agc): skip the queued-draw read check when a storage flush stores nothing) Following up on the artifact request. Here are captures for the main-vs-#8911 comparison, with their limits. What was measured
Results (median frame time p50, ms; GPU busy per present, ms)
What this does and does not show
Observed on both sides (not attributed to #8911)
Attached / available
Run notes: head-3 was killed by a 22 GB memory cap after its trace was written. The trace is complete (trace_dropped is false). Happy to rerun it if you need a clean set. Dextroid17 Summary lines (one per run, as written by the tracer): |
|
@Dextroid17 thanks for running this, and for interleaving the runs and clearing the shader cache each time. That's exactly the main-vs-change comparison I couldn't make here. I read it the same way you do: on the title menu the two builds don't separate (p50 -1.2 ms against a 1.6-2.4 ms spread, GPU per present -1.5 ms, mostly from one run), so no claim either way. That's about what I'd expect from that scene. The check this PR skips only costs something when a storage flush stores nothing while queued draws are pending, and that mostly happens in the open world, where we saw it on our own tree. The ~130 s stall on both sides lines up with the cold shader cache: If it's not too much trouble, could you attach two of the traces (one per side) and the |
|
@Celegans12 Here they are: one trace per side from the six interleaved runs above, with the
I picked the median Side by side (
|
| thread | busy | wait | untraced | in slices < 20 us | largest |
|---|---|---|---|---|---|
| title | 19.9 (1 %) | 18.8 (1 %) | 2486.6 | 0.2 | Shader.Register 19.6, Recorder.Sync 0.2 |
| shader prepare | 2258.5 (89 %) | 0.0 (0 %) | 266.8 | 0.0 | Shader.PrepareArtifact 2258.5 |
| shader prepare | 2253.5 (89 %) | 0.0 (0 %) | 271.8 | 0.0 | Shader.PrepareArtifact 2253.5 |
| shader prepare | 2253.6 (89 %) | 0.0 (0 %) | 271.7 | 0.0 | Shader.PrepareArtifact 2253.6 |
| shader prepare | 2258.5 (89 %) | 0.0 (0 %) | 266.8 | 0.0 | Shader.PrepareArtifact 2258.5 |
| shader prepare | 2259.0 (89 %) | 0.0 (0 %) | 266.3 | 0.0 | Shader.PrepareArtifact 2259.0 |
| shader prepare | 2258.1 (89 %) | 0.0 (0 %) | 267.1 | 0.0 | Shader.PrepareArtifact 2258.1 |
| shader prepare | 2259.4 (89 %) | 0.0 (0 %) | 265.9 | 0.0 | Shader.PrepareArtifact 2259.4 |
| shader prepare | 2254.2 (89 %) | 0.0 (0 %) | 271.0 | 0.0 | Shader.PrepareArtifact 2254.2 |
| queue worker 0x0 | 138.2 (5 %) | 2385.3 (94 %) | 1.7 | 5.1 | Driver.Packet 164.6, Driver.Completion 0.1 |
| shader prepare | 1.2 (0 %) | 0.0 (0 %) | 2524.1 | 0.0 | Vulkan.GraphicsPipelinePrebuild 1.2 |
| queue worker 0x52 | 4.0 (0 %) | 130.3 (5 %) | 2391.0 | 0.8 | Driver.Packet 35.0, Driver.EndSubmission 1.2 |
| queue worker 0x20 | 1.3 (0 %) | 2515.2 (100 %) | 8.7 | 0.1 | Driver.Packet 37.9, Driver.EndSubmission 0.9 |
| queue worker 0x53 | 0.6 (0 %) | 133.9 (5 %) | 2390.8 | 0.2 | Driver.Packet 37.7, Driver.EndSubmission 0.1 |
| title | 0.0 (0 %) | 0.0 (0 %) | 2525.3 | 0.0 | Shader.ResolveGraphicsStagesAbi 0.0, Shader.ResolveAbi 0.0 |
| title | 0.0 (0 %) | 0.0 (0 %) | 2525.3 | 0.0 | Shader.ResolveAbi 0.0, Shader.ResolveGraphicsStagesAbi 0.0 |
| title | 0.0 (0 %) | 0.0 (0 %) | 2525.3 | 0.0 | Shader.ResolveGraphicsStagesAbi 0.0, Shader.ResolveAbi 0.0 |
| queue worker 0x48 | 4.0 (0 %) | 2512.8 (100 %) | 8.5 | 0.3 | Driver.Packet 13.8, Driver.EndSubmission 0.7 |
| queue worker 0x30 | 24.5 (1 %) | 2497.4 (99 %) | 3.4 | 0.7 | Driver.Packet 112.7, Driver.EndSubmission 0.8 |
| queue worker 0x38 | 19.1 (1 %) | 2503.6 (99 %) | 2.6 | 0.8 | Driver.Packet 130.5, Driver.EndSubmission 0.3 |
| draw committer | 43.9 (2 %) | 15.9 (1 %) | 2465.5 | 0.3 | Vulkan.DrawFromRecipe 20.7, Graphics.Draw 15.6 |
| presenter | 9.6 (0 %) | 0.0 (0 %) | 2515.6 | 0.1 | VideoOut.Flip 9.4, Driver.Present 0.2 |
| title | 0.0 (0 %) | 0.0 (0 %) | 2525.2 | 0.0 | Shader.ResolveGraphicsStagesAbi 0.0, Shader.ResolveGraphicsAbi 0.0 |
| title | 0.0 (0 %) | 0.0 (0 %) | 2525.2 | 0.0 | Shader.ResolveAbi 0.0, Shader.ResolveGraphicsStagesAbi 0.0 |
| title | 0.0 (0 %) | 0.0 (0 %) | 2525.2 | 0.0 | Shader.ResolveGraphicsStagesAbi 0.0, Shader.ResolveAbi 0.0 |
| title | 0.1 (0 %) | 0.0 (0 %) | 2525.2 | 0.0 | Shader.ResolveGraphicsStagesAbi 0.1, Shader.ResolveAbi 0.0 |
| title | 0.0 (0 %) | 0.0 (0 %) | 2525.2 | 0.0 | Shader.ResolveGraphicsStagesAbi 0.0, Shader.ResolveAbi 0.0 |
| title | 0.0 (0 %) | 0.0 (0 %) | 2525.2 | 0.0 | Shader.ResolveGraphicsStagesAbi 0.0, Shader.ResolveAbi 0.0 |
| title | 0.0 (0 %) | 0.0 (0 %) | 2525.2 | 0.0 | Shader.ResolveGraphicsStagesAbi 0.0, Shader.ResolveAbi 0.0 |
| gpu | 81.2 (3 %) | 0.0 (0 %) | 2444.1 | 0.0 | batch 81.2 |
Largest slices (ms per frame, inclusive, all threads): Shader.PrepareArtifact 18054.9, Driver.WorkerWait 12333.9, Driver.WorkerWait.idle_and_completion_poll 12333.8, Driver.Packet 532.1, Driver.Packet.dispatch 245.1, Driver.Packet.memory_wait 217.3, Driver.Dispatch 155.9, batch 81.2, Resources.Complete 60.7, Vulkan.Dispatch 58.0
Longest waits
- Driver.WorkerWait (queue worker 0x20) 131899.5 ms at 9038 ms, present 209
- Driver.WorkerWait (queue worker 0x48) 131804.4 ms at 9140 ms, present 210
- Driver.WorkerWait (queue worker 0x30) 131649.0 ms at 9296 ms, present 210
- Driver.WorkerWait (queue worker 0x38) 131645.0 ms at 9300 ms, present 210
- Driver.WorkerWait (queue worker 0x0) 131599.4 ms at 9345 ms, present 211
- Driver.WorkerWait (queue worker 0x20) 494.5 ms at 8027 ms, present 205
- Driver.WorkerWait (queue worker 0x48) 376.2 ms at 8164 ms, present 206
- Driver.WorkerWait (queue worker 0x48) 300.6 ms at 623 ms, present 161
- Driver.Packet.memory_wait (queue worker 0x30) 265.0 ms at 140969 ms, present 211
- Driver.WorkerWait (queue worker 0x20) 249.8 ms at 675 ms, present 161
Largest GPU batches (GPU ranges inside, and the CPU slices that recorded each, inclusive)
- batch 1862: 157.9 ms at 9465 ms, present 211: GPU no ranges; recorded by Driver.WorkerWait (queue worker 0x0) 131599.6, Driver.WorkerWait.idle_and_completion_poll (queue worker 0x0) 131599.5, Recorder.Sync (queue worker 0x0) 158.2, Driver.Packet (queue worker 0x0) 15.3
- batch 359: 71.7 ms at 1837 ms, present 166: GPU no ranges; recorded by no CPU slices
- batch 395: 71.3 ms at 2026 ms, present 167: GPU no ranges; recorded by no CPU slices
- batch 237: 70.2 ms at 1262 ms, present 163: GPU no ranges; recorded by no CPU slices
- batch 319: 69.4 ms at 1644 ms, present 165: GPU no ranges; recorded by no CPU slices
trace_digest.py, #8911 (bfd4634c88da, run 1)
seconds 20:30 from present 155: 55 presents, frame p50 159.9 / p90 221.3 / p99 131927.0 / max 131927.0 ms, GPU busy 72.4 ms per present
NVIDIA GeForce RTX 3080 Ti, NVIDIA 615.78.08, Linux 7.3.0-2-cachyos, 3840x2160, commit bfd4634c88da, dropped: no
{"commit":"bfd4634c88da","dirty":false,"env":{"APS5_TRACE_DIR":"<path>","APS5_TRACE_SECONDS":"20:30"},"gpu":"NVIDIA GeForce RTX 3080 Ti","driver":"NVIDIA 615.78.08","os":"Linux 7.3.0-2-cachyos","cpu":"11th Gen Intel(R) Core(TM) i9-11900K @ 3.50GHz","cpu_threads":16,"memory_mib":31912,"title_id":"PPSA26344","title":"Ghost of Y\u00c5\u008dtei","content_version":"01.008.000","resolution":"3840x2160","window":{"spec":"seconds 20:30","first_present":155,"ms":141141.748},"presents":55,"frame_ms":{"p50":159.861,"p90":221.298,"p99":131927.011,"max":131927.011},"gpu_busy_ms_per_present":72.394,"worker_busy_pct":{"queue worker 0x0":6.425,"queue worker 0x20":1.489,"queue worker 0x52":1.359,"queue worker 0x53":1.527,"queue worker 0x30":4.41,"queue worker 0x38":5.088,"queue worker 0x48":0.454},"top_phases_ms_per_frame":{"Shader.PrepareArtifact":18371.997,"Driver.Packet":530.589,"Driver.Packet.dispatch":245.406,"Driver.Packet.memory_wait":211.582,"Driver.Dispatch":158.985,"Resources.Complete":62.124,"Vulkan.Dispatch":57.12,"Vulkan.Dispatch.shader_resources":55.56},"trace_dropped":false,"trace":"aps5-trace-bfd4634c88da-139442.json.gz"}Slowest frames (largest slices inside each, inclusive)
- present 209: 131927.0 ms at 9215 ms: Shader.PrepareArtifact (shader prepare) 1008441.2, Driver.WorkerWait (queue worker 0x48) 131564.6, Driver.WorkerWait.idle_and_completion_poll (queue worker 0x48) 131564.6, Driver.WorkerWait (queue worker 0x38) 131564.6
- present 204: 418.0 ms at 7973 ms: Driver.WorkerWait (queue worker 0x20) 418.0, Driver.WorkerWait.idle_and_completion_poll (queue worker 0x20) 418.0, Driver.WorkerWait (queue worker 0x48) 414.5, Driver.WorkerWait.idle_and_completion_poll (queue worker 0x48) 414.5
- present 160: 315.9 ms at 607 ms: Driver.WorkerWait (queue worker 0x48) 313.7, Driver.WorkerWait.idle_and_completion_poll (queue worker 0x48) 313.7, Driver.Packet (queue worker 0x0) 304.0, Driver.Packet.dispatch (queue worker 0x0) 289.0
- present 208: 271.2 ms at 8944 ms: Shader.PrepareArtifact (shader prepare) 2012.0, Driver.WorkerWait (queue worker 0x20) 271.2, Driver.WorkerWait.idle_and_completion_poll (queue worker 0x20) 271.2, Driver.Packet (queue worker 0x0) 259.5
- present 205: 224.0 ms at 8391 ms: Driver.WorkerWait (queue worker 0x48) 218.1, Driver.WorkerWait.idle_and_completion_poll (queue worker 0x48) 218.1, Driver.Packet (queue worker 0x0) 214.5, Driver.Packet.dispatch (queue worker 0x0) 196.5
Threads (ms per frame)
| thread | busy | wait | untraced | in slices < 20 us | largest |
|---|---|---|---|---|---|
| title | 22.0 (1 %) | 20.1 (1 %) | 2524.1 | 0.2 | Shader.Register 21.8, Shader.ResolveGraphicsStagesAbi 0.1 |
| shader prepare | 2296.0 (89 %) | 0.0 (0 %) | 270.2 | 0.0 | Shader.PrepareArtifact 2296.0 |
| shader prepare | 2297.0 (90 %) | 0.0 (0 %) | 269.2 | 0.0 | Shader.PrepareArtifact 2297.0 |
| shader prepare | 2296.2 (89 %) | 0.0 (0 %) | 270.0 | 0.0 | Shader.PrepareArtifact 2296.2 |
| shader prepare | 2297.8 (90 %) | 0.0 (0 %) | 268.4 | 0.0 | Shader.PrepareArtifact 2297.8 |
| shader prepare | 2297.5 (90 %) | 0.0 (0 %) | 268.7 | 0.0 | Shader.PrepareArtifact 2297.5 |
| shader prepare | 2294.2 (89 %) | 0.0 (0 %) | 272.0 | 0.0 | Shader.PrepareArtifact 2294.2 |
| shader prepare | 2294.3 (89 %) | 0.0 (0 %) | 272.0 | 0.0 | Shader.PrepareArtifact 2294.3 |
| shader prepare | 2299.2 (90 %) | 0.0 (0 %) | 267.1 | 0.0 | Shader.PrepareArtifact 2299.2 |
| queue worker 0x0 | 136.0 (5 %) | 2428.5 (95 %) | 1.7 | 5.1 | Driver.Packet 163.5, Driver.Completion 0.1 |
| shader prepare | 1.1 (0 %) | 0.0 (0 %) | 2565.1 | 0.0 | Vulkan.GraphicsPipelinePrebuild 1.1 |
| queue worker 0x20 | 0.5 (0 %) | 2558.9 (100 %) | 6.8 | 0.1 | Driver.Packet 37.9, Driver.EndSubmission 0.3 |
| queue worker 0x52 | 3.4 (0 %) | 131.1 (5 %) | 2431.7 | 0.8 | Driver.Packet 34.3, Driver.EndSubmission 0.4 |
| queue worker 0x53 | 0.8 (0 %) | 134.3 (5 %) | 2431.1 | 0.2 | Driver.Packet 39.1, Driver.EndSubmission 0.0 |
| title | 0.0 (0 %) | 0.0 (0 %) | 2566.2 | 0.0 | Shader.ResolveGraphicsStagesAbi 0.0, Shader.ResolveAbi 0.0 |
| title | 0.0 (0 %) | 0.0 (0 %) | 2566.2 | 0.0 | Shader.ResolveGraphicsStagesAbi 0.0, Shader.ResolveAbi 0.0 |
| title | 0.0 (0 %) | 0.0 (0 %) | 2566.2 | 0.0 | Shader.ResolveGraphicsStagesAbi 0.0, Shader.ResolveAbi 0.0 |
| queue worker 0x30 | 22.1 (1 %) | 2542.6 (99 %) | 1.5 | 0.7 | Driver.Packet 113.0, Driver.EndSubmission 0.0 |
| queue worker 0x38 | 20.9 (1 %) | 2544.0 (99 %) | 1.4 | 0.8 | Driver.Packet 130.2, Driver.EndSubmission 0.2 |
| queue worker 0x48 | 3.2 (0 %) | 2556.5 (100 %) | 6.5 | 0.3 | Driver.Packet 10.7, Driver.EndSubmission 0.8 |
| draw committer | 41.1 (2 %) | 16.2 (1 %) | 2508.9 | 0.3 | Vulkan.DrawFromRecipe 19.3, Graphics.Draw 17.3 |
| presenter | 9.4 (0 %) | 0.0 (0 %) | 2556.8 | 0.1 | VideoOut.Flip 9.3, Driver.Present 0.2 |
| title | 0.0 (0 %) | 0.0 (0 %) | 2566.2 | 0.0 | Shader.ResolveGraphicsStagesAbi 0.0, Shader.ResolveAbi 0.0 |
| title | 0.0 (0 %) | 0.0 (0 %) | 2566.2 | 0.0 | Shader.ResolveGraphicsStagesAbi 0.0, Shader.ResolveAbi 0.0 |
| title | 0.0 (0 %) | 0.0 (0 %) | 2566.2 | 0.0 | Shader.ResolveGraphicsStagesAbi 0.0, Shader.ResolveAbi 0.0 |
| title | 0.0 (0 %) | 0.0 (0 %) | 2566.2 | 0.0 | Shader.ResolveGraphicsStagesAbi 0.0, Shader.ResolveGraphicsAbi 0.0 |
| title | 0.0 (0 %) | 0.0 (0 %) | 2566.2 | 0.0 | Shader.ResolveGraphicsStagesAbi 0.0, Shader.ResolveAbi 0.0 |
| title | 0.0 (0 %) | 0.0 (0 %) | 2566.2 | 0.0 | Shader.ResolveGraphicsStagesAbi 0.0, Shader.ResolveAbi 0.0 |
| title | 0.0 (0 %) | 0.0 (0 %) | 2566.2 | 0.0 | Shader.ResolveGraphicsStagesAbi 0.0, Shader.ResolveGraphicsAbi 0.0 |
| gpu | 79.6 (3 %) | 0.0 (0 %) | 2486.6 | 0.0 | batch 79.6 |
Largest slices (ms per frame, inclusive, all threads): Shader.PrepareArtifact 18372.0, Driver.WorkerWait 12552.1, Driver.WorkerWait.idle_and_completion_poll 12552.1, Driver.Packet 528.8, Driver.Packet.dispatch 245.0, Driver.Packet.memory_wait 211.6, Driver.Dispatch 158.3, batch 79.6, Resources.Complete 62.0, Vulkan.Dispatch 57.1
Longest waits
- Driver.WorkerWait (queue worker 0x20) 131887.5 ms at 8890 ms, present 207
- Driver.WorkerWait (queue worker 0x48) 131788.0 ms at 8991 ms, present 208
- Driver.WorkerWait (queue worker 0x30) 131627.9 ms at 9151 ms, present 208
- Driver.WorkerWait (queue worker 0x38) 131609.9 ms at 9169 ms, present 208
- Driver.WorkerWait (queue worker 0x0) 131560.6 ms at 9219 ms, present 209
- Driver.WorkerWait (queue worker 0x20) 501.8 ms at 7895 ms, present 203
- Driver.WorkerWait (queue worker 0x48) 412.4 ms at 7986 ms, present 204
- Driver.WorkerWait (queue worker 0x48) 313.1 ms at 619 ms, present 160
- Driver.Packet.memory_wait (queue worker 0x30) 262.7 ms at 140813 ms, present 209
- Driver.WorkerWait (queue worker 0x20) 262.1 ms at 671 ms, present 160
Largest GPU batches (GPU ranges inside, and the CPU slices that recorded each, inclusive)
- batch 1821: 157.9 ms at 9323 ms, present 209: GPU no ranges; recorded by Driver.WorkerWait (queue worker 0x0) 131560.8, Driver.WorkerWait.idle_and_completion_poll (queue worker 0x0) 131560.8, Recorder.Sync (queue worker 0x0) 158.2, Driver.Dispatch.decode_key_device_setup (queue worker 0x0) 75.2
- batch 314: 70.6 ms at 1642 ms, present 164: GPU no ranges; recorded by no CPU slices
- batch 240: 69.8 ms at 1257 ms, present 162: GPU no ranges; recorded by no CPU slices
- batch 351: 69.7 ms at 1837 ms, present 165: GPU no ranges; recorded by no CPU slices
- batch 281: 69.3 ms at 1451 ms, present 163: GPU no ranges; recorded by no CPU slices
AI-assisted: yes (Claude Code).
|
@Dextroid17 thanks, that's exactly the |
…ar#9289 boykopovar#8911 boykopovar#8912 boykopovar#8913 boykopovar#10382 (PPSA26344 world, 60-present windows)
|
I've finished the second round of world captures I mentioned, this time with 60-present windows (the first round's 16-present windows were too noisy to use). All ten are warm runs of PPSA26344 v1.008 on our own tree (085bd8f, which carries all six of these changes; not With the change switched off, the frame p50 was 1,646 ms against 1,867 and 1,605 ms in the A runs on either side (mean 1,736), and GPU busy was 858 against 955 and 906 ms per present (mean 930). That's within the spread of its two A runs (1,867 and 1,605 ms, 15 % apart), so this world capture doesn't separate the two sides, much like @Dextroid17's title-menu runs on These are all on one tree, so they don't replace a Files are on our media branch (the comment box can't take 35 MB traces):
|
…ort the walks HeldReadQueries counts every query, as main's QueuedIndexReadOrder test expects since boykopovar#8911; behind the prefilter it missed the queries the prefilter answered. HeldReadWalks counts the locked walks, and the [draw] pipelined line prints both per report.
…t-in switches Main keeps resident linear targets and layer-scoped refreshes on by default; our tree makes them opt-in (APS5_RESIDENT_LINEAR, APS5_LAYER_REFRESH). The linear_target tests now run with APS5_RESIDENT_LINEAR=1, draw_bindings also with APS5_NO_READ_ONLY_LEASE_SKIP=1 (our read-only lease skip records the store in the open batch instead of syncing, which the test counts), and the depth_plane_partial_store pair with APS5_LAYER_REFRESH=1. Main's new check that an empty flush asks for no held reads (boykopovar#8911, merged without a switch) is skipped in our APS5_NO_HELD_READ_SKIP variant. AI-assisted: yes
What
Since #6914,
StorageTexture::FlushPendingasksDrawPipeline::HeldReadsfirst on every call. That takes the draw pipeline's mutex and walks the read ranges of every queued draw. Most flushes come from sampled-texture lookups and storage refreshes over memory with no pending results, and those return false without storing or publishing anything, held or not. In a Yōtei profile on our tree the check cost the draw commit thread about 3.3 s per 120 s, 2.1 s of it in the winpthreads mutex.FlushPendingnow returns false before the check when nothing would be stored: no pending image with a unit in the range, none being flushed, and no unit shadow over it when the scope publishes. That's the same answer the old path gives in that case.HeldReadsfirst, so fix(agc): order deferred write-backs after queued draws' index reads #6914's ordering is unchanged.DrawPipeline::HeldReadQueriesreturns the existing query counter, for the test.[storage]line's "held for a queued draw read" and "pretest skipped" counts no longer include flushes that had nothing to store.Overlaps: #6615 renames
refreshingtoRefreshing::Get(), which the new check reads too, so whichever lands second needs that one-word change. #6682 changesFlushPending's signature right next to these lines (textual only).Tested
-DBUILD_TESTING=ON, RTX 3080 Laptop, based onmain7ab4b2e: ctest 1824/1828. The 4 failures (log_macros,log_macros_timestamps,guest_kqueue, andagc_driver_image_array_window_past_layer_limit, which doesn't compile with MinGW here) fail onmaintoo.agc_driver_queued_index_read_ordernow also flushes a range with no pending results while an image is pending elsewhere, and checks thatHeldReadswasn't asked. Withmain'sTexture.cppit fails: "a flush with nothing to store asked the draw pipeline for held reads".main: 1760/1780; the same 20 fail onmain(WSL has no userfaultfd write watching).main, with perf(agc): skip the queued-draw read check when a storage flush stores nothing #8911, perf(agc): give small device-local buffers a pool tier of their own #8912 and perf(agc): prefer a pooled buffer of the requested exact size #8913 switched on and off together in one in-run open-world A/B (9+9 phases): 6.17 vs 5.16 presents per 10 s (paired -0.95 +- 0.20 SE) for the combined set. This PR's own counter in that run: 948k flushes skipped the check in the on phases (a counter in our tree, not in this diff).mainvs this change, measured by @Dextroid17 (thanks), in this comment: Ghost of Yōtei title menu and loading, RTX 3080 Ti, Linux,APS5_TRACE_SECONDS=20:30, cleared shader cache, main/change interleaved three times each. Frame p50 160.1 vs 158.9 ms (mean of 3), GPU busy 75.4 vs 73.9 ms per present: within the run-to-run spread, so no speedup on that scene. The traces andtrace_digest.pyoutput are attached there. The two summary lines below are his medianmainrun and the closest change run. I only fixed thetitlefield, which the summary writer had double-encoded.aps5-summary.jsonl,main2b3baac and #8911 bfd4634c88da{"commit":"2b3baacdba51","dirty":false,"env":{"APS5_TRACE_DIR":"<path>","APS5_TRACE_SECONDS":"20:30"},"gpu":"NVIDIA GeForce RTX 3080 Ti","driver":"NVIDIA 615.78.08","os":"Linux 7.3.0-2-cachyos","cpu":"11th Gen Intel(R) Core(TM) i9-11900K @ 3.50GHz","cpu_threads":16,"memory_mib":31912,"title_id":"PPSA26344","title":"Ghost of Yōtei","content_version":"01.008.000","resolution":"3840x2160","window":{"spec":"seconds 20:30","first_present":156,"ms":141414.646},"presents":56,"frame_ms":{"p50":159.802,"p90":225.49,"p99":132069.728,"max":132069.728},"gpu_busy_ms_per_present":74.76,"worker_busy_pct":{"queue worker 0x0":6.574,"queue worker 0x52":1.44,"queue worker 0x20":1.539,"queue worker 0x53":1.496,"queue worker 0x48":0.574,"queue worker 0x30":4.501,"queue worker 0x38":5.184},"top_phases_ms_per_frame":{"Shader.PrepareArtifact":18054.9,"Driver.Packet":533.912,"Driver.Packet.dispatch":245.568,"Driver.Packet.memory_wait":217.322,"Driver.Dispatch":156.637,"Resources.Complete":60.799,"Vulkan.Dispatch":58.066,"Vulkan.Dispatch.shader_resources":56.567},"trace_dropped":false,"trace":"aps5-trace-2b3baacdba51-155960.json.gz"}{"commit":"bfd4634c88da","dirty":false,"env":{"APS5_TRACE_DIR":"<path>","APS5_TRACE_SECONDS":"20:30"},"gpu":"NVIDIA GeForce RTX 3080 Ti","driver":"NVIDIA 615.78.08","os":"Linux 7.3.0-2-cachyos","cpu":"11th Gen Intel(R) Core(TM) i9-11900K @ 3.50GHz","cpu_threads":16,"memory_mib":31912,"title_id":"PPSA26344","title":"Ghost of Yōtei","content_version":"01.008.000","resolution":"3840x2160","window":{"spec":"seconds 20:30","first_present":155,"ms":141141.748},"presents":55,"frame_ms":{"p50":159.861,"p90":221.298,"p99":131927.011,"max":131927.011},"gpu_busy_ms_per_present":72.394,"worker_busy_pct":{"queue worker 0x0":6.425,"queue worker 0x20":1.489,"queue worker 0x52":1.359,"queue worker 0x53":1.527,"queue worker 0x30":4.41,"queue worker 0x38":5.088,"queue worker 0x48":0.454},"top_phases_ms_per_frame":{"Shader.PrepareArtifact":18371.997,"Driver.Packet":530.589,"Driver.Packet.dispatch":245.406,"Driver.Packet.memory_wait":211.582,"Driver.Dispatch":158.985,"Resources.Complete":62.124,"Vulkan.Dispatch":57.12,"Vulkan.Dispatch.shader_resources":55.56},"trace_dropped":false,"trace":"aps5-trace-bfd4634c88da-139442.json.gz"}Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file.mdfiles or images added to the repository (attach them to this PR)