AGC and the PM4 command stream
A PS5 title builds GPU packets in its own memory and submits the buffer. PS5PCEM decodes that PM4 stream, keeps the register state, and executes draws and dispatches in order.
Repository notes through October 10, 2026
The stream is the graphics API
The title does not have to call a high-level draw function for every triangle. It writes packets: register updates, draws, dispatches, fences and flips. Whichever layer produced the buffer, the GPU sees the same stream. The decoder names the packets whose opcodes have a documented meaning and leaves the others as numbers. An invented name in a trace would be worse than an opcode.
Packet body length is stored biased by one, so an empty body cannot be encoded. Every step checks its bounds. A body that does not fit is reported. It is not clipped, because a clipped body would shift every following packet and the trace would lie.
State, waits and indirect buffers
Register state survives across submissions, including writes of zero. The executor applies direct register lists, native and legacy indirect lists, acquire and release, 32-bit and 64-bit waits, writes, events and SetFlip. A wait that is not met returns blocked and the exact word to resume from. Guest memory is not modified to manufacture progress.
Indirect buffers are followed recursively, both the ordinary 4-dword form and the conditional 14-dword form. Chain packets end the parent. Nesting stops at sixteen frames. A blocked child returns a fixed path from the root to the leaf, so resuming does not replay draws that already happened. The scheduler copies each root command buffer and the indirect buffers it can reach, so the title may recycle the arena while a wait is still blocked.
From registers to a draw
At a draw or a dispatch the register snapshot becomes typed resources: 128-bit buffer and sampler descriptors, 256-bit image descriptors, eight color targets, depth and stencil, viewports, scissor, cull, blend, and the PS5 swizzle and MSAA fields. Missing color-control and clip-control writes inherit the AGC defaults. An explicit disable stays a disable. Two CPU workers prepare graphics and compute commands. One Vulkan owner submits them so execution and completion stay ordered.
Shader metadata supplies the resource tables and the user-data registers. Scalar provenance walks a bounded prefix of the shader, loads only the guest memory the prefix actually touches, and stops on an unknown branch instead of inventing a descriptor. The result is what the translator and the Vulkan backend consume.
What is implemented
- PM4 decode with biased body lengths and hard bounds on every packet.
- Persistent register banks, blocked waits, and recursive indirect buffers up to sixteen frames.
- Typed buffers, images, color targets, depth, viewport, blend and MSAA state at draw time.
- Two preparation workers and one ordered Vulkan submission owner.
What is still missing
- An opcode without a documented meaning stays unnamed.
- A blocked wait is never cleared by writing a fake fence value.
- Layers, metadata and a few image operations are still incomplete. Those have their own pages.
Related mechanisms
What these pages are