Files
AnyPS5/docs/dev
XairRrR 84e3b73f16 fix(agc): keep depth planes coherent with buffer reads and writes of their memory
A depth surface lives in its Vulkan image, so a buffer read of its depth
plane saw guest memory the surface never wrote, and a buffer write into the
plane never reached the surface: binding the target again kept the old
depth.

- A single-sample 32-bit depth surface with the 64 KiB Z swizzle
  (DB_Z_INFO SW_MODE 24) keeps a storage image in that swizzle over its
  plane. A bind that writes or fast clears depth marks the plane stale;
  FlushDepthPlanes copies the depth into the storage image and stores it
  into guest memory. It runs from StorageTexture::FlushPending, when a
  buffer upload finishes (over its regions and address space), and before
  a dispatch for each GuestBuffers V# it binds (a cached dispatch reads
  them without an upload). A reused build flushes its in-place buffer
  regions, and an image lookup flushes the range it reads, as do the
  write-stamp proofs that let a cached image or a reused build skip that
  lookup: a stale plane's memory looks unchanged to them.
- Stale planes are kept as ranges under their own lock with an atomic
  hull; a flush that overlaps none returns without the GPU and surface
  locks.
- Every bind of such a surface, and every flush of its stale plane,
  collects the plane's writes. Written by someone else since the surface's
  previous bind, store or reload, the plane is reloaded from memory
  instead of stored, so a guest write after a depth draw is not
  overwritten by that draw's late store. A pending HTILE fast clear wins
  over the reload.
- A color target flushes the stale planes under it before it retires their
  surfaces, so a target that loads or blends reads the stored depth. A
  retired surface's plane is no longer stale: a later flush never stores
  its old depth over what the new owner of the memory wrote.
- The depth surfaces lock is recursive: a store reached from a flush under
  DepthSurfaceTexture re-enters it.
- Draws pass whether they write depth, so read-only binds do not mark the
  plane stale.

PPSA05684 copies its main depth plane into two ping-pong planes with a
buffer compute, draws the cage's depth into them and fogs its menu from the
result; without this the copy carried nothing and the fog covered the
cliff and the cage.

agc_driver_depth_plane_buffer_memory draws depth 0.5 into such a plane,
fetches vertices from it (the plane must hold 0.5), writes 0.75 into the
memory and draws at 0.5 under LESS (must pass), then checks the depth
written after the reload reaches memory again. On a new plane it writes
memory after a depth draw and before any store: a buffer read must keep
the guest bytes and the next bind must reload them; a guest write before a
depth draw must then lose to that draw. A linear texture at an offset into
a plane must read what memory holds after a flush, also when it is viewed
through its cached storage image after another depth draw. On a plane with
HTILE, an HTILE fast clear after a guest write must win. A color target
that blends ZERO/ONE over a plane just drawn at 0.5 must write back the 0.5
it loaded.

AI-assisted: yes
2026-10-19 03:49:59 +02:00
..
2026-10-18 19:49:54 +02:00