Ghost of Tsushima (PPSA02225) samples a two-sample D32S8 1920x2160
target with a separate stencil plane and a depth-only HTILE that is
neither pipe-aligned nor ITERATE_256. The import required a pipe-aligned
HTILE.
Pipe alignment only decides where each tile's word sits in the HTILE.
When every word is the same and proves the clear, their order cannot
change what they prove, so a depth-only HTILE that is not pipe-aligned
is imported when all its words are one word proving the clear value.
A non-pipe-aligned HTILE whose words differ is refused ("native
multisample depth HTILE that is not pipe-aligned holds more than one
word"), and one that holds stencil state keeps the alignment refusal.
The range stays HtileMetadataBytes(extent): Ghost's whole-HTILE fill
covers exactly that, 0x50000 bytes for 1920x2160. ITERATE_256 is
already independent of the import (752cca10f).
Tested: agc_driver_native_depth_separate_stencil runs every separate
stencil case on a depth-only HTILE that is not pipe-aligned or
ITERATE_256 too, sampled through a descriptor naming that HTILE and one
without metadata; one differing word is refused. Without the change the
target refuses "native multisample depth initial import requires
pipe-aligned HTILE without VRS".
Once its D32S8 target imports, The Grinch: Christmas Adventures
(PPSA07656) samples the depth plane through a T# with no metadata
(META_DATA_ADDRESS 0, not pipe-aligned) while the target has its HTILE.
The pipe/bank XOR and ITERATE_256 match. CheckResource required the
descriptor's metadata to be the target's HTILE and stopped the title
with "native multisample depth sampled metadata or XOR mismatch".
The host image keeps the depth decompressed, so a descriptor that reads
the plane without metadata reads the values a metadata-aware one does.
CheckResource now accepts a descriptor with no metadata at all beside
one naming the target's HTILE, when its address, format, XOR and
ITERATE_256 match. A descriptor with any other metadata keeps refusing.
Assumption: on hardware such a read returns the decompressed depth only
once the guest has expanded the plane (an in-place expand with
compression disabled). Main draws an in-place expand as an ordinary draw
that writes the depth attachment (DB_RENDER_CONTROL compress-disable bits
are not refused), over a host image that already holds the decompressed
depth, and has no out-of-place expand for multisampled planes. Nothing
here observes whether the guest expanded first; a title that samples the
plane unexpanded gets the decompressed values instead of the raw plane.
Tested: agc_driver_native_depth_separate_stencil samples the separate
stencil target through a descriptor without metadata, before and after
raster writes and after a depth-only HTILE fill, and gets the depth.
The same descriptor with another XOR and one naming other metadata are
refused. Without the change the first sample refuses "native
multisample depth sampled metadata or XOR mismatch".
The Grinch: Christmas Adventures (PPSA07656) binds a two-sample
D32_SFLOAT_S8_UINT target whose stencil is a plane of its own and whose
HTILE is depth-only (DB_STENCIL_INFO.TILE_STENCIL_DISABLE), so HTILE
holds no stencil state. Every byte of that plane is the clear stencil
when the target is first bound. The import refused it ("native
multisample stencil import requires HTILE stencil metadata") and the
title stopped before its first present.
With a depth-only HTILE the stencil is uncompressed in its plane, so the
plane is its own proof: the import scans it once and accepts the target
when every byte equals DB_STENCIL_CLEAR. The depth keeps its HTILE clear
proof. The plane is already one of the import's ranges, accessible,
watched, generation-checked, guarded from guest publication and kept
apart from the depth and HTILE ranges, so a later CPU or GPU write to it
refuses sampling like a write to the depth. The host image is created
cleared to the clear stencil. The plane's base keeps the 64 KiB
alignment of the depth plane: both use SW_64KB_Z_X, the decode takes
the pipe/bank XOR from the depth base's low 16 bits and masks both bases.
A whole HTILE fill of such a target is proven for the depth only and
clears only the host depth: the stencil plane is untouched by the fill
and still proven unchanged since the import.
A stencil plane that is not all clear, a stencil in neither HTILE nor
its own plane, D16S8 and HTILE words that do not prove a clear keep
their refusals.
Tested: agc_driver_native_depth_separate_stencil imports a four-sample
target (two and eight where the device has them), samples the clear
depth, stencil-tests the clear stencil, and refills a depth-only HTILE
keeping a replaced stencil; one stencil byte not clear, a later stencil
write and an unwatched plane are refused. Without the import change the
target refuses "native multisample stencil import requires HTILE
stencil metadata"; without the fill change the refilled target loses
its stencil.
Brings upstream main a6dcea927 under #6300's two commits.
Conflicts:
- DepthSurface.cpp prepareDepthSampling: #6300's stencil checks are kept
and main's 752cca10f drops the ITERATE_256 requirement, so the HTILE
check is main's line ("requires pipe-aligned HTILE without VRS").
- DepthSurface.cpp NoteHtileDepthClear and NoteDepthMetadataFill: #6300's
clear and fill proofs are kept, written with main's first-refusal-wins
DepthSamplingState::Refuse. After the proven whole-fill branch, the
remaining fills take main's ForgetClear/NoteHtileClear and single-sample
plane-fill paths.
- NativeMultisampleDepth.cpp CheckDepthTarget takes both #6300's
ClearSource and main's iterate256, in that order; main's ITERATE_256
call passes ClearSource::HtileDispatch.
- docs/dev/debt/libSceAgcDriver.md: one entry with #6300's stencil and
fill text and main's ITERATE_256 text.
Adapted to main: main samples a native multisampled depth target
through a shadow copy that is refreshed when the sampled view is looked
up (1912045c1, 5a0a00f42). CheckStencilTarget recorded its raster and
the fetch in one batch, so the fetch read the shadow from before the
raster ("native depth-stencil sampled fetch lost a depth sample or a
stencil test outcome"). It now submits the raster, looks the view up
again and syncs before the fetch, as main's CheckDepthTarget does.