Skip to content

fix(agc): run an indirect buffer as it is when execution reaches it - #11346

Open
milescoviello wants to merge 12 commits into
boykopovar:mainfrom
milescoviello:fix/gpu-written-indirect-buffer
Open

milescoviello wants to merge 12 commits into
boykopovar:mainfrom
milescoviello:fix/gpu-written-indirect-buffer

Conversation

@milescoviello

@milescoviello milescoviello commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Hot Wheels Infinite Rush (PPSA22408): @mrfelek's runs show its garage needs this refresh. The re-read buffer is an Unreal shader bundle's command list, written on the GPU earlier in the same submission (trace). main runs the copy taken at submit, 375 NOPs: the garage loads, but its 3D scene stays black. The previous head ran the generated list, and then a compute loop never exited (pc 0x54). @mrfelek traced that loop to copySegment flattening a COND_INDIRECT_BUFFER like a call: Hot Wheels leaves its list through another COND_INDIRECT_BUFFER that chains into the rest of the frame, so the rest of the frame ran twice. This head (ddb59eefaf, with @mrfelek's change folded in) makes a taken COND_INDIRECT_BUFFER replace the rest of its buffer. In @mrfelek's runs the loop guard then trips 0 times; without #15465 the load can abort with runtime resource snapshot did not stabilize, so this depends on #15465.

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:

  • A compute pass packs records into a buffer with ds_ordered_count, keeping only the records whose three counts multiply to a nonzero value.
  • A COND_INDIRECT_BUFFER then runs that buffer.

On main the 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 nested INDIRECT_BUFFERs.

How

  • copySegment notes every INDIRECT_BUFFER and COND_INDIRECT_BUFFER it inlined unchanged (not chained or predicated): where its copy starts, its guest address and its size (Submission::indirectSegments).
  • When execute reaches one, refreshIndirectSegment reads 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 through GuestMemory::Read, which syncs pending GPU writes. That is when the CP reads an indirect buffer.
  • A taken COND_INDIRECT_BUFFER outside a COND_EXEC range replaces the rest of the buffer it is in, like a chained INDIRECT_BUFFER: copySegment stops 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 a COND_EXEC range the packets after it are still copied. That the branch does not return is unverified on hardware; it is in the technical debt file.
  • A buffer no queued work writes runs as copied. A title that rewrites one on the CPU after submitting it would normally find the console's CP done with it, while here execution can trail the submission by a long way. A CPU rewrite behind a WAIT_REG_MEM gate, which the CP would read, also runs as copied; that is in the technical debt file.
  • If the buffer is unchanged, nothing else happens. If it changed:
    • The new contents are expanded like a submission (nested buffers included), validated, and their register lists read.
    • Their rendering waits use tickets the submission took at submit: reserveOutputs takes 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.
    • They replace the old copy.
    • The positions of the flips, rendering waits, register lists, conditional ranges, held waits and later indirect buffers move by the size difference.
    • Dispatches resolved ahead are dropped, and queued work is drained before the stream changes.
    • The label writes of the new contents (WRITE_DATA, RELEASE_MEM) join the submission's labelWrites and the queue's unfinishedWrites, so a wait submitted later sees a writer; completion reads labelWrites after execute, 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.
  • A rewritten buffer holding a flip, an EOP flip release, a REWIND, or a rendering wait on a buffer no ticket was taken for runs as it was copied, since those were not reserved at submit. The pair of such a wait gets a ticket from the next submission on. A chained or predicated buffer also runs as copied. Both are in the technical debt file.
  • New contents that fail to expand, validate or have their register lists read (an unsupported packet, for instance) also leave the buffer as it was copied, which validated at submit, so a refresh can never fail a queue that main would have run. The first eight are logged.

Overlap (tools/pr_overlap.py, git merge-tree): files only. #10487, #10507 and #11207 also change Driver.hpp and merge cleanly with this. #10193 conflicts with main already. Many open PRs add entries to docs/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 base ba5b5330b3, after the Hot Wheels report:

    • New case in agc_driver_gpu_written_indirect_buffer, for a COND_INDIRECT_BUFFER and an INDIRECT_BUFFER: the submission waits on a CPU gate before the buffer. After it is submitted, the CPU writes a WRITE_DATA marker into the buffer and opens the gate. The packet after the buffer must run and the marker must stay 0.
    • Red control 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.
    • The nested, invalid-contents and rendering-wait cases used to rewrite their buffers on the CPU behind a gate. Now a dispatch earlier in the same submission writes them, the case this PR is for. Their checks are unchanged.
    • Linux: the 32 tests of the area regex plus the flip tests, 3 runs: the 16 AGC tests pass 3 of 3, this one included; the 16 video_out_flip_* tests skip in that environment.
    • Khronos validation 1.4.363 over the same set: the merge base ba5b5330b3 passes 31 of 31 and this head 32 of 32, no layer missing, 17 and 19 Vulkan devices created, no VUID- messages on either side.
    • Windows 11 VM (GT 1030, WinLibs GCC 15.2.0 r7): the test passes 3 of 3 on this head (the merge base has no such test).
  • Head 82f3ada000: the same five commits rebased onto main aaccd0ba39 with 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 on main and 23 of 23 here, no VUID- messages. Windows 11 VM (GT 1030): main 10 of 10 and this head 11 of 11, 3 of 3 each (details).

  • Head e593f32f86 (oneandonlydean's and MarcZX10's reviews), test only: TicketWait::Wait records the ticket it waits for, and RewrittenWaitBeforeOwnFlip requires 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 with they 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 base 46e54cf1f7 passes 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 a VUID- 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 onto main 46e54cf1f7. One conflict: main moved the reportSkip declaration in Driver.hpp to the public section (03fcf73), next to the line where the second commit adds validate's report parameter. I kept main's move and the parameter; git range-diff shows the first and third commits unchanged. The 11 tests pass 3 of 3. Windows 11 VM (GT 1030): main 10 of 10 and this head 11 of 11, 3 of 3 each.

  • Head 240c1c218b, rebased onto main 8c7cf82 (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, until AgcDriverAwaitedWaits_nid_postfix reports 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 rewritten WRITE_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_MS sleeps at the start of every execute, and at 1000 ms every submission starts executing after the old 500 ms sample.

      Build No delay 1 s delay
      This head plus the switch 3 of 3 pass 3 of 3 pass
      The same without the two held-wait erase_if lines in refreshIndirectSegment 3 of 3 fail 3 of 3 fail
      The same, with the previous test 3 of 3 fail 3 of 3 pass

      Without 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 main 8c7cf82 and 11 of 11 on this head, no VUID- messages. Windows 11 VM (GT 1030): main 10 of 10 and this head 11 of 11, 3 of 3 each.

  • Head 199186dabd added a second commit after review. In a MXGP 26 run with a local diagnostic on 5dd3166c16, the title stopped at 48 s: a rewritten 44,019-dword list at 0x1078da8010, one of MXGP's GPU-built command lists, held a 0x00000000 header. The throw from the refresh's validate failed the queue with unsupported PM4 packet type: header 0x00000000 at DWORD 39212 of 44019. Such contents now run as copied.

    • New case in agc_driver_gpu_written_indirect_buffer: after the submission, the CPU rewrites a gated COND_INDIRECT_BUFFER's target with a 0x00000000 header and a WRITE_DATA. The queue must keep running, the packet after the buffer must run, and the WRITE_DATA must not. The test alone on 5dd3166c16 fails 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.
    • On this head the 11 tests pass 3 of 3. Khronos validation: 10 of 10 on main 4b1a9a3 and 11 of 11 on this head, no VUID- messages. Windows 11 VM (GT 1030): main b27cc84 10 of 10 and this head 11 of 11, 3 of 3 each.
    • MXGP 26 on this head with the same diagnostic: it runs to the 480 s timeout, and no rewritten list failed validation in that run.
    • Windows hardware (ycbuzi): 199186dabd merged onto main 9ff033b, the 11 tests with ctest --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, with agc_driver_pipelined_dispatch failing 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 its runs as copied line on every device and passes. With main's production files, the test fails on the 4070 with the original marker-0 message.
  • Head 5dd3166c16: 25000ed852 rebased onto main b27cc84, the same patch (git range-diff shows it unchanged). Since 204c674, main changed only docs/dev/debt/libSceAgcDriver.md among the touched files; both sides' entries are kept and conventions pass. The runs below are on 25000ed852.

  • Windows hardware (ycbuzi, Windows 11 Home 10.0.26200, WinLibs GCC 15.2.0 r7): 25000ed852 merged onto main b27cc84, the same tree as this head, the 11 tests with ctest --repeat until-fail:3:

  • Head 25000ed852, rebased onto main 204c674 (clean; both sides' entries kept in docs/dev/debt/libSceAgcDriver.md). The 11 tests pass 3 of 3 on Linux. Khronos validation: 10 of 10 on main 204c674 and 11 of 11 on this head, no VUID- messages. Windows 11 VM (GT 1030): main 10 of 10 and this head 11 of 11, 3 of 3 each.

    • On the VM, agc_submit_progress (in the set) failed twice on PR builds in about 100 runs, with its 2 s submission lost its real GPU completion store deadline: once in a 3-run pass on b5c1a82490, and once within 15 repeats. It passed 20 more on that build and 60 of 60 on 25000ed852, and 40 of 40 on main. A further 100 runs each, one ctest per run: 100 of 100 on this head 5dd3166c16 and 100 of 100 on main 4e43321, so 2 failures in about 280 PR-build runs against 0 in 140 on main. 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 b5c1a82490 on main 14c99b5, after review: rebased, the held-wait bookkeeping added, and indirectSegments kept sorted by start after the copy and after every splice.

    • Nested case: a mutant whose splice drops the nested entries fails it with 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.
    • Khronos validation over the 11: 10 of 10 on main 14c99b5 and 11 of 11 on this head, no VUID- messages. The Windows VM run of this head is in a comment below.
  • Previous head 867f93d9dc (same code as 4f55aae4f8, which only shortened the debt entry):

    • The held-wait case below fails in both runs on the head before it, 9f3361d: 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.
    • Khronos validation over the same 11: 10 of 10 on main 14c99b5 and 11 of 11 on this head, no VUID- 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 a WRITE_DATA packet into a NOP-filled buffer, then a COND_INDIRECT_BUFFER (and, in a second case, an INDIRECT_BUFFER) runs that buffer; the marker the packet stores must be set.

    • Held-wait case:
      1. A first submission waits on a CPU gate, then a dispatch writes WRITE_DATA label = 0 into a NOP-filled buffer that a COND_INDIRECT_BUFFER runs. The label starts at 1.
      2. A second submission, queued while the first is held, waits for label == 1 and then writes a marker.
      3. After the gate opens, the test waits up to 10 s until the worker is blocked on the label wait or the marker turns 1. The label must be 0 and the marker 0 at that point; then the CPU sets the label back to 1 and the marker must be 1.
    • Nested case:
      1. A submission waits on a CPU gate, then a COND_INDIRECT_BUFFER runs a NOP-filled parent.
      2. While the gate holds, the CPU rewrites the parent into a dispatch that writes a WRITE_DATA marker into a second NOP-filled buffer, followed by an INDIRECT_BUFFER call into it.
      3. When the parent is read again the child is still NOPs, so it has to be refreshed again at its call, and the marker must be set.
    • The test alone on main 5b85225 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.
    • With this change it passes 3 of 3.
  • 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 base 5b85225ef3, 11 of 11 on this head, no layer missing, no VUID- messages on either. Correction (10-27): two tests of this set never load the layer. agc_driver_graphics and agc_driver_pm4 run 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 at 240c1c218b), creates a real device, as do the others; I counted Physical device selected per 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.
    • This head plus one log line in 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.
    • Before rendering waits took their tickets at submit, a run hung at 252 s: a rendering wait in a rewritten boot buffer, captured at execution, also waited for flips that later submissions had reserved, and UE stopped on GameThread timed out waiting for RenderThread after 120.00 secs.
    • The frame rate is lower (0.8 against about 4.5 FPS in the menus), since the GPU now draws the passes it skipped. The run also overlapped a backup of the host's disk, so I make no frame-rate claim.
  • Jump fold-in (ddb59eefaf), merge preview 6c257dbfb6 on main 4f41f4c375: ^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 the Submission.cpp line reverted, agc_driver_pm4 fails with the packet after a taken COND_INDIRECT_BUFFER ran: the branch returned like a call.

Checklist

🤖 Generated with Claude Code

@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.

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.

@milescoviello
milescoviello force-pushed the fix/gpu-written-indirect-buffer branch from 3715420 to 9f3361d Compare October 26, 2026 06:15

@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.

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.

@milescoviello

Copy link
Copy Markdown
Contributor Author

@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:

  • Fix: the label writes of a rewritten buffer are added to the submission's labelWrites and the queue's unfinishedWrites when it is spliced in. Completion reads labelWrites after execute, so they're released with the submission. Any wait already marked held on one of those dwords loses the mark, whether later in the same submission or in one already pending on that queue. Waits inside a rewritten buffer are never held.
  • Regression (in agc_driver_gpu_written_indirect_buffer):
    1. The first submission waits on a CPU gate, then a dispatch writes WRITE_DATA label = 0 into a NOP-filled buffer that a COND_INDIRECT_BUFFER runs. The label starts at 1.
    2. A second submission, queued while the first is held, waits for label == 1 and then writes a marker.
    3. After the gate opens, the marker must stay 0 until the CPU sets the label back to 1.

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)

@milescoviello
milescoviello force-pushed the fix/gpu-written-indirect-buffer branch 2 times, most recently from 867f93d to 4f55aae Compare October 26, 2026 06:40

@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.

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.

@milescoviello

Copy link
Copy Markdown
Contributor Author

@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. noteIndirectSegment records a buffer only when its copy is word for word the guest buffer (commands.size() - start == words and std::equal). A parent that contains an indirect call never passes that check, because the call's packet is replaced by the child's words. So the initial recursive copy never records a parent together with its children; only the child is recorded, and only if it is verbatim itself. In a splice, the parent's entry is removed, its nested entries are inserted at its index, and later entries move by the size difference, so they stay in start order there too. I'd still rather not depend on that.

The change (b5c1a82, not pushed yet): indirectSegments is sorted by start after copyCommands and after every splice, so the single nextSegment walk never relies on how the copy recursed.

The regression (a fourth case in agc_driver_gpu_written_indirect_buffer):

  1. A submission waits on a CPU gate, then a COND_INDIRECT_BUFFER runs a NOP-filled parent buffer.
  2. While the gate holds, the CPU rewrites the parent: a dispatch that writes a WRITE_DATA marker into a second, NOP-filled buffer, followed by an INDIRECT_BUFFER call into that buffer.
  3. When the parent is read again, the child is still NOPs, so its copy then has to be refreshed again at its call, after the dispatch in the parent has written it.
  4. The marker must be set.

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 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.

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.

@milescoviello

Copy link
Copy Markdown
Contributor Author

@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)

@github-actions

github-actions Bot commented Oct 26, 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 6867 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Queues/Submission.cpp L227
PR 12172 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Queues/Submission.cpp L138, L176-177, L204-205, L209

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 5609 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Driver.hpp
PR 5925 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Driver.hpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Packets/PacketExecution.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6186 core/libs/prx/libSceAgcDriver/tests/Pm4.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6188 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Driver.hpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Packets/PacketExecution.cpp
PR 6194 docs/dev/debt/libSceAgcDriver.md
PR 6223 docs/dev/debt/libSceAgcDriver.md
PR 6280 docs/dev/debt/libSceAgcDriver.md
PR 6412 docs/dev/debt/libSceAgcDriver.md
PR 6481 docs/dev/debt/libSceAgcDriver.md
PR 6549 core/libs/prx/libSceAgcDriver/tests/Pm4.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6804 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Driver.hpp
docs/dev/debt/libSceAgcDriver.md
PR 6808 docs/dev/debt/libSceAgcDriver.md
PR 7085 docs/dev/debt/libSceAgcDriver.md
PR 7275 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Driver.hpp
PR 7449 docs/dev/debt/libSceAgcDriver.md
PR 7604 docs/dev/debt/libSceAgcDriver.md
PR 7642 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Driver.hpp
docs/dev/debt/libSceAgcDriver.md
PR 8592 docs/dev/debt/libSceAgcDriver.md
PR 9356 docs/dev/debt/libSceAgcDriver.md
PR 9387 docs/dev/debt/libSceAgcDriver.md
PR 9592 docs/dev/debt/libSceAgcDriver.md
PR 9748 docs/dev/debt/libSceAgcDriver.md
PR 9893 core/libs/prx/libSceAgcDriver/tests/Pm4.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9915 docs/dev/debt/libSceAgcDriver.md
PR 9950 docs/dev/debt/libSceAgcDriver.md
PR 10193 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Driver.hpp
docs/dev/debt/libSceAgcDriver.md
PR 10233 docs/dev/debt/libSceAgcDriver.md
PR 10359 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Driver.hpp
docs/dev/debt/libSceAgcDriver.md
PR 10678 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Driver.hpp
PR 11435 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Driver.hpp
PR 11436 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Driver.hpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Queues/Submission.cpp
PR 11825 docs/dev/debt/libSceAgcDriver.md
PR 12904 docs/dev/debt/libSceAgcDriver.md
PR 13486 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Driver.hpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Queues/Submission.cpp
docs/dev/debt/libSceAgcDriver.md
PR 13599 docs/dev/debt/libSceAgcDriver.md
PR 13707 core/libs/prx/libSceAgcDriver/tests/Pm4.cpp
docs/dev/debt/libSceAgcDriver.md
PR 13793 docs/dev/debt/libSceAgcDriver.md
PR 13809 docs/dev/debt/libSceAgcDriver.md
PR 13863 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Packets/PacketExecution.cpp
docs/dev/debt/libSceAgcDriver.md
PR 13920 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Packets/PacketExecution.cpp
docs/dev/debt/libSceAgcDriver.md
PR 13928 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Driver.hpp
docs/dev/debt/libSceAgcDriver.md
PR 13929 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Driver.hpp
docs/dev/debt/libSceAgcDriver.md
PR 14137 docs/dev/debt/libSceAgcDriver.md
PR 14212 docs/dev/debt/libSceAgcDriver.md
PR 14344 docs/dev/debt/libSceAgcDriver.md
PR 14944 docs/dev/debt/libSceAgcDriver.md
PR 15136 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Driver.hpp
core/libs/prx/libSceAgcDriver/Execution/include/Driver/Queues/Submission.hpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Packets/PacketExecution.cpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Queues/Submission.cpp
docs/dev/debt/libSceAgcDriver.md
PR 15169 docs/dev/debt/libSceAgcDriver.md
PR 15529 docs/dev/debt/libSceAgcDriver.md
PR 15548 docs/dev/debt/libSceAgcDriver.md
PR 16059 docs/dev/debt/libSceAgcDriver.md

@milescoviello
milescoviello force-pushed the fix/gpu-written-indirect-buffer branch from 4f55aae to b5c1a82 Compare October 26, 2026 07:37
@MarcZX10

Copy link
Copy Markdown
Contributor

I rechecked the new exact head b5c1a8249068c631f91fa7048a6e1880288913e3. It now adds the expanded label writes to submission.labelWrites and worker.unfinishedWrites, clears stale held-at-submit marks for later waits in the current and queued submissions, and includes both the held-wait and nested indirect-buffer regressions. The PR body reports the focused 11-test set three times on Linux and Windows plus validation-layer results. I have not run the GPU tests independently on this host.

There is a new integration point to refresh: current main is 35ac3402c80b152983e8aa11196835d3a16370bf; this branch is 1 commit ahead and 74 behind from 14c99b52ac. The direct merge preview is clean; the only shared changed path since the merge base is docs/dev/debt/libSceAgcDriver.md, where both sides have edits. Please rebase, preserve both debt entries, and rerun the focused test/validation set at the resulting exact head before merge. The earlier child-before-parent finding was withdrawn after the guard review; this comment does not revive it.

@milescoviello

Copy link
Copy Markdown
Contributor Author

@MarcZX10 thanks. I've rebased onto main 204c674, which has moved past 35ac340, as 25000ed. It was clean: in docs/dev/debt/libSceAgcDriver.md main's new entries and this PR's are both kept, and conventions pass.

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)

@github-actions github-actions Bot added docs agc libSceAgc* labels Oct 26, 2026
@milescoviello
milescoviello force-pushed the fix/gpu-written-indirect-buffer branch from b5c1a82 to 25000ed Compare October 26, 2026 08:27
@milescoviello

Copy link
Copy Markdown
Contributor Author

@MarcZX10 pushed 25000ed852, rebased onto main 204c674. It was clean, with both sides' debt entries kept. The focused set at this exact head:

  • Linux (RTX 4070 Ti, 615.71.09): the 11 tests pass 3 of 3, including the direct, conditional, held-wait and nested cases of agc_driver_gpu_written_indirect_buffer.
  • Khronos validation 1.4.363 over the 11: 10 of 10 on main 204c674 and 11 of 11 on this head, no VUID- messages.
  • Windows 11 VM (GT 1030, 582.78): main 10 of 10 and this head 11 of 11, 3 of 3 each.
  • On the previous head, the mutant whose splice drops nested entries fails the nested case. The held-wait case fails on the head before the bookkeeping.

One flake to note. On the VM, agc_submit_progress failed twice on PR builds in about 100 runs: submission lost its real GPU completion store, its 2 s wait for a released label. One failure was in a 3-run pass on b5c1a82490 and one was within 15 repeats. It then passed 20 more on that build and 60 of 60 on this head, and 40 of 40 on main. That test submits no indirect buffer, so indirectSegments stays empty and the refresh path is never entered, and it has never failed on Linux. I read it as the 2 s deadline on a loaded VM, but I've put it in the description so it isn't hidden.

AI-assisted: yes (Claude Code)

@MarcZX10

Copy link
Copy Markdown
Contributor

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 agc_submit_progress timeout is disclosed; its path does not use indirect segments, and the author reports 60/60 on main and 60/60 on this head afterward. I have not independently run the GPU tests. Current main has advanced to b27cc8416f820e40ce187f165d34138e24373dd7; this PR is 1 ahead/31 behind. Main changed only docs/dev/debt/libSceAgcDriver.md among the touched files since the tested base. Please refresh the branch and retain both debt updates; the focused GPU rerun is unnecessary if the rebase only changes that documentation file, but conventions should pass on the resulting head.

@milescoviello
milescoviello force-pushed the fix/gpu-written-indirect-buffer branch from 25000ed to 5dd3166 Compare October 26, 2026 08:47
@milescoviello

Copy link
Copy Markdown
Contributor Author

@MarcZX10 done: rebased onto main b27cc84 as 5dd3166c16. It was clean, and git range-diff shows the patch unchanged from 25000ed852. Since 204c674 main changed only docs/dev/debt/libSceAgcDriver.md among the touched files, and both sides' entries are kept: main's new New depth surface from storage writes entry and its edit of the write-watch entry, and this PR's indirect-buffer entry. tools/check_conventions.py passes on the new head with the updated body, which records the rebase.

AI-assisted: yes (Claude Code)

@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.

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.

@ycbuzi

ycbuzi commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

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 25000ed852 onto main b27cc8416f, and that merge has the same tree as your new head 5dd3166c16 (a4317ecc0e), so these results apply to it. One GPU at a time with ANYPS5_GPU, plus ANYPS5_REQUIRE_VULKAN=1 and ANYPS5_NO_SHADER_CACHE=1, run with ctest -V --repeat until-fail:3. Each log's Selected GPU line names the device.

device result
GeForce RTX 4070 SUPER (0x2783), NVIDIA 616.92 11 of 11, 3 of 3 runs
GeForce GTX 1650 SUPER (0x2187), NVIDIA 616.92 11 of 11, 3 of 3 runs
AMD Radeon(TM) Graphics (1002:164e, RDNA2 iGPU), AMD 32.0.21030.2001 10 of 11 pass 3 of 3; agc_driver_pipelined_dispatch passed its first run and failed its second
  • Control: with main's Driver.hpp, Submission.hpp, PacketExecution.cpp and Submission.cpp, agc_driver_gpu_written_indirect_buffer fails on the 4070 with 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, the WRITE_DATA the dispatch wrote stores 1592590337. The other 10 pass.
  • agc_submit_progress, the one that flaked on your VM: 3 of 3 on each of the three GPUs here.
  • agc_driver_pipelined_dispatch on the Radeon: my runner didn't keep that failure's output, so I don't have its message yet, and I can't say whether it's this PR or the test. I've queued 20 runs of it on the Radeon for main and for this head, keeping each failing log, plus 20 more of agc_submit_progress there. I'll post both here.

AI-assisted: yes (Claude Code)

@milescoviello

Copy link
Copy Markdown
Contributor Author

@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 agc_driver_pipelined_dispatch failure on the Radeon is noted there as pending your 20-run comparison of main and this head.

For that comparison: the test doesn't submit an INDIRECT_BUFFER or COND_INDIRECT_BUFFER, as far as I can see. With no indirect segments recorded, execute never calls refreshIndirectSegment, and reserveOutputs takes no prepared waits. So a failure on this head alone would surprise me, but the logs will tell.

AI-assisted: yes (Claude Code)

@ycbuzi

ycbuzi commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

@milescoviello The two follow-ups from #11346 (comment), on the Radeon iGPU (1002:164e, AMD 32.0.21030.2001): 20 runs of each test on main and on main + 5dd3166c16, each run its own ctest -V with ANYPS5_GPU=Radeon ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1.

test main main + this PR
agc_driver_pipelined_dispatch 2 of 20 fail 2 of 20 fail
agc_submit_progress 20 of 20 pass 20 of 20 pass

All four pipelined_dispatch failures are pipelined dispatch: the two targets do not share their high address dword. That's the fixture check after its two separate VirtualAlloc calls, before any dispatch, so it's #9680 (fixed by #9696), not this PR. It's more frequent on this device than the 1 in 70 reported there. I've queued #9696 on the Radeon to check the fix there too.

AI-assisted: yes (Claude Code)

@milescoviello

Copy link
Copy Markdown
Contributor Author

@ycbuzi thank you, that settles it. Equal failure counts on main and the head, and a fixture check that fails before any dispatch, point at #9680, not this change. I've replaced the pending note in Tested with your 20-run numbers.

AI-assisted: yes (Claude Code)

@milescoviello

Copy link
Copy Markdown
Contributor Author

@MarcZX10 one more commit after your approval, 199186dabd, because I found a way this PR could fail a queue that main would have run.

What happened. In a MXGP 26 run of 5dd3166c16 with a local diagnostic, the title stopped at 48 s. A rewritten GPU-built list (44,019 dwords once expanded, at 0x1078da8010) held a 0x00000000 header. refreshIndirectSegment's validate threw on it (unsupported PM4 packet type: header 0x00000000 at DWORD 39212 of 44019), and the throw failed the queue. On main that buffer just runs as its submit-time copy.

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. validate gains a report argument (default true) so these failures don't dump the whole list each time. The debt entry gains one sentence.

Tests.

  • New case in agc_driver_gpu_written_indirect_buffer: the CPU rewrites a gated COND_INDIRECT_BUFFER's target with a 0x00000000 header and a WRITE_DATA. The queue must keep running, the packet after the buffer must run, and the WRITE_DATA must not.
  • That test alone on 5dd3166c16 fails 2 of 2 with ... failed the queue instead of running as it was copied: AGC driver: unsupported PM4 packet type ....
  • On 199186dabd the 11 tests pass 3 of 3. Khronos validation: 10 of 10 on main, 11 of 11 on the head, no VUID-. Windows VM: 10 of 10 and 11 of 11, 3 of 3 each.
  • MXGP 26 on the head runs to its 480 s timeout.

AI-assisted: yes (Claude Code)

@ycbuzi

ycbuzi commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

A Windows rerun of the new head on the same three devices: 199186dabd merged onto main 9ff033b1a1 with no conflicts, the 11-test set, ctest -V --repeat until-fail:3, one GPU at a time with ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1.

device result
GeForce RTX 4070 SUPER (0x2783), NVIDIA 616.92 11 of 11, 3 of 3 runs
GeForce GTX 1650 SUPER (0x2187), NVIDIA 616.92 11 of 11, 3 of 3 runs
AMD Radeon(TM) Graphics (1002:164e), AMD 32.0.21030.2001 10 of 11, 3 of 3; agc_driver_pipelined_dispatch failed on its third run with the two targets do not share their high address dword, the #9680 fixture flake from before
  • The new zero-header case runs in agc_driver_gpu_written_indirect_buffer on every device. The log shows indirect buffer 0x200001000 (64 dwords) changed since its submission but runs as copied: AGC driver: unsupported PM4 packet type: header 0x00000000 at DWORD 0 of 64, and the test passes.
  • Control with main's versions of the PR's production files: agc_driver_gpu_written_indirect_buffer fails on the 4070 with the original a COND_INDIRECT_BUFFER ran the command buffer as it was at submission ... message. The other 10 pass.
  • Build warnings: only main's known ones (Signals.cpp:25 _sigintr_nid_postfix, and the two PipelineLibrary.cpp -Wstringop-overread), none from this PR's files.

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>
@milescoviello

Copy link
Copy Markdown
Contributor Author

main moved and the technical debt file conflicted, so I merged main into the branch instead of rebasing. No commit you reviewed changed, and nothing was force-pushed. The new head is 4143f1b4a0, which merges main 6cd2899cc6. The only conflict was in docs/dev/debt/libSceAgcDriver.md: I kept this branch's COND_INDIRECT_BUFFER and indirect buffer entries and main's two label entries, one reworded and one new. main didn't change the COND_INDIRECT_BUFFER line itself. The head merges cleanly with main 45ba19f149.

Rerun on 4143f1b4a0 (Linux, RTX 4070 Ti, driver 615.71.09):

Check Result
^agc_driver_pm4|^agc_driver_gpu_written_indirect_buffer, 17 tests in 3 executables 3 of 3 runs pass
Khronos validation 1.4.363, base 6cd2899cc6 10 of 10 pass, layer loaded in each, 13 Vulkan devices created, no VUID-
Khronos validation 1.4.363, head 4143f1b4a0 11 of 11 pass, layer loaded in each, 15 Vulkan devices created, no VUID-

The validation set is the same as the Windows VM's (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). check_conventions.py --base upstream/main reports 0 errors and the same debt-length warning as before.

AI-assisted: yes (Claude Code)

@XairRrR XairRrR 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.

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 of main 6cd2899cc6.
  • The PR's diff against main 086c0686c8 is still the same 8 files. In the debt file it still changes the COND_INDIRECT_BUFFER entry 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_buffer fails: a COND_INDIRECT_BUFFER ran the command buffer as it was at submission … the marker is 0.
  • agc_driver_pm4 fails: 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.
  • prepare captures every known target once per segment (core/libs/prx/libSceAgcDriver/Execution/src/Driver/Queues/Submission.cpp:435): still open, non-blocking, unchanged.
  • CaptureRenderingWait failures are swallowed and renderingWaitTargets is 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.

@adam25136

Copy link
Copy Markdown

Windows and NVIDIA Blackwell run, for head 4143f1b4a0 merged into main 04a9eb4fa2 (git merge --no-ff, clean merge).

GPU NVIDIA GeForce RTX 5080 (10de:2c02), driver 617.42 (32.0.16.1742), Vulkan 1.4.351
Host Windows 10 Pro 22H2 (19045), i9-12900KF, WinLibs GCC 15.2.0 r7, Release, BUILD_TESTING=ON
Selection 2,194 of 3,853 tests, chosen by tools/select_tests.py select from main's build graph for the 8 changed files
Run select_tests.py ctest build --parallel 4 --timeout 120 with ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1; main ran the full suite the same way on this machine
Result 2,181 passed, 12 skipped (the same 12 as on main), 1 failed, 0 new

The failure, agc_driver_direct_write_completion, fails on main on this machine as well, also when run on its own (33 of 34 runs). agc_driver_gpu_written_indirect_buffer, the agc_driver_pm4* tests and the other indirect-buffer tests in the selection (36 in all) passed. No selected test took over 30 s.

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.

@milescoviello

Copy link
Copy Markdown
Contributor Author

@adam25136 thanks for the Blackwell run. agc_driver_direct_write_completion fails on main on Windows since #13159 (#15564). #15610 fixes the discrete-GPU case: on the GT 1030 VM, main fails it 3 of 3 and #15610 passes 3 of 3.

AI-assisted: yes (Claude Code)

@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head 4143f1b merged onto main 1c8c0ef · tested 2026-11-04 02:05 UTC · 23 min

GPU NVIDIA RTX 2000 Ada Generation, driver 595.99.02, Vulkan 1.4.329
Host Ubuntu 26.04.1 LTS, kernel 7.0.0-38-generic, container ubuntu:24.04
Logs build and test logs for this run
Build ✅ passed (Release, -DANYPS5_ENABLE_SPIRV_TOOLS=ON)
Tests ✅ 2,725 passed · 6 failed (0 new, 3 also fail on main, 3 unstable on main) · 50 skipped (ANYPS5_REQUIRE_VULKAN=1)
Test setup CPU-only tests without a GPU; GPU tests (and any CPU-only test that failed or skipped without one) once on the GPU with VK_LAYER_KHRONOS_validation and ANYPS5_NO_SHADER_CACHE=1; main ran the same way
Test selection 2,781 of 3,842 tests run: the ones this change can reach, chosen by tools/select_tests.py from main's build graph
Vulkan validation ✅ no new validation IDs vs main (952 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 120.1 s, ⚠️ agc_driver_lazy_resolved_abi 34.9 s
Unstable on main (3, these also failed in recent main runs on this machine; not counted against this PR)
agc_driver_pipeline_journal: failed in 4 of the last 10 main runs
agc_submit_progress: failed in 5 of the last 10 main runs
agc_submit_progress_no_timeline: failed in 4 of the last 10 main runs
Failing on main too (3, not counted against this PR)
agc_driver_image_table
guest_mmap_executable
guest_socket_options_multicast
Validated but not compared (1, not in the main baseline's validation pass)
agc_driver_gpu_written_indirect_buffer
Validation IDs already present on main (8 IDs in 527 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (527 tests): agc_driver, agc_driver_address_passes, agc_driver_alias_copy_label, agc_driver_alpha_to_coverage, agc_driver_array_layer_target, agc_driver_bc_block_copy, agc_driver_bda_anchor_reads, agc_driver_bda_span_reads, and 519 more
VUID-vkCmdCopyImage-srcImage-01548 (7 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_sampling, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-vkCmdCopyImage-srcImage-01551 (7 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_sampling, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 (2 tests): agc_driver_prepared_exports, agc_driver_srgb8_color_target
VUID-VkSamplerCreateInfo-addressModeU-01079 (1 test): agc_driver_image_gather_volume
VUID-VkSamplerCreateInfo-addressModeU-parameter (1 test): agc_driver_image_gather_volume
VUID-VkSamplerCreateInfo-addressModeV-parameter (1 test): agc_driver_image_gather_volume
VUID-VkSamplerCreateInfo-addressModeW-parameter (1 test): agc_driver_image_gather_volume
Skipped (50)
agc_driver_bda_reads_shadowed_results: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_bda_reads_shadowed_results_per_build: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_gcn_display_present: skipped, no display: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
agc_driver_sample_order_grid_reference: skipped, the device does not keep depth drawn at custom sample locations at those locations, even after a transition that names them: the composite of uniform renders holds the guest's depth in 0 of 3005 sloped samples, so no path can be compared with it bit for bit
agc_driver_scattered_runs: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_sparse_dma_buf_import: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_stencil_ref_export: skipped, the device lacks VK_EXT_shader_stencil_export
agc_driver_vertex_elected_atomic_max: skipped, the device runs vertex programs in subgroups, so they keep their cross-lane reductions
agc_host_import_sparse: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_import_settle_initial_dcc: skipped, the device has no deferred settle of host imports: imports under 1 MiB wait for one only on Windows
agc_unit_shadow_completion_store: skipped, the device reports watched host memory written when it imports or reads it
guest_http_uri_locale: 
guest_net_ctl: skipped, the host has no IPv4 address
guest_video_out_color_space: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_hdr: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_high_frame_rate: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_output_mode: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_resolution_status: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_wqhd_detection: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
video_out_flip_aftergpu: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_backtoback: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_controls: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip_in_order: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_dcc: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_deferred: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_eop: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
vide
Reproduce
git fetch origin 4143f1b4a03f8e41d608c577214e260a005dc015 1c8c0efc8c41314402e6966da5bef6ea3d639d10
git checkout 1c8c0efc8c41314402e6966da5bef6ea3d639d10 && git merge --no-ff 4143f1b4a03f8e41d608c577214e260a005dc015
git submodule update --init --recursive
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON -DANYPS5_ENABLE_SPIRV_TOOLS=ON
cmake --build build && cmake --build build --target libs
VK_DRIVER_FILES=/nonexistent/icd.json ctest --test-dir build -E '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 32 --output-on-failure
ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation \
  ctest --test-dir build -R '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 4 --output-on-failure
# failures are then re-run alone: --timeout 360 --parallel 2; new validation IDs: the test alone, twice, --parallel 1

Automated 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.

@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ AMD GPU test: passed

PR head 4143f1b merged onto main 1c8c0ef · tested 2026-11-04 05:56 UTC · 20 min

GPU AMD Radeon RX 6300 (RADV NAVI24), driver Mesa 25.2.8-0ubuntu0.24.04.4, Vulkan 1.4.318
Host Ubuntu 26.04.1 LTS, kernel 7.0.0-42-generic, container ubuntu:24.04
Logs build and test logs for this run
Build ✅ passed (Release, -DANYPS5_ENABLE_SPIRV_TOOLS=ON)
Tests ✅ 2,711 passed · 9 failed (0 new, 7 also fail on main, 2 unstable on main) · 61 skipped (ANYPS5_REQUIRE_VULKAN=1)
Test setup CPU-only tests without a GPU; GPU tests (and any CPU-only test that failed or skipped without one) once on the GPU with VK_LAYER_KHRONOS_validation and ANYPS5_NO_SHADER_CACHE=1; main ran the same way
Test selection 2,781 of 3,842 tests run: the ones this change can reach, chosen by tools/select_tests.py from main's build graph
Vulkan validation ✅ no new validation IDs vs main (952 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 120.3 s, ⚠️ public_headers 60.7 s, ⚠️ agc_driver_image_sample_unnormalized 34.6 s, ⚠️ agc_driver_lazy_resolved_abi 33.6 s
Unstable on main (2, these also failed in recent main runs on this machine; not counted against this PR)
agc_driver_pipeline_journal: failed in 8 of the last 10 main runs
agc_driver_submit_progress: failed in 8 of the last 10 main runs
Failing on main too (7, not counted against this PR)
agc_driver_image_table
agc_driver_native_depth_bda_clear
agc_driver_native_multisample_depth
agc_submit_progress
agc_submit_progress_no_timeline
guest_mmap_executable
guest_socket_options_multicast
Validated but not compared (1, not in the main baseline's validation pass)
agc_driver_gpu_written_indirect_buffer
Validation IDs already present on main (8 IDs in 527 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (527 tests): agc_driver, agc_driver_address_passes, agc_driver_alias_copy_label, agc_driver_alpha_to_coverage, agc_driver_array_layer_target, agc_driver_bc_block_copy, agc_driver_bda_anchor_reads, agc_driver_bda_span_reads, and 519 more
VUID-vkCmdCopyImage-srcImage-01548 (4 tests): agc_driver_depth_clear_hle, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-vkCmdCopyImage-srcImage-01551 (4 tests): agc_driver_depth_clear_hle, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 (2 tests): agc_driver_prepared_exports, agc_driver_srgb8_color_target
VUID-VkSamplerCreateInfo-addressModeU-01079 (1 test): agc_driver_image_gather_volume
VUID-VkSamplerCreateInfo-addressModeU-parameter (1 test): agc_driver_image_gather_volume
VUID-VkSamplerCreateInfo-addressModeV-parameter (1 test): agc_driver_image_gather_volume
VUID-VkSamplerCreateInfo-addressModeW-parameter (1 test): agc_driver_image_gather_volume
Skipped (61)
agc_driver_bda_reads_shadowed_results: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_bda_reads_shadowed_results_per_build: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_copied_writer_label_order: skipped, the device reports a minStorageBufferOffsetAlignment of 4, so the dispatch binds its record at +0x1004 in place and nothing is written back; the test needs an alignment above 4
agc_driver_float16_unused_nan_payloads: skipped, the device has no native f16 conversions with RTE rounding and kept f16 denormals
agc_driver_gcn_display_present: skipped, no display: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
agc_driver_image_table_vouched_lookups: skipped, the device reports 4 of 4 host-imported pages written after a GPU read, so a watched imported table cannot be vouched for
agc_driver_linear_target_direct_write_completion: skipped, the device does not keep host imports write-watched, so no completion stamp over the target is tracked
agc_driver_ngg_vertex_wave_reduction: skipped, s3 describes a 32-lane wave only on 32-lane subgroups, and the device has 64 lanes
agc_driver_scattered_runs: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_sparse_dma_buf_import: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_unit_shadow: skipped, the device does not import watched host memory for unit shadows
agc_driver_unit_shadow_budget: skipped, the device does not import watched host memory for unit shadows
agc_driver_vertex_elected_atomic_max: skipped, the device runs vertex programs in subgroups, so they keep their cross-lane reductions
agc_host_import_sparse: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_idle_publish_wait: skipped, the device reports 4 of 4 host-imported pages written after a GPU read, so a forced watch of the import reads its submissions as CPU stores
agc_import_settle_initial_dcc: skipped, the device has no deferred settle of host imports: imports under 1 MiB wait for one only on Windows
agc_shadowed_key_stores: skipped, the device imports no watched host memory under a unit shadow
agc_small_tiled_shadow_label: skipped, host imports are unavailable: the test block is not imported and watched
agc_storage_clear_hand_over: skipped, the device imports no watched host memory for the clear-key hand-over
agc_storage_pending_key_refresh: skipped, refreshes over a pending key store are not testable here
agc_unit_shadow: skipped, the device does not import watched host memory for unit shadows
agc_unit_shadow_completion_store: skipped, the device reports watched host memory written when it imports or reads it
guest_http_uri_locale: 
guest_net_ctl: skipped, the host has no IPv4 address
guest_video_out_color_space: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_hdr: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_high_frame_rate: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_output_mode: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_resolution_status: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_wqhd_detection: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
video_out_flip_aftergpu: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_backtoback: skipped, no display or Vulkan d
Reproduce
git fetch origin 4143f1b4a03f8e41d608c577214e260a005dc015 1c8c0efc8c41314402e6966da5bef6ea3d639d10
git checkout 1c8c0efc8c41314402e6966da5bef6ea3d639d10 && git merge --no-ff 4143f1b4a03f8e41d608c577214e260a005dc015
git submodule update --init --recursive
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON -DANYPS5_ENABLE_SPIRV_TOOLS=ON
cmake --build build && cmake --build build --target libs
VK_DRIVER_FILES=/nonexistent/icd.json ctest --test-dir build -E '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 12 --output-on-failure
ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation \
  ctest --test-dir build -R '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 16 --output-on-failure
# failures are then re-run alone: --timeout 360 --parallel 2; new validation IDs: the test alone, twice, --parallel 1

Automated 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.

milescoviello and others added 2 commits November 4, 2026 12:37
…irect-buffer

# Conflicts:
#	core/libs/prx/libSceAgcDriver/Execution/include/Driver/Driver.hpp
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@milescoviello

Copy link
Copy Markdown
Contributor Author

Merged main 9ab6a281ea into the branch (merge commit 2c6abb4d6d, no rebase).

  • The one conflict, Driver.hpp:
    • Kept this PR's execute(Submission&). It refreshes an indirect segment in place, so it can't be const.
    • Took main's deliverGuestEopInterrupt(queue, context) and releaseInterrupt.
    • Dropped deliverFlipEopInterrupt, which main removed. Nothing in the tree still calls it.
  • Focused tests at 2c6abb4d6d (Linux, RTX 4070 Ti, 615.71.09): all 11 pass in each of 3 runs.
  • ca7b428e7a only shortens this PR's indirect-buffer debt entry to under 1000 characters; check_conventions.py had warned about it.
  • The paired validation-layer comparison for the new head is queued, and I'll post it here.

AI-assisted: yes (Claude Code)

@github-actions github-actions Bot removed the review queue Next in the maintainer review queue: checks pass, no open change request, no conflict label Nov 4, 2026
@milescoviello

Copy link
Copy Markdown
Contributor Author

@MarcZX10 @XairRrR main conflicted with this branch in Driver.hpp, so I merged main 9ab6a281ea (current main as I write this) into the branch as 2c6abb4d6d. The conflict was main and this PR each adding a declaration in the same place, and both are kept. I also trimmed the debt entry back under the length limit in ca7b428e7a, which is docs only. The head ca7b428e7a contains main 9ab6a281ea, so the merge preview's tree is the head's own tree.

  • Focused tests at 2c6abb4d6d (the 10 executables / 11 tests this PR touches or depends on), run 3 times: 11/11 passed each time.
  • Khronos VK_LAYER_KHRONOS_validation, same test set, base main 9ab6a281ea vs head ca7b428e7a:
    • base: 10/10 passed, 13 Vulkan devices created, no VUIDs;
    • head: 11/11 passed, 15 Vulkan devices created, no VUIDs.
    • The extra test on the head is this PR's own agc_driver_gpu_written_indirect_buffer.

AI-assisted: yes (Claude Code)

@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head ca7b428 merged onto main 9ab6a28 · tested 2026-11-04 20:38 UTC · 23 min

GPU NVIDIA RTX 2000 Ada Generation, driver 595.99.02, Vulkan 1.4.329
Host Ubuntu 26.04.1 LTS, kernel 7.0.0-38-generic, container ubuntu:24.04
Logs build and test logs for this run
Build ✅ passed (Release, -DANYPS5_ENABLE_SPIRV_TOOLS=ON)
Tests ✅ 2,788 passed · 2 failed (0 new, 2 also fail on main) · 49 skipped (ANYPS5_REQUIRE_VULKAN=1)
Test setup CPU-only tests without a GPU; GPU tests (and any CPU-only test that failed or skipped without one) once on the GPU with VK_LAYER_KHRONOS_validation and ANYPS5_NO_SHADER_CACHE=1; main ran the same way
Test selection 2,839 of 3,909 tests run: the ones this change can reach, chosen by tools/select_tests.py from main's build graph
Vulkan validation ✅ no new validation IDs vs main (978 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 114.3 s, ⚠️ public_headers 33.3 s
Failing on main too (2, not counted against this PR)
agc_driver_image_table
guest_mmap_executable
Validated but not compared (1, not in the main baseline's validation pass)
agc_driver_gpu_written_indirect_buffer
Validation IDs already present on main (13 IDs in 549 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (549 tests): agc_driver, agc_driver_address_draw_space_reuse, agc_driver_address_passes, agc_driver_alias_copy_label, agc_driver_alpha_to_coverage, agc_driver_array_layer_target, agc_driver_bc_block_copy, agc_driver_bda_anchor_reads, and 541 more
VUID-VkShaderModuleCreateInfo-pCode-08737 (8 tests): agc_driver_dpp16_operands, agc_driver_dpp8_pk_fmac, agc_driver_dx10_clamp, agc_driver_float16_fma_rounding, agc_driver_float16_unused_nan_payloads, agc_driver_packed_alu, agc_driver_packed_f16_denormal_modes, agc_driver_packed_float16_native
VUID-VkShaderModuleCreateInfo-pCode-08739 (8 tests): agc_driver_dpp16_operands, agc_driver_dpp8_pk_fmac, agc_driver_dx10_clamp, agc_driver_float16_fma_rounding, agc_driver_float16_unused_nan_payloads, agc_driver_packed_alu, agc_driver_packed_f16_denormal_modes, agc_driver_packed_float16_native
VUID-VkShaderModuleCreateInfo-pCode-08741 (8 tests): agc_driver_dpp16_operands, agc_driver_dpp8_pk_fmac, agc_driver_dx10_clamp, agc_driver_float16_fma_rounding, agc_driver_float16_unused_nan_payloads, agc_driver_packed_alu, agc_driver_packed_f16_denormal_modes, agc_driver_packed_float16_native
VUID-vkCmdCopyImage-srcImage-01548 (7 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_sampling, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-vkCmdCopyImage-srcImage-01551 (7 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_sampling, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 (1 test): agc_driver_srgb8_color_target
VUID-VkPipelineShaderStageCreateInfo-module-parameter (1 test): agc_driver_float16_unused_nan_payloads
VUID-VkPipelineShaderStageCreateInfo-pSpecializationInfo-06849 (1 test): agc_driver_float16_unused_nan_payloads
VUID-VkSamplerCreateInfo-addressModeU-01079 (1 test): agc_driver_image_gather_volume
VUID-VkSamplerCreateInfo-addressModeU-parameter (1 test): agc_driver_image_gather_volume
VUID-VkSamplerCreateInfo-addressModeV-parameter (1 test): agc_driver_image_gather_volume
VUID-VkSamplerCreateInfo-addressModeW-parameter (1 test): agc_driver_image_gather_volume
Skipped (49)
agc_driver_bda_reads_shadowed_results: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_bda_reads_shadowed_results_per_build: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_gcn_display_present: skipped, no display: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
agc_driver_sample_order_grid_reference: skipped, the device does not keep depth drawn at custom sample locations at those locations, even after a transition that names them: the composite of uniform renders holds the guest's depth in 0 of 3005 sloped samples, so no path can be compared with it bit for bit
agc_driver_scattered_runs: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_sparse_dma_buf_import: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_stencil_ref_export: skipped, the device lacks VK_EXT_shader_stencil_export
agc_driver_vertex_elected_atomic_max: skipped, the device runs vertex programs in subgroups, so they keep their cross-lane reductions
agc_host_import_sparse: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_import_settle_initial_dcc: skipped, the device has no deferred settle of host imports: imports under 1 MiB wait for one only on Windows
agc_unit_shadow_completion_store: skipped, the device reports watched host memory written when it imports or reads it
guest_http_uri_locale: 
guest_video_out_color_space: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_hdr: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_high_frame_rate: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_output_mode: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_resolution_status: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_wqhd_detection: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
video_out_flip_aftergpu: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_backtoback: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_controls: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip_in_order: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_dcc: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_deferred: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_eop: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_eop_aftergpu: skipped, no display or Vulka
Reproduce
git fetch origin ca7b428e7ad1fbe85364d4a35f3f7124de801487 9ab6a281ea61c9e62a7eb07eb4cef8f19ede1c5c
git checkout 9ab6a281ea61c9e62a7eb07eb4cef8f19ede1c5c && git merge --no-ff ca7b428e7ad1fbe85364d4a35f3f7124de801487
git submodule update --init --recursive
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON -DANYPS5_ENABLE_SPIRV_TOOLS=ON
cmake --build build && cmake --build build --target libs
VK_DRIVER_FILES=/nonexistent/icd.json ctest --test-dir build -E '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 32 --output-on-failure
ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation \
  ctest --test-dir build -R '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 4 --output-on-failure
# failures are then re-run alone: --timeout 360 --parallel 2; new validation IDs: the test alone, twice, --parallel 1

Automated 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.

@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ AMD GPU test: passed

PR head ca7b428 merged onto main b611e63 · tested 2026-11-05 00:23 UTC · 20 min

GPU AMD Radeon RX 6300 (RADV NAVI24), driver Mesa 25.2.8-0ubuntu0.24.04.4, Vulkan 1.4.318
Host Ubuntu 26.04.1 LTS, kernel 7.0.0-42-generic, container ubuntu:24.04
Logs build and test logs for this run
Build ✅ passed (Release, -DANYPS5_ENABLE_SPIRV_TOOLS=ON)
Tests ✅ 2,805 passed · 8 failed (0 new, 7 also fail on main, 1 unstable on main) · 59 skipped (ANYPS5_REQUIRE_VULKAN=1)
Test setup CPU-only tests without a GPU; GPU tests (and any CPU-only test that failed or skipped without one) once on the GPU with VK_LAYER_KHRONOS_validation and ANYPS5_NO_SHADER_CACHE=1; main ran the same way
Test selection 2,872 of 3,946 tests run: the ones this change can reach, chosen by tools/select_tests.py from main's build graph
Vulkan validation ✅ no new validation IDs vs main (984 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 120.4 s, ⚠️ agc_driver_image_sample_unnormalized 64.8 s, ⚠️ agc_driver_lazy_resolved_abi 56.4 s, ⚠️ public_headers 54.9 s, ⚠️ agc_driver_sample_multisample_target 46.9 s
Unstable on main (1, these also failed in recent main runs on this machine; not counted against this PR)
agc_driver_pipeline_journal: failed in 9 of the last 10 main runs
Failing on main too (7, not counted against this PR)
agc_driver_image_gather_volume
agc_driver_image_table
agc_driver_native_depth_bda_clear
agc_driver_native_multisample_depth
agc_driver_submit_progress
agc_submit_progress
agc_submit_progress_no_timeline
Validated but not compared (1, not in the main baseline's validation pass)
agc_driver_gpu_written_indirect_buffer
Validation IDs already present on main (4 IDs in 557 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (557 tests): agc_driver, agc_driver_address_draw_space_reuse, agc_driver_address_passes, agc_driver_alias_copy_label, agc_driver_alpha_to_coverage, agc_driver_array_layer_target, agc_driver_bc_block_copy, agc_driver_bda_anchor_reads, and 549 more
VUID-vkCmdCopyImage-srcImage-01548 (4 tests): agc_driver_depth_clear_hle, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-vkCmdCopyImage-srcImage-01551 (4 tests): agc_driver_depth_clear_hle, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 (1 test): agc_driver_srgb8_color_target
Skipped (59)
agc_driver_bda_reads_shadowed_results: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_bda_reads_shadowed_results_per_build: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_copied_writer_label_order: skipped, the device reports a minStorageBufferOffsetAlignment of 4, so the dispatch binds its record at +0x1004 in place and nothing is written back; the test needs an alignment above 4
agc_driver_float16_unused_nan_payloads: skipped, the device has no native f16 conversions with RTE rounding and kept f16 denormals
agc_driver_gcn_display_present: skipped, no display: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
agc_driver_image_table_vouched_lookups: skipped, the device reports 4 of 4 host-imported pages written after a GPU read, so a watched imported table cannot be vouched for
agc_driver_linear_target_direct_write_completion: skipped, the device does not keep host imports write-watched, so no completion stamp over the target is tracked
agc_driver_ngg_vertex_wave_reduction: skipped, s3 describes a 32-lane wave only on 32-lane subgroups, and the device has 64 lanes
agc_driver_scattered_runs: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_sparse_dma_buf_import: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_unit_shadow: skipped, the device does not import watched host memory for unit shadows
agc_driver_unit_shadow_budget: skipped, the device does not import watched host memory for unit shadows
agc_host_import_sparse: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_idle_publish_wait: skipped, the device reports 4 of 4 host-imported pages written after a GPU read, so a forced watch of the import reads its submissions as CPU stores
agc_import_settle_initial_dcc: skipped, the device has no deferred settle of host imports: imports under 1 MiB wait for one only on Windows
agc_shadowed_key_stores: skipped, the device imports no watched host memory under a unit shadow
agc_small_tiled_shadow_label: skipped, host imports are unavailable: the test block is not imported and watched
agc_storage_clear_hand_over: skipped, the device imports no watched host memory for the clear-key hand-over
agc_storage_pending_key_refresh: skipped, refreshes over a pending key store are not testable here
agc_unit_shadow: skipped, the device does not import watched host memory for unit shadows
agc_unit_shadow_completion_store: skipped, the device reports watched host memory written when it imports or reads it
guest_http_uri_locale: 
guest_video_out_color_space: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_hdr: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_high_frame_rate: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_output_mode: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_resolution_status: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_wqhd_detection: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
video_out_flip_aftergpu: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_backtoback: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_controls: skipped, no display or V
Reproduce
git fetch origin ca7b428e7ad1fbe85364d4a35f3f7124de801487 b611e634f7fc024f0c13e342d96de744448ef1d9
git checkout b611e634f7fc024f0c13e342d96de744448ef1d9 && git merge --no-ff ca7b428e7ad1fbe85364d4a35f3f7124de801487
git submodule update --init --recursive
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON -DANYPS5_ENABLE_SPIRV_TOOLS=ON
cmake --build build && cmake --build build --target libs
VK_DRIVER_FILES=/nonexistent/icd.json ctest --test-dir build -E '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 12 --output-on-failure
ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation \
  ctest --test-dir build -R '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 16 --output-on-failure
# failures are then re-run alone: --timeout 360 --parallel 2; new validation IDs: the test alone, twice, --parallel 1

Automated 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.

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Nov 6, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@milescoviello

Copy link
Copy Markdown
Contributor Author

main conflicted with the branch again, this time in PacketExecution.cpp, so I merged main 85e291c12b into it as f381003e09 (head before: ca7b428e7a).

  • The conflict: main added auto* const executingPacket = workerPacket(); at the line where this PR adds std::size_t nextSegment = 0; before the packet loop. Both are kept. nextSegment drives the indirect-segment refresh, and executingPacket the packet tracking further down; they don't interact.
  • Focused rerun on the merge (Linux, RTX 4070 Ti, NVIDIA 615.71.09): agc_driver_gpu_written_indirect_buffer, agc_driver_pm4, agc_driver_empty_indirect_skip and agc_driver_pipelined_dispatch pass, 4 of 4.

AI-assisted: yes (Claude Code)

@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Nov 6, 2026
@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head f381003 merged onto main 5299939 · tested 2026-11-06 11:53 UTC · 31 min

GPU NVIDIA RTX 2000 Ada Generation, driver 595.99.02, Vulkan 1.4.329
Host Ubuntu 26.04.1 LTS, kernel 7.0.0-38-generic, container ubuntu:24.04
Logs build and test logs for this run
Build ✅ passed (Release, -DANYPS5_ENABLE_SPIRV_TOOLS=ON)
Tests ✅ 2,932 passed · 5 failed (0 new, 4 also fail on main, 1 unstable on main) · 53 skipped (ANYPS5_REQUIRE_VULKAN=1)
Test setup CPU-only tests without a GPU; GPU tests (and any CPU-only test that failed or skipped without one) once on the GPU with VK_LAYER_KHRONOS_validation and ANYPS5_NO_SHADER_CACHE=1; main ran the same way
Test selection 2,990 of 4,210 tests run: the ones this change can reach, chosen by tools/select_tests.py from main's build graph
Vulkan validation ✅ no new validation IDs vs main (987 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 120.1 s, ⚠️ public_headers 31.0 s
Unstable on main (1, these also failed in recent main runs on this machine; not counted against this PR)
agc_driver_pipeline_journal: failed in 1 of the last 10 main runs
Failing on main too (4, not counted against this PR)
agc_driver_image_table
guest_mmap_executable
guest_socket_options_multicast
web_library_assets
Validated but not compared (1, not in the main baseline's validation pass)
agc_driver_gpu_written_indirect_buffer
Validation IDs already present on main (9 IDs in 595 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (595 tests): agc_driver, agc_driver_address_draw_space_reuse, agc_driver_address_draw_space_reuse_held, agc_driver_address_passes, agc_driver_alias_copy_label, agc_driver_alpha_to_coverage, agc_driver_array_layer_target, agc_driver_bc_block_copy, and 587 more
VUID-VkShaderModuleCreateInfo-pCode-08737 (14 tests): agc_driver_dpp16_operands, agc_driver_dpp8_pk_fmac, agc_driver_dx10_clamp, agc_driver_f16_fma_denormal_modes, agc_driver_f16_fma_invalid_nan, agc_driver_float16_fma_rounding, agc_driver_float16_modifiers, agc_driver_float16_native, and 6 more
VUID-VkShaderModuleCreateInfo-pCode-08739 (14 tests): agc_driver_dpp16_operands, agc_driver_dpp8_pk_fmac, agc_driver_dx10_clamp, agc_driver_f16_fma_denormal_modes, agc_driver_f16_fma_invalid_nan, agc_driver_float16_fma_rounding, agc_driver_float16_modifiers, agc_driver_float16_native, and 6 more
VUID-VkShaderModuleCreateInfo-pCode-08741 (14 tests): agc_driver_dpp16_operands, agc_driver_dpp8_pk_fmac, agc_driver_dx10_clamp, agc_driver_f16_fma_denormal_modes, agc_driver_f16_fma_invalid_nan, agc_driver_float16_fma_rounding, agc_driver_float16_modifiers, agc_driver_float16_native, and 6 more
VUID-vkCmdCopyImage-srcImage-01548 (7 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_sampling, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-vkCmdCopyImage-srcImage-01551 (7 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_sampling, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 (2 tests): agc_driver_prepared_exports, agc_driver_srgb8_color_target
VUID-VkPipelineShaderStageCreateInfo-module-parameter (1 test): agc_driver_float16_unused_nan_payloads
VUID-VkPipelineShaderStageCreateInfo-pSpecializationInfo-06849 (1 test): agc_driver_float16_unused_nan_payloads
Skipped (53)
agc_driver_gcn_display_present: skipped, no display: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
agc_driver_sample_order_grid_reference: skipped, the device does not keep depth drawn at custom sample locations at those locations, even after a transition that names them: the composite of uniform renders holds the guest's depth in 0 of 3005 sloped samples, so no path can be compared with it bit for bit
agc_driver_sparse_dma_buf_import: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_stencil_ref_export: skipped, the device lacks VK_EXT_shader_stencil_export
agc_driver_vertex_elected_atomic_max: skipped, the device runs vertex programs in subgroups, so they keep their cross-lane reductions
agc_host_import_sparse: skipped, host imports are unavailable: /dev/udmabuf is not accessible
guest_http_uri_locale: 
guest_net_ctl: skipped, the host has no IPv4 address
guest_net_ctl_disconnected: skipped, the host has no IPv4 address
guest_video_out_color_space: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_device_capability: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_hdr: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_high_frame_rate: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_host_resolution_disabled: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_host_resolution_four_k: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_host_resolution_height_only: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_host_resolution_limit: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_host_resolution_malformed: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_host_resolution_width_only: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_output_mode: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_resolution_status: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_wqhd_detection: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
video_out_flip_aftergpu: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_backtoback: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_controls: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip_in_order: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_dcc: skipped, no dis
Reproduce
git fetch origin f381003e091cb71cac55ea36f18df8487fcc56ae 5299939ecfa9e186e1eb457c6f4bd133bdb087c7
git checkout 5299939ecfa9e186e1eb457c6f4bd133bdb087c7 && git merge --no-ff f381003e091cb71cac55ea36f18df8487fcc56ae
git submodule update --init --recursive
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON -DANYPS5_ENABLE_SPIRV_TOOLS=ON
cmake --build build && cmake --build build --target libs
VK_DRIVER_FILES=/nonexistent/icd.json ctest --test-dir build -E '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 32 --output-on-failure
ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation \
  ctest --test-dir build -R '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 4 --output-on-failure
# failures are then re-run alone: --timeout 360 --parallel 2; new validation IDs: the test alone, twice, --parallel 1

Automated 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.

@github-actions github-actions Bot added the review queue Next in the maintainer review queue: checks pass, no open change request, no conflict label Nov 6, 2026
@Superseabas

Copy link
Copy Markdown

Windows run of the current head, f381003e09, on the integrated Radeon of a Ryzen 7 7700X with AMD's own driver, and on an RTX 5070 Ti. The Windows results since ddb59eefaf are NVIDIA only (the GT 1030 VM and adam25136's RTX 5080), and ycbuzi's earlier run on the same Radeon model was on 199186dabd. Everything passes on both GPUs, and the test catches both the refresh and the taken COND_INDIRECT_BUFFER change. One non-blocking note on what the test reaches.

Head merged onto main 6bf3a19b81 (clean merge, local only). Windows 11 Home 10.0.26200, WinLibs GCC 16.2.0 (x86_64-ucrt-posix-seh, r3), Release. ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation, no missing-layer line, ANYPS5_GPU selecting the device, confirmed by Selected GPU:

  • AMD Radeon of a Ryzen 7 7700X (1002:164e, integrated), AMD 26.10.2 (32.0.21045.20006)
  • NVIDIA GeForce RTX 5070 Ti (10de:2c05), 621.01

Your 11-test set (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): main 10 of 10 and this PR 11 of 11, 3 of 3 runs on both GPUs. No VUID- lines. agc_driver_gpu_written_indirect_buffer runs on both devices, and the zero-header case logs changed since its submission but runs as copied, as in ycbuzi's run. agc_driver_pipelined_dispatch, which failed 2 of 20 runs in ycbuzi's October runs on the same 1002:164e device (#9680), passes 3 of 3 on both trees.

Red checks, each a local edit of the merged tree, 3 runs per GPU:

Edit agc_driver_gpu_written_indirect_buffer agc_driver_pm4
none passes passes
main's Driver.hpp, Submission.hpp, CommandValidation.cpp, PacketExecution.cpp and Submission.cpp fails: a COND_INDIRECT_BUFFER ran the command buffer as it was at submission ... the marker is 0 fails: the packet after a taken COND_INDIRECT_BUFFER ran: the branch returned like a call
copySegment: if (guarded.empty()) return false; after a taken COND_INDIRECT_BUFFER removed passes fails: the same message
refreshIndirectSegment always returning false fails: the same message as the first row passes
the draw pipeline overlap (pipelineWrites) forced false passes passes
the draw finisher overlap (finisherWrites) forced false passes passes
the recorder's PendingWriterSerial (recordedWrites) forced false fails: the same message as the first row passes

The results are the same on both GPUs.

Non-blocking. Every case in agc_driver_gpu_written_indirect_buffer reaches the refresh through the recorder's PendingWriterSerial. The draw pipeline and draw finisher conditions, and the drains they trigger before the re-read, aren't reached on either GPU. mrfelek's PPSA22408 trace also went through the recorder ("only the recorder check let this buffer through"), so neither branch has been seen running yet. A case whose writer is a draw still queued in the draw pipeline, or still held by the finisher, when execution reaches the buffer would cover them.

Whole AGC set. ctest -R '^agc' -j 8 --timeout 300, 1,394 tests: 1,392 pass on the RTX and 1,391 on the Radeon. No VUID- lines. The failures are the ones main has on this machine, all tracked: agc_driver_direct_write_completion (#15564), agc_driver_quad_pixel_mask on the RTX (#14341), and on the Radeon agc_driver_scratch_pool (#15566) and agc_driver_sample_order_grid_reference (#9503).

check_conventions.py --base main passes. No title run.

AI-assisted: yes (Claude Code)

@milescoviello

Copy link
Copy Markdown
Contributor Author

@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 ddb59eefaf, and each guard failing on its own edit is exactly the coverage I wanted.

Good catch on the pipeline and finisher branches: every case reaches the refresh through PendingWriterSerial, so pipelineWrites and finisherWrites aren't covered by a run yet. I'll add a case whose writer is a draw still queued in the draw pipeline (and one held by the finisher) when execution reaches the buffer, with the same red check for each.

AI-assisted: yes (Claude Code)

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* docs review queue Next in the maintainer review queue: checks pass, no open change request, no conflict unblocks title Names a title ID on the Unblocks line

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants