DepthPlanePartialStore draws depth 0.5 into a 384x200 D32 Z_X plane (3x2
64 KiB tiles, the last row 72 texels high) over memory filled with 1.0 and
checks the plane's memory unit by unit:
- a read ending 3 KiB into the plane stores unit 0 alone (one store, one
unit, 64 KiB counted) and leaves the plane stale; the same read again
stores nothing;
- a read of the whole plane stores the other five units, the edge tiles
holding 128x72 depth values with their padding left as it was;
- a guest write into unit 4 after unit 0 was stored wins in unit 4 only:
a later whole read stores the four other stale units over 1.0, and a
LESS draw at 0.6 passes exactly over unit 4 (the plane-wide generation
synced every unit from memory instead);
- the retire of a surface the guest wrote into, through a view with two
levels, stores its stale units the guest did not write;
- a color target over unit 5 retires the surface after storing units 1-4;
- over unwatched memory a partial store leaves the other units on the GPU,
so a LESS draw at 0.6 passes nowhere.
TextureTiling checks that the 64KB Z_X equation of 4-byte elements reads
only x and y bits below 7, so each 64 KiB unit of a 3840x2160 D32 plane is
exactly one 128x128 tile.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A read of memory inside a stale D32 Z_X depth plane (FlushDepthPlanes) stored
the whole plane: a copy of the depth image into the mirror, MarkWholeWritten
and a write-back of every byte. In Super Meat Boy 3D (#8840) a read-only
buffer ending about 3 KiB inside a stale 3840x2160 plane makes
ShaderResources::Revalidate flush ~1000 times per 5 s, each one moving
31.9 MiB, bound by transfer bandwidth.
A depth surface now tracks its plane as 64 KiB units, each one 128x128 tile
of the mirror's block units: a stale bit and a write generation per unit
replace memoryStale and the plane-wide syncedGeneration.
- FlushDepthPlanes stores only the stale units the range overlaps: the depth
to mirror copy takes one region per unit rectangle (UnitRects, from the
mirror's slice windows), the mirror marks just those units written
(MarkUnitsWritten) and the write-back covers their hull. The other units
stay stale and the plane stays registered. Stale bits are cleared only
after the copy was recorded, and the stored units' generations advance
only when FlushPending stored them. A depth fast clear still pending at
the store rewrites the whole image, so it makes every unit stale first.
- SyncFromMemory copies from the mirror only the units the guest wrote since
their own generation (one ChangedBlocks scan; untracked memory counts as
unwritten, as WrittenSince did), so a guest write into one unit no longer
replaces GPU depth that is still unstored in the others.
- Flushes followed by a retire keep the whole-plane store: the color target
flush in Draw and a written storage view (DepthPlaneScope::Whole). The
retire of an overwritten surface in DepthSurfaceTexture first stores its
remaining stale units the guest did not write.
- A mirror without block units (APS5_NO_BLOCK_TRACKING, unaligned base)
falls back to the whole-plane copy, and APS5_DEPTH_PLANE_WHOLE_STORE=1
tracks the plane as one unit, the previous behaviour.
- DepthPlaneStoreCounts reports stores, units and bytes stored.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The detached thread of the abort-race case reads a flag that is a local
of the enclosing block, which ends before main calls std::abort(). Under
AddressSanitizer that read is reported as stack-use-after-scope. Make the
flag static.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
The DB depth copy case drew a two-sample depth surface, which lavapipe
cannot sample (it samples depth at 1 and 4 samples only). The copy then
threw outside the expected-failure checks and the test crashed on exit.
Pick 2 samples when the device samples them, else 4, else skip the
multisample half, and copy every sample of that count.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Each asynchronous call must start with valid arguments and finish signed out, refuse an unknown request and a non-null option; each synchronous call must return SCE_NP_ERROR_SIGNED_OUT. Targeted cases cover empty virtual users, the operation and sort types and the slot, user, friend and TSS size limits.
The add-and-get, try-and-set, multi-user and friends variable calls (NpId, account, virtual user and cross-save forms) run shadPS4's argument checks and then finish with SCE_NP_ERROR_SIGNED_OUT like the multi-slot variable calls; the synchronous forms wait for their asynchronous ones.
- Drain the draw pipeline before recording the copy, as the CB metadata
pass does, so the copy follows the queued draws that render the plane.
- Address the plane as decodeDepth registers it: a multisampled plane's
pipe-bank XOR bits are stripped and a DB_DEPTH_VIEW slice is added.
Mipmapped or partially resident planes are refused.
- Refuse a color target with CMASK fast clears, as the CB resolve does.
- Find the source through the depth owner (planeSurface) and require a
32-bit float surface with the decoded sample count.
Co-Authored-By: Claude Opus 5.5 <[email protected]>