Skip to content

perf(agc): run the dispatches a compute ring leaves unordered side by side - #9176

Open
Celegans12 wants to merge 1 commit into
boykopovar:mainfrom
Celegans12:perf/agc-dispatch-overlap
Open

Celegans12 wants to merge 1 commit into
boykopovar:mainfrom
Celegans12:perf/agc-dispatch-overlap

Conversation

@Celegans12

@Celegans12 Celegans12 commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

What

Every dispatch records a barrier before and after itself, so dispatches the game leaves unordered never overlap on the host GPU, and on NVIDIA each barrier drains the GPU.

  • A dispatch of a compute ring (queue != 0) is a candidate when only SET_SH_REG and plain NOPs lie between it and the ring's previous dispatch in the same submission. Queue 0 is unchanged.
  • A candidate joins the open run (no leading barrier; the run's trailing barrier waits for the next other command) only when its accesses are disjoint from the run's: bound buffer ranges as reads, written ranges as writes, storage images (and sampled views of them) by image; reads against writes and writes against writes conflict. Address-based and BDA builds count as writing all memory. A run never takes one resources object twice.
  • Indirect, device-memory LDS, thread-dimension, split-grid, staged and checkpointed dispatches never join.
  • GPU work a dispatch records before itself (texture refreshes, copies, storage flushes) goes through Recorder::Commands, which closes the run first.
  • APS5_NO_DISPATCH_OVERLAP=1 records every dispatch as before.

Overlaps (no ordering dependency; whichever lands second adds the condition):

Tested

  • Windows 11 Pro, MinGW-w64 GCC 15.2.0, RTX 3080 Laptop, based on main cc00785: ctest 1886/1892 (the 6 failures fail on main too: log_macros x2, three agc_driver_sample_order, guest_kqueue). Linux (WSL, lavapipe) job on the merge: 1823/1843, the same 20 fail on main.
  • Validation layer (VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation ANYPS5_NO_SHADER_CACHE=1 ANYPS5_REQUIRE_VULKAN=1 ctest -V -R dispatch): main 12/12, this head 14/14; the loader shows the layer added, no "was not found", no VUID- on either.
  • agc_driver_dispatch_overlap: four unordered builds share one run (3 join); with CS partial flushes none joins; RAW, WAR and WAW pairs with only SET_SH_REG between them don't join and get the ordered result; a disjoint pair joins; _off expects none. Without the range check the RAW case fails "1 joined a run, expected 0".
  • Main vs change, driver microbenchmark (8 unordered single-group dispatches of a 32,767-iteration loop, submit to results, median of 40 rounds x3): main 12.5 ms, this PR 1.79 ms; with CS partial flushes 12.3 vs 12.8 ms.
  • Feature on/off, our own tree (not main): PPSA26344 overlap off added ~146 ms GPU per frame (+19 %), presents unchanged (CPU-bound). No main-vs-change game scene yet: plain main stops on Yōtei's loading screen (~160 s) and later aborts on a 10_11_11 blend (feat(agc): blend into 11_11_10 float color targets in the pixel shader #9020 follow-up in progress).
  • Not tested: Intel, console behaviour.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Fixes: none
  • Unblocks: none
  • GPUs tested: NVIDIA GeForce RTX 3080 Laptop GPU, driver 610.62, Windows 11 Pro; lavapipe (Mesa 25.2.8, WSL Ubuntu 24.04)
  • AI-assisted: yes

@github-actions github-actions Bot added perf Performance change perf numbers missing perf pull request without a before and after summary line labels Oct 21, 2026
@github-actions

Copy link
Copy Markdown

This pull request is labeled perf, so it needs the summary line of a capture on main and one with the change, from the same title, scene and machine, as the Performance report form asks. Please paste both aps5-summary.jsonl lines, attach the two traces and add the output of tools/trace_digest.py.

@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.

Pull request Conflicting files (lines on main) Same exports Same new files
PR 7449 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp L4870, L4875, L4940-4945
PR 7920 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp L4939-4945
PR 9685 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp L4802
PR 9852 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp L5170
PR 9879 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp L4802

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.

Pull request Shared files not compared
PR 1191 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 1368 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 1395 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 2434 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/GuestBufferMemory.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 4040 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 4072 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 4448 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Packets/PacketExecution.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/GuestBufferMemory.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 4449 core/libs/prx/libSceAgcDriver/Graphics/include/GuestBufferMemory.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 4472 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 5021 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 5115 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Packets/PacketExecution.cpp
PR 5371 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 5431 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Packets/PacketExecution.cpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/Recorder.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Recorder.cpp
docs/dev/ENVIRONMENT.md
PR 5441 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 5609 core/libs/prx/libSceAgcDriver/Graphics/include/Recorder.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Recorder.cpp
PR 5925 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Packets/PacketExecution.cpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 6044 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6169 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6186 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/GuestBufferMemory.hpp
core/libs/prx/libSceAgcDriver/Graphics/include/Recorder.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Recorder.cpp
docs/dev/ENVIRONMENT.md
PR 6187 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6188 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Packets/PacketExecution.cpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 6192 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 6194 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 6197 core/libs/prx/libSceAgcDriver/Graphics/include/GuestBufferMemory.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 6202 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 6209 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6223 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 6280 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6292 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Packets/PacketExecution.cpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/Recorder.hpp
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Recorder.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 6300 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6412 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 6481 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/GuestBufferMemory.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 6501 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Packets/PacketExecution.cpp
PR 6539 core/libs/prx/libSceAgcDriver/Graphics/include/Recorder.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Recorder.cpp
PR 6548 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 6565 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 6615 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Packets/PacketExecution.cpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/Recorder.hpp
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Recorder.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 6642 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6741 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6788 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 6804 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 6808 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6868 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6879 docs/dev/ENVIRONMENT.md
PR 6924 docs/dev/ENVIRONMENT.md
PR 6960 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 6977 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 7201 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 7275 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 7457 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/GuestBufferMemory.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
docs/dev/ENVIRONMENT.md
PR 7604 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
PR 7689 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 7705 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
PR 7803 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/Recorder.hpp
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Recorder.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 7814 docs/dev/ENVIRONMENT.md
PR 8026 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 8077 docs/dev/ENVIRONMENT.md
PR 8246 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
PR 8365 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 8484 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
PR 8527 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 8542 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
PR 8552 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 8592 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 8658 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 8672 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 8998 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 9133 docs/dev/ENVIRONMENT.md
PR 9356 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Recorder.cpp
docs/dev/ENVIRONMENT.md
PR 9387 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Recorder.cpp
docs/dev/ENVIRONMENT.md
PR 9431 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 9432 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 9489 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 9592 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 9669 docs/dev/ENVIRONMENT.md
PR 9672 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 9673 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 9674 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 9675 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 9676 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/ENVIRONMENT.md
PR 9891 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 9892 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 9893 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 9895 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp

@janzezno

Copy link
Copy Markdown
Contributor

Run on AMD hardware.

Host: Arch Linux, kernel 7.2.11, AMD Radeon RX 7900 GRE (RADV NAVI31), Mesa 26.2.5, GCC 16.2.1, Release, BUILD_TESTING=ON.
main cecb540a6; PR head 0c930692a merged on top (clean merge).

ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation ctest --test-dir build -j6 -V -R 'dispatch|recorder|compute|idle_store|pipelined'
  • main: 38 of 38 pass. PR: 40 of 40 pass, including the new agc_driver_dispatch_overlap and agc_driver_dispatch_overlap_off.
  • No VUID- messages in either run, so the deferred and skipped barriers draw no synchronization errors from the validation layer on RADV. The layer loaded in both runs.
  • This was one pass of each test with six running at a time, not a repeated stress run.

@CnRJay CnRJay left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The microbenchmark is a real signal (8 independent dispatches 0.80 ms against 6.3 ms with a barrier between each pair on an RTX 3080 Laptop). The design decides overlap from the absence of packets the game wrote, and that is the wrong evidence.

  • "Unordered" here means no packet between the two dispatches other than SET_SH_REG and NOP. That says the game didn't ask for ordering; it does not say the dispatches are independent. Titles that skip a CS_PARTIAL_FLUSH/ACQUIRE_MEM between two dispatches may still depend on the second starting after the first has launched, and nothing in the PR shows that none does. Before this PR the emulator imposed full ordering and hid that; now a dispatch that reads what the previous one wrote through the same memory (not the same resources object) runs concurrently with it. The PR's own tests only check that dispatches over separate resources keep their results.
  • The emulator already has the evidence the PR needs: the read and write ranges of each dispatch (PassHazards does it for draws in one render pass, and the staged-element code knows each element's extent). Overlap a dispatch only when its ranges are disjoint from the run's, and treat unknown accesses (BDA, indirect) as conflicting, the way PassHazards does. That makes overlap a proven-independent case and costs one range check; the packet-pattern rule makes it a guess. Please add that check, and a test where dispatch B reads what A writes, with only SET_SH_REG between them, and requires B to see A's result.
  • The only measured effect on a game is in "our own tree (not main)": overlap off added about 146 ms of summed GPU time per frame (+19%) on PPSA26344, with presents unchanged because the scene is CPU-bound. That is a GPU-time number on a scene where the frame rate doesn't move. Post the summary lines of main and this PR from the same scene, and one GPU-bound scene where the benefit would show in frame time.
  • NVIDIA only. AMD and Intel hardware run unordered dispatches differently; an AMD run of agc_driver_dispatch_overlap and a game scene would show it's not specific to the NVIDIA barrier cost.

@CnRJay CnRJay left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A data point for the hazard question in my earlier review: #9287, stacked on this PR, says "PPSA26344 v1.008: renders correctly in our tree with this change (geometry broke before the guards)" and adds a rule that "a dispatch does not join when one of its ranges overlaps a range of the run" when one side is a staged copy. So overlapping dispatches already produced wrong geometry on this title once the copies were allowed inside a run.

That shows the dispatch overlap in this PR needs the same guard in the base case: a dispatch must not join an open run when its read or write ranges overlap the ranges of the run (reads against writes, writes against writes), and unknown accesses (BDA, indirect) must conflict, not only the staged-copy case #9287 covers. Please add that check here, with a test where dispatch B reads what A wrote with only SET_SH_REG between them, rather than leaving it to a follow-up that depends on this one landing first.

@Celegans12
Celegans12 force-pushed the perf/agc-dispatch-overlap branch from 0c93069 to 49625ed Compare October 21, 2026 21:45
@Celegans12

Copy link
Copy Markdown
Contributor Author

Thanks, you're right that the packet pattern was the wrong evidence. No CS_PARTIAL_FLUSH between two dispatches only says the game didn't ask for ordering, not that the dispatches are independent, and #9287's geometry history shows what happens when that gap is left open. I've amended the commit so a dispatch joins an open run only when its accesses are disjoint from the run's: every bound buffer range counts as a read, every written range as a write, and storage images (including sampled views of them) are compared by image. Reads against writes and writes against writes conflict. An address-based or BDA build counts as writing all memory, and indirect, LDS, thread-dimension and staged dispatches never join.

agc_driver_dispatch_overlap now has the case you asked for: B reads the buffer A just wrote with only SET_SH_REG between them, and it must not join and must see A's values. There are also write-after-read and write-after-write versions, and the same pair over disjoint buffers still joins. With the range check taken out, the read case fails with "1 joined a run, expected 0" in 3 of 3 runs. To be honest, its data check still passed in those runs, probably because a single 64-lane group finishes before the next one starts, so the join count is what actually guards it. #9287 now relies on this base check instead of its own rule for staged copies.

You're also right that the main-vs-PR summary lines from one scene and a GPU-bound scene are still owed. In the part of Yotei's world we can reach we're CPU-bound in the committer, so frame time won't move there; I'll post both summary lines and look for a GPU-bound spot. We don't have AMD hardware either. Could someone with an AMD card run agc_driver_dispatch_overlap and agc_driver_dispatch_overlap_off?

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review

I reviewed the dispatch eligibility, access-range conflict checks, deferred barrier lifecycle, and the added ordering/hazard cases. I did not confirm a behavioral defect in the read/write conflict predicate from static inspection. I’m requesting changes because the branch is far behind current main, the performance report does not yet meet the repository’s evidence rule, and some active overlaps need to be recorded and coordinated.

Bring the branch and validation current

This head is 721 commits behind current main (merge base de4ef842b5). The tests in the description were run against that old base. Please rebase on current main, resolve any conflicts, and rerun the focused dispatch tests on both main and this head.

This changes the AGC driver, so the PR checklist also requires the focused tests on both revisions with VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation, ANYPS5_NO_SHADER_CACHE=1, and ANYPS5_REQUIRE_VULKAN=1 under ctest -V, including a comparison of new VUID- messages and confirmation the requested validation layer loaded. The reported Windows/WSL test counts and dispatch cases are useful, but the description does not report this comparison.

Performance report

The repo requires a perf PR to provide valid summary lines for main and the change from the same machine and scene, with traces. The current perf numbers missing label reflects the gap: the PPSA26344 result compares the feature enabled/disabled in “our own tree (not main),” and the 8-dispatch microbenchmark is not a main-versus-change scene report.

Please add same-scene, same-machine main and rebased-head summary lines and traces as described by the performance issue form. Keep the enabled/disabled run as a useful feature-isolation result, but label it separately from the required main comparison.

Open overlaps

The generated overlap report lists currently open #6946, #9508, and #7449 in code changed here; the PR body currently records #7920 and mentions #8278/#8992. In particular, #6946 changes packet execution ordering in the same function, #9508 is stacked on #6946, and #7449 touches the dispatch recording/barrier path. Please update the overlap notes, agree on integration order with the affected authors, and add a Depends on entry if this branch actually depends on another PR. The #7920 barrier interaction is already called out; please preserve that coordination as well.

Checks

  • git diff --check: passed.
  • tools/check_conventions.py against current main: passed.
  • Current CI: eligibility, conventions, labels, and report passed; Linux, Windows, register-context, relinker, ASan relinker, and write-watch jobs were skipped.
  • I did not produce a local build/runtime result for this head in this session. The runtime results in the PR description are author-reported and are from the older base above.

The test matrix and explicit APS5_NO_DISPATCH_OVERLAP control are useful. I’ll revisit after the current-base validation, performance comparison, and overlap notes are updated.

Celegans12 added a commit to Celegans12/AnyPS5 that referenced this pull request Oct 22, 2026
…_NO_OVERLAP_RANGE_CHECK=1 off; an APS5_AB switch)

Port of boykopovar#9176's range check: a dispatch joins an open run only when its
buffer ranges and storage images are disjoint from the run's (reads
against writes, writes against writes); address-based/BDA builds and
bindless image dispatches count as accessing everything. [overlap-range]
counts refusals, and conflicts that joined while the switch was set.

AI-assisted: yes
… side

Every dispatch records a barrier before and after itself, and on NVIDIA
any barrier between two dispatches drains the GPU.

A dispatch of a compute ring (queue != 0) with only SET_SH_REG and plain
NOPs between it and the ring's previous dispatch in the same submission
may join that dispatch's run: it records no leading barrier, and the
run's trailing barrier is deferred until any other command records it.
It joins only when its buffer ranges and storage images are disjoint
from the run's (reads against writes, writes against writes); an
address-based or BDA build counts as accessing everything, and a run
never takes the same resources object twice.
APS5_NO_DISPATCH_OVERLAP=1 turns it off.

AI-assisted: yes
@Celegans12
Celegans12 force-pushed the perf/agc-dispatch-overlap branch from 49625ed to baae58f Compare October 22, 2026 12:03
@Celegans12

Copy link
Copy Markdown
Contributor Author

Thanks for the careful pass, especially the reminder that the validation-layer comparison is part of the checklist. I hadn't run it. I've rebased onto current main (cc00785, with #8992 in) and restacked #9287 and #9289. The rebase changed no lines of the PR's diff. I moved the ring-order hook two lines down so it no longer touches the lines #6946 edits.

Validation: I ran VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation ANYPS5_NO_SHADER_CACHE=1 ANYPS5_REQUIRE_VULKAN=1 ctest -V -R dispatch on main and on the head. With VK_LOADER_DEBUG=layer the loader shows the layer being added from the SDK 1.4.363 registry entry, and there's no "was not found" message. main passes 12/12 and the head 14/14 (the same 12 plus the two overlap tests), with no VUID- message on either. That's in the body now, together with fresh Windows and Linux runs on the new base.

On performance, I've split the two results. The game number stays as a feature on/off result from our own tree, and it's labelled that way. A main-vs-change game scene isn't possible yet: plain main doesn't reach Yōtei's world. It stops on the loading screen at about 160 s and later aborts on a 10_11_11 blend; a follow-up to #9020 is in progress. What I can give for main against this head is a driver-level microbenchmark: 8 unordered single-group dispatches of a loop, timed until the results are visible on the CPU. That's 12.5 ms on main and 1.79 ms here, and 12.3 ms vs 12.8 ms when a CS partial flush separates them. The harness is on our fork (bench/dispatch-overlap, not for merge) if you want to rerun it. I'll post game summary lines once main gets into the world.

On overlaps, @AlxcBTW @hugodearaujo @Raghav314, I don't think there's an ordering dependency in either direction. Whoever lands second adds one condition:

If any of you would rather this one went first or last, tell me and I'll rebase to match.

Details

@hugodearaujo

Copy link
Copy Markdown
Contributor

@Celegans12 no preference on order from #7920's side, and your condition is the right one. With APS5_GPU_CHECKPOINTS on a device without the NV extension, #7920 writes a top-of-pipe marker before each dispatch and a bottom-of-pipe marker after it. On a lost device it lists the dispatches between the last finished marker and the last reached one. Today the trailing barrier keeps that to the one dispatch in flight. In a run, all of the run's dispatches can be in flight together, so the report would list them all without saying which one faulted.

So a dispatch that writes markers should stay out of runs, as the NV checkpoint does: state->bufferMarker == nullptr next to state->checkpointMarker == nullptr in overlapCapable. If #9176 lands first, I'll add it to #7920 when I rebase. If #7920 lands first, it's yours to add.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agc libSceAgc* build docs perf numbers missing perf pull request without a before and after summary line perf Performance change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants