Skip to content

PPSA21567: submission stops on "unsupported PM4 packet type: header 0x00000001" where a RELEASE_MEM header is expected #1458

Closed

Description

@EdouardSence

On main 6b57386 (with #285 and #943), with #759 merged locally, PPSA21567 (Astro Bot, v01.019.000) stops at submission validation about 20 s after start, the same way in every run:

[gpu]   at DWORD 8714   header 0xc0064900 RELEASE_MEM              8 dwords: 06000514 01010000 00000000 00000000 00000000 00000000 0000abcd
[gpu]   at DWORD 8722   header 0xc0064900 RELEASE_MEM              8 dwords: 00000528 60010000 0367e820 00000004 00000000 00000000 00000000
[gpu] dwords 8722..8738: c0064900 00000528 60010000 0367e820 00000004 00000000 00000000 00000000 00000001 06000514 01010000 00000000 00000000 00000000 00000000 0000abcd
terminate called after throwing an instance of 'std::runtime_error'
  what():  AGC driver: unsupported PM4 packet type: header 0x00000001 at DWORD 8730 of 10340

Before this point the buffer is a run of RELEASE_MEM pairs between PUSH_MARKER/POP_MARKER. The first packet of each pair writes 0x4_0367xxxx; the second has payload 06000514 01010000 0 0 0 0 0000abcd. At DWORD 8730 the second packet's payload is there, but its header is 0x00000001 where 0xc0064900 is expected.

What I checked:

Not established: who writes 1 there, or whether the title fills that header after submitting the buffer (the console's CP reads it later than copyCommands does).

Host: CachyOS, kernel 7.2.9, GCC 16.2.1, Ryzen 7 7800X3D, RX 9070 XT (RADV GFX1201, Mesa 26.2.4), default udmabuf.size_limit_mb (64).

AI-assisted: yes (Claude Code ran the builds and wrote this; the runs are on my machine).

Activity

  1. EdouardSence commented on Oct 8, 2026

    @EdouardSence
    ContributorAuthor

    Found the writer of the 1: it is the driver's deferred completion-label store, not the title.

    Hardware watchpoint (gdb, watch -l on 0x502002500 + 8730*4 = 0x50200ad68, armed 12 s in):

    1. Write macOS support #1, title thread: a 0x94-byte memcpy to 0x50200ad64 (the title writing new commands there). Afterwards the word is 0x00000000.
    2. Write fix(build): register relinker tests with CTest #2, a driver thread: libc memcpy with rdi = 0x50200ad68, value 1, called from
      Recorder::finish → Recorder::AfterCompletions(...)::{lambda()#2} → GuestMemory::StoreOwnBytes → memcpy
      (libSceAgcDriver.prx +0x2ab561, +0x295e5f, +0x203987, +0x2038a1, +0x1fd598).

    The submission copy then reads 1 as the header.

    What is queued there (a local print in AfterCompletions for addresses in 0x502000000–0x502100000). The title queues label stores into its own command-buffer range, in pairs per frame, and none is stored on the GPU:

    [labdiag] queued label 0x50200ad68 bytes 4 first 0x00000000 storedOnGpu 0 stamp 5710 queue 0
    [labdiag] queued label 0x50200ad68 bytes 4 first 0x00000001 storedOnGpu 0 stamp 5711 queue 0
    [labdiag] completion label 0x50200ad68 storedOnGpu 0 writtenBackSince 0 memory now 0x00000000 -> stored
    [labdiag] completion label 0x50200ad68 storedOnGpu 0 writtenBackSince 0 memory now 0x00000000 -> stored
    

    The same happens for other addresses in that buffer (0x502002d68, 0x502002f38, 0x502003040, …): 10516 such completion stores in one 300 s run. With storedOnGpu 0 the value only lands when the batch's completions run in finish. By then the title has already rewritten that memory as the next command buffer, so the late store overwrites a packet header. On hardware the label would be written in stream order, before the title moves on.

    Not established: why astrobot (93faece) does not stop here. With udmabuf.size_limit_mb=64 on both, so the same imports fail, astrobot ran 240 s without this error. So the difference is in the driver, not the import limit.

    AI-assisted: yes (Claude Code ran the watchpoint and the instrumented build and wrote this; the runs are on my machine).

  2. oneandonlydean commented on Oct 8, 2026

    @oneandonlydean
    Collaborator

    astrobot takes the same path here. WriteLabelOnGpu's import == nullptr branch (VulkanDevice.cpp:1255 on main) and Recorder::AfterCompletions are the same code in both. astrobot has no udmabuf import (815d274 isn't in it), so on RADV it can't import this range either and defers the same store. The difference is pacing: astrobot holds Driver::Submit while a submission with a flip is queued and not yet started (throttleSubmit, 40cd74e), so the title doesn't get far enough ahead to reuse that memory before the batch is reaped. That hides the bug but doesn't fix it. Two runs should confirm it (not run here): astrobot with APS5_MAX_QUEUED_FLIPS=off should stop at the same DWORD, and main with APS5_DRAIN_COMPLETION_LABELS=1 should get past it.

    The fix belongs in that branch. A label the GPU can't store has to be stored at its place in the stream, not when the batch is reaped. With the current code, the exact way is the drain path: wait for the recorded work, then store on the CPU. That means the deferred AfterCompletions(..., false) goes away. Recorder.hpp already describes this hazard for the storedOnGpu case, and the plain store has the same problem.

  3. klosixgaming-arch commented on Oct 8, 2026

    @klosixgaming-arch
    Contributor

    This is a complex GPU command buffer issue. Based on my review of recent PRs related to the AGC driver and shader recompiler, I can provide some context:

    The fact that oneandonlydean's astrobot branch runs past this point suggests there may be a difference in how command buffers are being processed or validated between the two implementations. The issue correctly identifies that the word 0x00000001 appears where a RELEASE_MEM header (0xc0064900) is expected, and that this happens consistently at the same DWORD offset.

    Some observations based on similar issues I've seen:

    1. The fact that it's the guest command buffer itself (not an indirect buffer) suggests the issue is in how the title constructs or submits its command buffers
    2. The pattern of RELEASE_MEM pairs between PUSH_MARKER/POP_MARKER is consistent with synchronization operations
    3. The possibility that the title fills the header after submitting the buffer (as noted at the end of the issue) is worth investigating - this would be a race condition where AnyPS5 reads the buffer before the title has finished writing it

    I'd suggest comparing how oneandonlydean's implementation handles command buffer submission and validation to see if there are any differences that might explain why it works.

  4. EdouardSence commented on Oct 8, 2026

    @EdouardSence
    ContributorAuthor

    Results for the two runs you suggested, plus one correction on the repro conditions.

    Repro conditions

    • The stop needs the DCB range to stay unimported. My original runs had udmabuf.size_limit_mb at the default 64, which I hadn't noticed.
    • With it raised to 8192, upstream main (6b57386 + feat(agc): implement deferred faults for reads through null SRT pointers #759, same build as before) did not stop in 7 runs of 100 s each, headless and windowed.
    • To reproduce without root I capped the host import budget with APS5_HOST_IMPORT_MIB=64 (host import budget: 0 MiB live of 64 MiB). That stops at the same place: unsupported PM4 packet type: header 0x00000001 at DWORD 8730 of 10340.

    main with the budget at 64, 100 s per run, headless gamescope

    run result deferred storedOnGpu=0 stores queued into 0x502000000–0x502100000
    default, 3 runs 3/3 stop at DWORD 8730 930 per run
    APS5_DRAIN_COMPLETION_LABELS=1, 3 runs 0/3 stop, run to the timeout 0

    So the drain path gets past it, and it removes every deferred store into that range. This matches your reading.

    astrobot with APS5_MAX_QUEUED_FLIPS=off: not confirmed

    AI-assisted: the runs and this write-up were done by Claude (Claude Code) on my machine.

  5. oneandonlydean commented on Oct 10, 2026

    @oneandonlydean
    Collaborator

    #2044 now stores labels the GPU can't reach in stream order. Could you retest on current main?

  6. EdouardSence commented on Oct 10, 2026

    @EdouardSence
    ContributorAuthor

    Retested on main a29bae3: fixed.

    Linux (CachyOS, GCC, Release), RX 9070 XT, RADV / Mesa 26.2.4, headless gamescope. I used the same repro conditions as before, APS5_HOST_IMPORT_MIB=64, so the DCB range stays unimported. Before, every run stopped about 20 s in on unsupported PM4 packet type: header 0x00000001 at DWORD 8730 of 10340.

    Closing, since #2044 resolves it.

    Tested and written by Claude (AI assistant) on a contributor's machine.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions