Commit Graph

27 Commits

Author SHA1 Message Date
alfalfa-star 124be3e7e8 feat(agc-driver): execute boolean SET_PREDICATION
SET_PREDICATION threw, and packets with the predicate header bit were
rejected. The executor now keeps the queue's predication: operations 3
and 4 read a 64- or 32-bit value and bit 8 selects whether predicated
packets run when it is non-zero or zero; operation 0 clears it. Before
a predicated packet runs while predication is active, queued labels are
recorded and the value is read, as for COND_EXEC; the packet is skipped
when the predicate fails.

Indirect buffers are inlined when a submission is copied, so a
predicated INDIRECT_BUFFER call keeps its header in front of the
inlined commands and records their end like a COND_EXEC range; the
block runs or is skipped on one evaluation, as on the command
processor. Query predication, a predicated COND_EXEC, predicated chains
and flips inside predicated command buffers throw.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 21:02:47 +02:00
Dean 0a081cbe8c
Merge pull request #673 from Celegans12/feat/agc-pm4-cond-exec
feat(agc): implement COND_EXEC
2026-10-06 07:49:33 +13:00
Celegans12 61d2fb0a53 feat(agc): accept the WRITE_DATA cache policy
WRITE_DATA's control dword carries a two-bit cache policy in bits
26:25 (LRU, stream, no-allocate, bypass). Validate refused it, so a
submission with a WRITE_DATA built with a non-zero policy was rejected
as a whole.

The policy only steers how the GPU L2 keeps the written lines; the
stored words are the same, and Execute already writes them to guest
memory in queue order. The mask now accepts bits 26:25, as was done
for DMA_DATA's cache policy hints. The CE engine and the remaining
reserved bits still throw, and the message no longer names the cache.

agc_driver_pm4 stores both dwords of a WRITE_DATA with control
0x04100200 and checks that reserved bit 27 is still refused.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 17:51:17 +02:00
Celegans12 9df0de2990 feat(agc): implement COND_EXEC
Validate refused every COND_EXEC, so a submission that uses one was
rejected as a whole. The packet now reads the dword at its address once
the earlier packets of its queue and their GPU writes have completed,
and skips the exec_count dwords after it when the dword is zero.

The command copy that inlines INDIRECT_BUFFERs records where each range
ends, so a range over an INDIRECT_BUFFER skips the whole buffer.
Unaligned addresses, address bits 48 and up, and reserved control and
count bits throw; the cache policy is accepted on compute queues only,
as the MEC defines it. A flip inside a range, a range that ends inside
a packet or past its command buffer, and a chained INDIRECT_BUFFER or
REWIND inside a range throw.

agc_driver_pm4 and agc_driver_flip cover the skips and the rejections.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 17:51:11 +02:00
Dean 98004c632d
Merge pull request #443 from oneandonlydean/fix/agc-write-data-pfp
fix(agc): accept WRITE_DATA with ENGINE_SEL = PFP
2026-10-04 11:32:58 +13:00
Dean 3bc8e94324
Merge pull request #439 from oneandonlydean/fix/agc-dma-copy-on-gpu
fix(agc): record large memory-to-memory DMA_DATA copies on the GPU in queue order
2026-10-04 11:32:07 +13:00
Dean Galvin b85358c021 fix(agc): accept WRITE_DATA with ENGINE_SEL = PFP
WRITE_DATA's ENGINE_SEL (control bits 31:30) picks the CP engine that
performs the write: 0 the micro engine, 1 the prefetch parser, 2 the
constant engine. Validate refused every engine bit, so a submission
with a PFP WRITE_DATA failed as a whole. The prefetch parser handles
packets in queue order ahead of the micro engine, and the driver already
performs the write in queue order, so PFP is accepted like ME. The
constant engine stays refused.

Tests: agc_driver_pm4_tests runs a PFP WRITE_DATA and checks that a CE
one is still refused.
2026-10-03 20:16:31 +13:00
Dean Galvin 895c1c0eed fix(agc): record large memory-to-memory DMA_DATA copies on the GPU in queue order
A DMA_DATA too large to resolve as a store drained the device and then
copied on the submitting worker's thread. For a large range that copy takes
milliseconds, and meanwhile another queue's worker records, submits and runs
work that reads the destination in place. PPSA21564 copies each 12 MiB
frame of its intro video into one of two textures with a single DMA_DATA on
one queue and samples it on queue 0 without waiting for that queue; the
GPU's own DMA finishes in microseconds, so the title never needed to. Here
queue 0's upload of the texture ran while the CPU copy was still writing
it, and a frame showed the new frame's luma over the chroma of the frame
two before.

Such a copy (both addresses memory and incrementing, ranges disjoint and
non-empty) now goes through VulkanDevice::CopyBuffer like the copy kernel:
a transfer between the host imports, recorded in order, so everything
recorded after the packet reads the whole copy. The drain and CPU copy
remain the fallback when either range is not host-imported.
2026-10-03 20:16:25 +13:00
Dean Galvin a4264793b1 perf(agc): keep a queue's registers in flat arrays instead of a std::map
Every SET_*_REG packet stored each register into a std::map, and every
draw read dozens of them back through map lookups (the decoders, the
draw key's range walks, the prechecks). PPSA21564 sends ~350k register
packets per 10 s at the title, and the map's node allocations and tree
walks were a visible share of the graphics queue worker's time.

Registers is now a flat value array with a presence bitmap per bank. It
keeps the map's interface and semantics: absent registers stay absent,
iteration and lower_bound walk the present registers in offset order,
emplace does not overwrite and at() throws for an unset register.
2026-10-03 09:48:44 +13:00
boykopovar 52ab9e3544
Merge pull request #176 from oneandonlydean/fix/agc-indexed-draw-index-offset
fix(agc): apply GE_INDX_OFFSET as the base vertex of direct indexed draws
2026-09-30 21:13:57 +03:00
boykopovar d1bf55ca14
Merge pull request #118 from oneandonlydean/feat/dispatch-tunnel-hint
feat(agc): accept the dispatch tunnel hint
2026-09-30 18:05:45 +03:00
Dean Galvin f4143d6186 fix(agc): apply GE_INDX_OFFSET as the base vertex of direct indexed draws
The GE adds GE_INDX_OFFSET to every index it fetches. The driver applied
it to auto draws only, so DRAW_INDEX_2 and DRAW_INDEX_OFFSET_2 fetched
from vertex 0 whatever the register held. Both packets now take it as
their base vertex, and like an auto draw they refuse a queue state without
the register (its reset value, 0, is part of the initial state).
2026-10-01 00:26:00 +13:00
STL1te 6b36c050fe style: drop the branch's code comments per CONVENTIONS.md
Only the lines this branch added lose their comments; the commits before
keep them, with the reasoning behind each change, for whoever digs into
that code later.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:25:29 +03:00
STL1te 19521c2ecd feat(agc-driver): occlusion counters from Vulkan occlusion queries
EVENT_WRITE PIXEL_PIPE_STAT_DUMP (event 0x39) dumps the DB sample
counters. The recorder, once a title asks for them, keeps an occlusion
query open over each batch (precise when the device supports it) and adds
the result to a running count when the batch is reaped. A dump drains
recorded work like a label and writes the count in the PS5 layout: 16 DBs
16 bytes apart, begin and end counters interleaved, the count in the
first and bit 63 marking each ready. Kyty and SharpEmu write a fixed
"visible" result instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:22:17 +03:00
STL1te 2476bfda56 feat(agc-driver): depth/stencil and mip-chain targets, more color formats
- Depth/stencil: draws that test depth or stencil against a bound surface
  render with a GPU-only depth/stencil attachment (DepthSurface), cleared
  to DB_DEPTH_CLEAR/DB_STENCIL_CLEAR when made. Z test/write/function and
  per face the stencil function, operations and masks (BACKFACE_ENABLE);
  replacements by another value where Vulkan's single reference can carry
  them. Clear and copy draws, add/sub other than 1, array or mip views
  and MSAA throw, and texture reads of a surface's memory are refused.
  Scaleform menus mask with the stencil (REPLACE 0, ADD_CLAMP, EQUAL);
  their masked content was skipped before.
- Mipmapped color targets render through the resident image of the whole
  chain with a view of the mip, so mips in the packed tail are drawn too;
  CB_COLOR_VIEW's mip level is read from bits 26-29 (GFX10).
- Color: SNORM targets, UNORM16/SNORM16 exports, one-component formats
  honouring COMP_SWAP (A8), 32_R/32_GR/32_AR exports, linear rows padded
  to 256 bytes, BLEND_BYPASS.
- INDIRECT_BUFFER jumps are followed when copying a submission; thin 3D
  textures in display and rotated XOR swizzles; only the bytes the GPU
  changed are written back; resource registration.
- VideoOut: a flip stalls the GPU queue while the flip queue is full and
  holds the submitter back.
- APS5_DUMP_FRAMES_EVERY dumps every k-th presented frame.
- The graphics test target builds again (missing sources, a hand-aligned
  64 KiB buffer, stale expectations updated) and gains DepthStencilTests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 21:22:15 +03:00
Dean Galvin 8ada7510bd feat(agc): accept the dispatch tunnel hint
DISPATCH_INITIATOR bit 13 (TUNNEL_ENABLE) asks the SPI to launch the dispatch's waves ahead of
other work. It is a scheduling priority hint with no effect on the results, so direct and indirect
dispatches accept it like the other ignored modifier bits.
2026-09-29 13:05:49 +13:00
boykopovar 829e8c14ae fix(tests): align agc flip waits and memory synchronization checks 2026-09-28 19:32:43 +03:00
Dean Galvin e1a8371bff feat(agc): DMA_DATA cache policy hints and GDS source/destination
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ButHENCbXXt8h4EZuWUabJ
2026-09-28 16:51:01 +13:00
devilismyfriend 29b4601564 perf(agc): dispatch and draw recipes, data-only cache hits, unit shadows, bindless image tables
Dispatch cache with per-key value variants and data-only hits (flat-SRT leaves the recompiler
proves pure are refreshed into the resource template instead of re-captured), dispatch and draw
recipes replaying a proven prepare, register-keyed draw entries, template data refresh, unit
shadows in device-local slabs, 64 KiB block-unit storage tracking with windowed detile, DCC
clear-key proofs, per-class GPU timing, a CPU copy path with batch read tracking, present slot
ring, rate-limited reaps and lazy completion counting, plan-failure and poisoned source memos,
bindless image tables (runtime-indexed descriptor arrays from a CPU-read table) so the
per-frame compute program that failed its plan now compiles. Worker affinity opt-in, per-draw
logs behind APS5_TRACE_DRAWS, wait-timeout reports include the recorder's view of the label.
Fixes a use-after-free behind BDA-miss dispatch snapshots and the CPU-write stamp of
UnchangedSinceCollected. Intro-video stage: 154 -> ~500 presents per 10 s at 4K.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0177gthrWEBBfBu5xJDXgBfo
2026-09-26 19:00:40 -07:00
boykopovar 5a280ced87 perf(agc): keep render targets on gpu across acquire_mem 2026-09-25 08:22:43 +03:00
boykopovar e98d2163f4 refactor(log): remove extra logs + refactor timing logging 2026-09-24 20:35:59 +03:00
boykopovar 4734f43c60 feat(agc): add ACQUIRE_MEM handling in agc driver 2026-09-22 20:35:15 +03:00
boykopovar 8fd65f2a25 add EVENT_WRITE support for CS/GS/PS_PARTIAL_FLUSH + relinker return exit code from autorun 2026-09-22 20:27:49 +03:00
boykopovar f7aaa2fb86 feat(agc): add DRAW_INDEX_AUTO handling impl 2026-09-22 20:07:09 +03:00
boykopovar 74613f7e0f feat(agc): extend graphics compiler contract and add mesh and tessellation paths 2026-09-15 21:19:06 +03:00
boykopovar b9cc7ffd85 feat(agcDriver): add draw handling and shader recompile preparation 2026-09-14 12:06:35 +03:00
boykopovar 699df8d5fa feat(agcDriver): add 54 PM4 execution and indirect dispatch support 2026-09-14 11:43:13 +03:00