Files
AnyPS5/docs/dev
thuanquangandClaude 0ec6032d23 fix(agc): store resident linear color targets at completion points, limited to their drawn rectangle
A recorded draw into a resident linear color target stored the whole
image to guest memory right after the draw. Every draw copied the full
surface, waited for the previous draw's store in the open batch (the
pending-writer check of FlushPending), and the recorded copy landed over
CPU stores made after Draw returned (#8152).

A draw now records its scissor, clipped to the image, as a union
rectangle in the target and lists the target as drawn. The listed
targets are stored before each point where the guest can first observe
the draws' completion: a flip (inside its locked block, before the
flip's submit, so the flip's end-of-pipe interrupt and the presenter
follow the store), a drain (which covers APS5_SYNC_FLIP=1),
VulkanDevice::WaitIdle, a label the GPU writes for the graphics queue
(WriteLabelOnGpu), and an interrupt-only RELEASE_MEM in
preparePacketMemory and in commitLabel, which submit the store's batch
before the interrupt can be delivered. The idle store, the access hooks
and the eviction store are unchanged and also store by rectangle.

A store of a drawn target copies the rectangle out of the image and
writes it row by row at the guest pitch into the host import, stamped
with one MarkWritten per run of 64 KiB blocks. A block that only other
driver stores wrote since the target's generation keeps the old rule.
In a block the CPU wrote, or that changed outside the write watch, only
the rectangle's rows are stored, so CPU stores outside the rectangle
stay, and the target re-uploads at its next use. A target with an
attachment proxy, several mips or layers, a 3D or DCC surface, or
results of a dispatch, fill or copy is stored whole at the same points.
A store no longer waits for the same target's previous store: the
pending-writer check skips the write notes of the target's own stores
when it has a host import.

APS5_PROFILE_DRAW adds the drawn targets' stores by reason and the
pending drawn targets (count, MiB, oldest) to the [storage] line.

The tests cover a target that stays pending across draws and labels
until WaitIdle without a submission, #8152's CPU stores after Draw
(ported from #8246, seeded and unseeded, inside and outside the write
watch), CPU stores outside the drawn rectangle and in the gap before a
target that starts past a 64 KiB boundary, and a flip, a drain, a label
and an interrupt-only RELEASE_MEM through AgcDriver::Submit with the
queue held by a WAIT_REG_MEM, inside and outside the write watch.

Co-Authored-By: Claude <[email protected]>
2026-10-23 16:51:34 +07:00
..