Repository navigation
fix(agc): run an indirect buffer as it is when execution reaches it - #11346
milescoviello wants to merge 12 commits into
Conversation
MarcZX10
left a comment
There was a problem hiding this comment.
This branch is 1 commit ahead and 168 commits behind current upstream/main (14c99b52ace303eef1667764670d1d1540140b3d). The merge preview is clean, but the sync checker reports shared changes to Driver.hpp and docs/dev/debt/libSceAgcDriver.md since its merge base. Please refresh onto current main and rerun the focused GPU-written-indirect-buffer regression and related AGC execution tests on the resulting exact head. I have not completed the full source review yet, so this request is limited to the outstanding current-main validation.
3715420 to
9f3361d
Compare
MarcZX10
left a comment
There was a problem hiding this comment.
The rebase resolves the sync request, but I found an execution-order bookkeeping gap in the new dynamic rewrite path.
noteHeldAtSubmit runs only while the original flattened commands are scanned in reserveOutputs. For an indirect buffer copied as NOPs, a later-spliced WRITE_DATA/RELEASE_MEM is absent from submission.labelWrites and from QueueWorker::unfinishedWrites; the rewritten command path also does not update heldAtSubmit. A concrete sequence is an earlier submission whose GPU-written indirect buffer later gains a label write to address X, followed by a same-queue wait on X whose condition is true when submitted. Because the writer is not registered, noteHeldAtSubmit can mark the wait as held; waitMemory deliberately returns on heldAtSubmit even if the condition has since become false. This can let the later wait pass before the required value is restored.
Please register the newly expanded label writes and waits with the same ordering metadata as ordinary submitted commands (including the corresponding unfinished-write lifetime), or otherwise ensure dynamic commands cannot use the held-at-submit shortcut based on incomplete writer tracking. Add a focused regression that starts with a NOP-filled indirect buffer, has preceding GPU work replace it with a label write, and verifies a following same-queue wait does not pass using a stale submit-time condition. The current regression proves the indirect command executes, but not this wait-ordering case.
|
@MarcZX10 thanks, you're right. A label write that a rewrite splices in was never registered, so a later same-queue wait could stay held on a submit-time value. I have the fix and the regression you describe locally, and they're being tested now:
I'll push once the red run (the test on the current head) and the green runs are in, with the validation layer and my Windows VM on the new exact head. AI-assisted: yes (Claude Code) |
867f93d to
4f55aae
Compare
MarcZX10
left a comment
There was a problem hiding this comment.
The latest head includes the label-writer bookkeeping and regression for the stale held-wait case from my earlier review. I found a separate nested-indirect-buffer ordering issue in the refresh path.
copySegment recursively expands an indirect buffer and only calls noteIndirectSegment after the recursion returns (for example, the COND_INDIRECT_BUFFER path at Submission.cpp:214-218). Thus when a copied parent buffer contains a child indirect buffer, the child segment is appended before the parent segment even though the parent starts earlier in submission.commands. The same order is retained when rewritten segments are spliced at Submission.cpp:324-327. execute advances a single nextSegment index and assumes the next entry has the earliest start; if the child start is later than the parent start, the parent is skipped at its execution position and never refreshed.
This is observable when a rewritten buffer contains an indirect call whose command range is itself GPU-written by work earlier in the stream: the child can execute the submit-time copy rather than the commands present when execution reaches the parent’s call. Please keep indirectSegments ordered by start after initial recursive expansion and after each splice, and add a regression with a GPU-written parent that contains a nested indirect buffer whose contents are also updated before its call. The current tests cover direct and conditional buffers plus the held-wait case, but not this nested refresh ordering.
|
@MarcZX10 thanks for reading the refresh path this closely. I've made the order explicit, and added the regression. Why I think the order held already. The change (b5c1a82, not pushed yet): The regression (a fourth case in
A mutant whose splice drops the nested entries is queued to show the case fails without them, with the 11 tests 3 times, the validation layer and my Windows VM on the new head. I'll push and post once they're in. AI-assisted: yes (Claude Code) |
MarcZX10
left a comment
There was a problem hiding this comment.
Correction: I overlooked the guard in noteIndirectSegment. A parent buffer whose nested call was expanded is not recorded as a segment, because the flattened commands no longer match the parent’s original words. The recorded leaf segments follow the flattened traversal order, and the splice replaces one segment with the nested entries before shifting later entries. That means my reported child-before-parent execution ordering is not substantiated; I withdraw that changes-requested finding.
The nested GPU-written regression described in your comment will be useful confirmation of this reasoning. I have not run it independently, so I’m leaving this as a comment rather than approving before the promised exact-head tests are available.
|
@MarcZX10 thanks for the correction. I'll keep the explicit sort, since it makes the order independent of that guard, and the nested regression as the confirmation. Both are in the next head, with the exact-head results (the mutant without the nested entries, the 11 tests 3 times, the validation layer and my Windows VM). Those are queued behind another PR's runs on the same machine, and I'll post them here when they're in. AI-assisted: yes (Claude Code) |
|
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.
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.
|
4f55aae to
b5c1a82
Compare
|
I rechecked the new exact head There is a new integration point to refresh: current |
|
@MarcZX10 thanks. I've rebased onto The focused set is queued at that exact head: the 11 tests 3 times on Linux, the Khronos comparison against 204c674, and my Windows VM. It runs after the VM finishes its current job. I'll push and post the results together. AI-assisted: yes (Claude Code) |
b5c1a82 to
25000ed
Compare
|
@MarcZX10 pushed
One flake to note. On the VM, AI-assisted: yes (Claude Code) |
|
The updated exact-head results address the focused-test request: the author reports the 11-test set 3/3 on Linux and Windows, with baseline/PR counts and Khronos validation showing no VUIDs. The intermittent |
25000ed to
5dd3166
Compare
|
@MarcZX10 done: rebased onto AI-assisted: yes (Claude Code) |
MarcZX10
left a comment
There was a problem hiding this comment.
Reviewed exact head 5dd3166c16d0c32c282a3c88865d76891f704f54 against current main b27cc8416f820e40ce187f165d34138e24373dd7.
The updated implementation now registers label writes from dynamically refreshed indirect commands in the submission and worker tracking, including the held-at-submit ordering path. Its regression coverage exercises direct and conditional indirect buffers, nested buffers, and the stale held-wait case. I previously withdrew my nested-segment ordering finding after checking the guard and traversal, and the author has since reported the nested refresh regression passing.
The author rebased onto current main and reports that the only change on a touched path since the tested base was the debt document. git range-diff 204c6747d0a1cbaf932def3dea0778810cc3935e..25000ed852e52da6cfbf4bb9cb7e8ac91dbe8258 b27cc8416f820e40ce187f165d34138e24373dd7..5dd3166c16d0c32c282a3c88865d76891f704f54 shows the single implementation commit unchanged by the rebase.
The author reports the focused 11-test AGC set passing 3/3 on Linux and Windows, with baseline/change counts and Khronos validation showing no new VUIDs. I did not independently run those GPU tests. Current hosted eligibility, conventions and report checks pass; product jobs are skipped by path policy. I found no outstanding blocking issue on this head.
AI-assisted review.
|
A Windows run of the 11-test focused set on real hardware: Windows 11 Home 10.0.26200, WinLibs GCC 15.2.0 r7 (MinGW-w64 UCRT), Release. I merged
AI-assisted: yes (Claude Code) |
|
@ycbuzi thank you. Three GPUs and the control on the 4070 are a solid check. I've added them to Tested and the GPUs line. The For that comparison: the test doesn't submit an AI-assisted: yes (Claude Code) |
|
@milescoviello The two follow-ups from #11346 (comment), on the Radeon iGPU (
All four AI-assisted: yes (Claude Code) |
|
@MarcZX10 one more commit after your approval, What happened. In a MXGP 26 run of Change. Expanding, validating and reading the register lists of the new contents is now in a try block. On failure the buffer runs as it was copied, which validated at submit, and the first eight cases are logged. Tests.
AI-assisted: yes (Claude Code) |
|
A Windows rerun of the new head on the same three devices:
AI-assisted: yes (Claude Code) |
Resolves the technical debt file: keeps this branch's COND_INDIRECT_BUFFER and indirect buffer entries and main's two label entries. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Rerun on
The validation set is the same as the Windows VM's ( AI-assisted: yes (Claude Code) |
XairRrR
left a comment
There was a problem hiding this comment.
Re-checked — approved
The only new commit, 4143f1b4a0, merges main into the branch and resolves a conflict in docs/dev/debt/libSceAgcDriver.md. The PR's own code and tests have not changed since ddb59eefaf, which I approved last time.
What changed since my last review
- Commits 1–8 are unchanged (all
=in the range-diff). The new commit is a merge ofmain6cd2899cc6. - The PR's diff against
main086c0686c8is still the same 8 files. In the debt file it still changes theCOND_INDIRECT_BUFFERentry and adds the indirect-buffer entry.main's two label entries are kept next to them, as the author says. - In the discussion, the author reports the 17 focused tests passing 3 of 3 on this head, plus a paired Khronos run (10/10 base, 11/11 head, no
VUID-). I accept both as author-reported.
What I ran
Head 4143f1b4a03f8e41d608c577214e260a005dc015, main 086c0686c8adff3ee648fdbe34e0b0b647e1d511, merged tree 536d6128f5af8d324bb5c8bcbdb91b7ca47f13bf. Build: Release, GCC 14.2.0, Ninja, on Debian 13 (VM) with lavapipe (Mesa 26.1.6).
git diff --check 086c0686c8adff3ee648fdbe34e0b0b647e1d511...4143f1b4a03f8e41d608c577214e260a005dc015
python3 tools/check_conventions.py --base 086c0686c8adff3ee648fdbe34e0b0b647e1d511
env VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation ANYPS5_NO_SHADER_CACHE=1 ANYPS5_REQUIRE_VULKAN=1 VK_LOADER_DEBUG=error,warn,layer \
ctest --test-dir build -V -R "^agc_driver_image_gather_volume$"
# control: main's Driver.hpp, Submission.hpp, CommandValidation.cpp, PacketExecution.cpp, Submission.cpp
git show 086c0686c8adff3ee648fdbe34e0b0b647e1d511:<path> > <path>
ninja -C build -j32 -l32 tests/agc_driver_image_gather_volume_tests tests/agc_driver_pm4_tests tests/agc_driver_gpu_written_indirect_buffer_tests
env VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation ANYPS5_NO_SHADER_CACHE=1 ANYPS5_REQUIRE_VULKAN=1 VK_LOADER_DEBUG=error,warn,layer \
ctest --test-dir build -V -R "^agc_driver_image_gather_volume$"
ctest --test-dir build --output-on-failure -R "^agc_driver_pm4$|^agc_driver_gpu_written_indirect_buffer$"
# restore the merged files
git show 536d6128f5af8d324bb5c8bcbdb91b7ca47f13bf:<path> > <path>
ninja -C build -j32 -l32 tests/agc_driver_pm4_tests tests/agc_driver_gpu_written_indirect_buffer_tests tests/agc_driver_image_gather_volume_tests
ctest --test-dir build --output-on-failure -j8 --test-load 32 -R "^agc_driver_pm4|^agc_driver_gpu_written_indirect_buffer$"
git status --porcelain| Check | Result |
|---|---|
git diff --check |
Clean |
| Conventions | 0 errors. The same debt-length warning as before (indirect-buffer entry, 1124 characters) |
| Script build and tests (build.json) | Build OK. 2180 tests run: no new failures, no timeouts. The 7 known failures also fail on main. |
| Script validation comparison | Layer loaded in 783 of 784 tests and missing in none. One test has new VUID-s: agc_driver_image_gather_volume ("test not run on main") |
agc_driver_image_gather_volume with the layer, merged tree vs. main's production files |
The same 8 VUID-VkSamplerCreateInfo-addressMode{U,V,W}-* lines on both, and the test passes on both. So they come from main's newer gather test, not from this PR. |
^agc_driver_pm4… and agc_driver_gpu_written_indirect_buffer, merged tree |
17 of 17 pass |
| Worktree after restoring | Clean |
Negative control
With main's five production files and the PR's tests:
agc_driver_gpu_written_indirect_bufferfails:a COND_INDIRECT_BUFFER ran the command buffer as it was at submission … the marker is 0.agc_driver_pm4fails:the packet after a taken COND_INDIRECT_BUFFER ran: the branch returned like a call.
With the merged files restored, both pass.
Previous findings
- PPSA22408 hang if merged alone: stays resolved. The jump commit is unchanged and #15465 is still under Depends on.
- Debt entry left out address-based readers: stays resolved.
preparecaptures every known target once per segment (core/libs/prx/libSceAgcDriver/Execution/src/Driver/Queues/Submission.cpp:435): still open, non-blocking, unchanged.CaptureRenderingWaitfailures are swallowed andrenderingWaitTargetsis never pruned: still open, non-blocking, unchanged.- Indirect-buffer debt entry is over 1000 characters (
docs/dev/debt/libSceAgcDriver.md:220): still open, non-blocking. The warning shows again. - Tests pinned the call behaviour of
COND_INDIRECT_BUFFER: stays resolved. - An empty taken branch still falls through, which the "does not return" debt sentence doesn't record (
Submission.cpp:215-223): still open, non-blocking, unchanged. - The jump changes what "runs as copied" means for every title that uses
sceAgcCbBranch: still open as a follow-up (a hardware oracle check), non-blocking.
New findings
Blocking
None.
Non-blocking
None.
Not verified
- PPSA22408 and MXGP 26: I launched no title. The garage results are mrfelek's, not on this exact head.
- #15465 itself: I did not review it or check whether it is merged.
- What the CP really does after a taken
COND_INDIRECT_BUFFER. - Windows, and GPUs other than lavapipe.
|
Windows and NVIDIA Blackwell run, for head
The failure, Not run: the Khronos validation layer is not installed on this machine, so this says nothing about VUIDs. PPSA30839 was not run. AI-assisted: yes. Claude Code ran the builds and tests and drafted this comment; the numbers are from the runs on this machine. |
|
@adam25136 thanks for the Blackwell run. AI-assisted: yes (Claude Code) |
✅ NVIDIA GPU test: passedPR head
Unstable on main (3, these also failed in recent main runs on this machine; not counted against this PR)Failing on main too (3, not counted against this PR)Validated but not compared (1, not in the main baseline's validation pass)Validation IDs already present on main (8 IDs in 527 tests)Skipped (50)ReproduceAutomated build and test on a contributor's NVIDIA machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs. |
✅ AMD GPU test: passedPR head
Unstable on main (2, these also failed in recent main runs on this machine; not counted against this PR)Failing on main too (7, not counted against this PR)Validated but not compared (1, not in the main baseline's validation pass)Validation IDs already present on main (8 IDs in 527 tests)Skipped (61)ReproduceAutomated build and test on a contributor's AMD machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs. |
…irect-buffer # Conflicts: # core/libs/prx/libSceAgcDriver/Execution/include/Driver/Driver.hpp
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Merged
AI-assisted: yes (Claude Code) |
|
@MarcZX10 @XairRrR
AI-assisted: yes (Claude Code) |
✅ NVIDIA GPU test: passedPR head
Failing on main too (2, not counted against this PR)Validated but not compared (1, not in the main baseline's validation pass)Validation IDs already present on main (13 IDs in 549 tests)Skipped (49)ReproduceAutomated build and test on a contributor's NVIDIA machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs. |
✅ AMD GPU test: passedPR head
Unstable on main (1, these also failed in recent main runs on this machine; not counted against this PR)Failing on main too (7, not counted against this PR)Validated but not compared (1, not in the main baseline's validation pass)Validation IDs already present on main (4 IDs in 557 tests)Skipped (59)ReproduceAutomated build and test on a contributor's AMD machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs. |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
AI-assisted: yes (Claude Code) |
✅ NVIDIA GPU test: passedPR head
Unstable on main (1, these also failed in recent main runs on this machine; not counted against this PR)Failing on main too (4, not counted against this PR)Validated but not compared (1, not in the main baseline's validation pass)Validation IDs already present on main (9 IDs in 595 tests)Skipped (53)ReproduceAutomated build and test on a contributor's NVIDIA machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs. |
|
Windows run of the current head, Head merged onto
Your 11-test set ( Red checks, each a local edit of the merged tree, 3 runs per GPU:
The results are the same on both GPUs. Non-blocking. Every case in Whole AGC set.
AI-assisted: yes (Claude Code) |
|
@Superseabas thanks for the Radeon iGPU and RTX 5070 Ti runs and the red-check table. That's the first AMD-driver Windows result since Good catch on the pipeline and finisher branches: every case reaches the refresh through AI-assisted: yes (Claude Code) |
What
The driver copies a submission's indirect buffers into one command stream when the submission is queued (
copySegment), but the CP reads an indirect buffer only when it reaches it. A buffer that work earlier in the stream fills was executed as it was before that work ran.MXGP 26 (PPSA30839) builds part of its command list on the GPU every frame:
ds_ordered_count, keeping only the records whose three counts multiply to a nonzero value.COND_INDIRECT_BUFFERthen runs that buffer.On
mainthe copy only ever saw the buffer's NOP fill (0xffff1000), so none of those commands ran (#9510). In a 45 s window of the 3D profile scene, all 161 such buffers were copied about 0.3 s before the packing dispatch that fills them ran. Read again when execution reached them, every one had changed and held nestedINDIRECT_BUFFERs.How
copySegmentnotes everyINDIRECT_BUFFERandCOND_INDIRECT_BUFFERit inlined unchanged (not chained or predicated): where its copy starts, its guest address and its size (Submission::indirectSegments).executereaches one,refreshIndirectSegmentreads it again only while queued GPU work writes its range: the draw pipeline or the draw finisher holds such work, or the recorder lists a writer of the range in its open or unfinished batches (PendingWriterSerial). It drains that work and reads the buffer throughGuestMemory::Read, which syncs pending GPU writes. That is when the CP reads an indirect buffer.COND_INDIRECT_BUFFERoutside aCOND_EXECrange replaces the rest of the buffer it is in, like a chainedINDIRECT_BUFFER:copySegmentstops copying that buffer once it has inlined the target. Before, it was flattened like a call, and the packets after the branch ran again after the target. Inside aCOND_EXECrange the packets after it are still copied. That the branch does not return is unverified on hardware; it is in the technical debt file.WAIT_REG_MEMgate, which the CP would read, also runs as copied; that is in the technical debt file.reserveOutputstakes one for every (video output, buffer) pair a rendering wait has targeted before (Submission::preparedWaits). A ticket taken at execution would also wait for flips that later submissions reserved, which can't complete first.WRITE_DATA,RELEASE_MEM) join the submission'slabelWritesand the queue'sunfinishedWrites, so a wait submitted later sees a writer; completion readslabelWritesafterexecute, so they're released with the submission. A wait already marked held at submit on one of those dwords, later in this submission or in one pending on the same queue, loses the mark and waits at execution. Waits inside a rewritten buffer are never held.mainwould have run. The first eight are logged.Overlap (
tools/pr_overlap.py,git merge-tree): files only. #10487, #10507 and #11207 also changeDriver.hppand merge cleanly with this. #10193 conflicts withmainalready. Many open PRs add entries todocs/dev/debt/libSceAgcDriver.md, none next to this one.Tested
Linux (Ubuntu 26.04.1, GCC 15.2, Release, RTX 4070 Ti, NVIDIA 615.71.09) unless noted.
This head
b11a1c2c63, on the same merge baseba5b5330b3, after the Hot Wheels report:agc_driver_gpu_written_indirect_buffer, for aCOND_INDIRECT_BUFFERand anINDIRECT_BUFFER: the submission waits on a CPU gate before the buffer. After it is submitted, the CPU writes aWRITE_DATAmarker into the buffer and opens the gate. The packet after the buffer must run and the marker must stay 0.e309c36252, this head's test file on the previous head's driver (15a4f95d4d): fails at the new check on Linux (1 of 1) and on the Windows VM (3 of 3):a COND_INDIRECT_BUFFER the CPU rewrote after its submission, with no GPU work before it writing the buffer, ran the rewritten commands instead of running as it was copied.video_out_flip_*tests skip in that environment.ba5b5330b3passes 31 of 31 and this head 32 of 32, no layer missing, 17 and 19 Vulkan devices created, noVUID-messages on either side.Head
82f3ada000: the same five commits rebased ontomainaaccd0ba39with no conflicts. The 32 area tests pass 3 of 3, the new case passes, and both negative controls fail on this exact head. Khronos validation: 22 of 22 onmainand 23 of 23 here, noVUID-messages. Windows 11 VM (GT 1030):main10 of 10 and this head 11 of 11, 3 of 3 each (details).Head
e593f32f86(oneandonlydean's and MarcZX10's reviews), test only:TicketWait::Waitrecords the ticket it waits for, andRewrittenWaitBeforeOwnFliprequires exactly{0, 1}(the seeded wait, then the rewritten wait on the first flip's ticket), so the rewritten wait must run. The 32 area tests pass 3 of 3. A mutant with the old placement (waits captured after the walk) fails with the 3 s timeout, and one that refuses every rewritten rendering wait fails withthey waited for {0}(details).Head
d93a040aa2(XairRrR's review): each indirect segment's rendering-wait tickets are now taken at its place in the submission. The new case (a rendering wait written into the buffer, then a flip of the same video buffer in the same submission, with a fake output whose waits give up after 3 s) passes. With the tickets taken after the walk again (7dc220b955) it fails on the 3 s timeout. The 32 tests of the area regex plus the flip tests pass 3 of 3. Validation layer (Khronos 1.4.363) over^agc_driver_gpu_written_indirect_buffer$|^agc_driver_pm4$|flip: the merge base46e54cf1f7passes 22 of 22 and this head 23 of 23. Neither log has a missing-layer line, the layer checked 4 and 6 devices, and neither side has aVUID-message. Windows 11 VM (GT 1030): the merge base passes 10 of 10 and this head 11 of 11, 3 of 3 each.Head
521bbc33c3, rebased ontomain46e54cf1f7. One conflict:mainmoved thereportSkipdeclaration inDriver.hppto the public section (03fcf73), next to the line where the second commit addsvalidate'sreportparameter. I keptmain's move and the parameter;git range-diffshows the first and third commits unchanged. The 11 tests pass 3 of 3. Windows 11 VM (GT 1030):main10 of 10 and this head 11 of 11, 3 of 3 each.Head
240c1c218b, rebased ontomain8c7cf82 (clean), adds a third commit after review: the held-wait case waits for an observed execution event instead of 500 ms. After opening the gate it polls, for up to 10 s, untilAgcDriverAwaitedWaits_nid_postfixreports the queue worker blocked on the label with reference 1, or until the marker turns 1. It then reads the label, which must still be 0 from the rewrittenWRITE_DATA, and only then sets it back to 1. The marker must have stayed 0 until then and be 1 after.Controls, 3 runs each, with a local switch that is not part of this PR:
APS5_CONTROL_EXECUTE_DELAY_MSsleeps at the start of everyexecute, and at 1000 ms every submission starts executing after the old 500 ms sample.erase_iflines inrefreshIndirectSegmentWithout the invalidation the new test fails, with and without the delay, at
a wait on a label that a rewritten indirect buffer before it sets to 0 passed on the value 1 it held at submission. The previous test passes under the delay, so it could not catch a missing invalidation when the worker started late.The 11 tests pass 3 of 3. Khronos validation 1.4.363: 10 of 10 on
main8c7cf82 and 11 of 11 on this head, noVUID-messages. Windows 11 VM (GT 1030):main10 of 10 and this head 11 of 11, 3 of 3 each.Head
199186dabdadded a second commit after review. In a MXGP 26 run with a local diagnostic on5dd3166c16, the title stopped at 48 s: a rewritten 44,019-dword list at 0x1078da8010, one of MXGP's GPU-built command lists, held a0x00000000header. The throw from the refresh'svalidatefailed the queue withunsupported PM4 packet type: header 0x00000000 at DWORD 39212 of 44019. Such contents now run as copied.agc_driver_gpu_written_indirect_buffer: after the submission, the CPU rewrites a gatedCOND_INDIRECT_BUFFER's target with a0x00000000header and aWRITE_DATA. The queue must keep running, the packet after the buffer must run, and theWRITE_DATAmust not. The test alone on5dd3166c16fails 2 of 2 with... failed the queue instead of running as it was copied: AGC driver: unsupported PM4 packet type: header 0x00000000 at DWORD 0 of 64.main4b1a9a3 and 11 of 11 on this head, noVUID-messages. Windows 11 VM (GT 1030):mainb27cc84 10 of 10 and this head 11 of 11, 3 of 3 each.199186dabdmerged ontomain9ff033b, the 11 tests withctest --repeat until-fail:3. RTX 4070 SUPER and GTX 1650 SUPER: 11 of 11, 3 of 3. RDNA2 iGPU: 10 of 11, 3 of 3, withagc_driver_pipelined_dispatchfailing once on the test(agc): agc_driver_pipelined_dispatch_item fails in about 1 of 70 Windows runs when VirtualAlloc puts its two targets in different 4 GiB regions #9680 fixture check. The new case logs itsruns as copiedline on every device and passes. Withmain's production files, the test fails on the 4070 with the original marker-0 message.Head
5dd3166c16:25000ed852rebased ontomainb27cc84, the same patch (git range-diffshows it unchanged). Since 204c674,mainchanged onlydocs/dev/debt/libSceAgcDriver.mdamong the touched files; both sides' entries are kept and conventions pass. The runs below are on25000ed852.Windows hardware (ycbuzi, Windows 11 Home 10.0.26200, WinLibs GCC 15.2.0 r7):
25000ed852merged ontomainb27cc84, the same tree as this head, the 11 tests withctest --repeat until-fail:3:main's four driver files, the new test fails on the 4070 with the marker 0, and the other 10 pass.1002:164e, AMD 32.0.21030.2001): 10 of 11 pass 3 of 3,agc_submit_progressincluded.agc_driver_pipelined_dispatchfailed once there; in 20 runs each it fails 2 of 20 onmainand 2 of 20 onmain+ this head, always at the fixture'sthe two targets do not share their high address dwordcheck before any dispatch, which is test(agc): agc_driver_pipelined_dispatch_item fails in about 1 of 70 Windows runs when VirtualAlloc puts its two targets in different 4 GiB regions #9680 (fixed by test(agc): keep pipelined dispatch targets in one address window #9696).agc_submit_progresspasses 20 of 20 on both.Head
25000ed852, rebased ontomain204c674 (clean; both sides' entries kept indocs/dev/debt/libSceAgcDriver.md). The 11 tests pass 3 of 3 on Linux. Khronos validation: 10 of 10 onmain204c674 and 11 of 11 on this head, noVUID-messages. Windows 11 VM (GT 1030):main10 of 10 and this head 11 of 11, 3 of 3 each.agc_submit_progress(in the set) failed twice on PR builds in about 100 runs, with its 2 ssubmission lost its real GPU completion storedeadline: once in a 3-run pass onb5c1a82490, and once within 15 repeats. It passed 20 more on that build and 60 of 60 on25000ed852, and 40 of 40 onmain. A further 100 runs each, onectestper run: 100 of 100 on this head5dd3166c16and 100 of 100 onmain4e43321, so 2 failures in about 280 PR-build runs against 0 in 140 onmain. It submits no indirect buffer, so the refresh path is never entered there. It has never failed on Linux. I read it as the 2 s deadline on a loaded VM, but I'm listing it.Previous head
b5c1a82490onmain14c99b5, after review: rebased, the held-wait bookkeeping added, andindirectSegmentskept sorted by start after the copy and after every splice.an indirect buffer called from a rewritten COND_INDIRECT_BUFFER ran as it was when the parent was read ... the marker is 0. The 11 tests pass 3 of 3 on this head.main14c99b5 and 11 of 11 on this head, noVUID-messages. The Windows VM run of this head is in a comment below.Previous head
867f93d9dc(same code as4f55aae4f8, which only shortened the debt entry):a wait on a label that a rewritten indirect buffer before it sets to 0 passed on the value 1 it held at submission. The 11 tests pass 3 of 3 on this head.main14c99b5 and 11 of 11 on this head, noVUID-messages. The Windows VM run of this head is in a comment below.Red/green: new
agc_driver_gpu_written_indirect_buffer. A dispatch writes aWRITE_DATApacket into a NOP-filled buffer, then aCOND_INDIRECT_BUFFER(and, in a second case, anINDIRECT_BUFFER) runs that buffer; the marker the packet stores must be set.WRITE_DATA label = 0into a NOP-filled buffer that aCOND_INDIRECT_BUFFERruns. The label starts at 1.label == 1and then writes a marker.COND_INDIRECT_BUFFERruns a NOP-filled parent.WRITE_DATA markerinto a second NOP-filled buffer, followed by anINDIRECT_BUFFERcall into it.main5b85225 fails in both runs:a COND_INDIRECT_BUFFER ran the command buffer as it was at submission, not as the dispatch before it wrote it: the marker is 0.Focused tests: the 11 tests matching
^agc_driver_gpu_written_indirect_buffer$|^agc_driver_pm4$|^agc_predication_tests$|^agc_submit_progress|^agc_driver_empty_indirect_skip$|^agc_driver_pipelined_dispatch$|^agc_driver_dispatch_differing_value_sets$|^agc_driver_graphics$|^agc_driver_gds_append_consume$|^agc_driver_depth_fast_clear_submit$pass 3 of 3.Khronos validation 1.4.363 over the same set, each arm run as
VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 ctest -R "$R" -V: 10 of 10 on the merge base5b85225ef3, 11 of 11 on this head, no layer missing, noVUID-messages on either. Correction (10-27): two tests of this set never load the layer.agc_driver_graphicsandagc_driver_pm4run on a test fixture's own device, so the clean result doesn't cover them. The test this PR changes,agc_driver_gpu_written_indirect_buffer(built at240c1c218b), creates a real device, as do the others; I countedPhysical device selectedper test.Windows 11 VM (GT 1030, driver 582.78, WinLibs GCC 15.2.0 r7), the same set: 10 of 10 pass 3 of 3 on the merge base and 11 of 11 pass 3 of 3 on this head; the new test runs there (not skipped).
MXGP 26 (PPSA30839), warm, 12 GB cap, the same scripted route to the 3D profile scene, release libraries:
main(16ff208 with a trace-only diagnostic): at 465 s the rider, the bike and the grass are black against a lit sky, as in AGC: MXGP 26 (PPSA30839) renders opaque surfaces black in its 3D scenes; only the sky and reflections are lit #9510.refreshIndirectSegment: it runs to the 480 s timeout. 883 rewritten buffers were read again and spliced in, with 1 to 4 rendering waits each, and none was kept as copied. At 478 s the rider is lit and textured (suit, helmet, goggles) on lit ground, and the trees behind the menus are lit too. Some foreground grass and the bike at the edge of the frame are still dark.GameThread timed out waiting for RenderThread after 120.00 secs.Jump fold-in (
ddb59eefaf), merge preview6c257dbfb6onmain4f41f4c375:^agc_driver_pm4|^agc_driver_gpu_written_indirect_buffer, 17 tests in 3 executables, 3 of 3 runs pass. @mrfelek's negative control: with only theSubmission.cppline reverted,agc_driver_pm4fails withthe packet after a taken COND_INDIRECT_BUFFER ran: the branch returned like a call.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.mdfiles or images added to the repository (attach them to this PR)runtime resource snapshot did not stabilizewithout it)🤖 Generated with Claude Code