A sampled copy of a depth plane is kept while the surface's write
serial is unchanged. Storing a written storage view back into the
depth image did not bump the serial, so a later draw or dispatch that
sampled the plane as an array or cube kept the values from before the
store. The store-back bumps it now.
The dispatch test samples the plane through a copy, stores to it in a
dispatch and samples it again.
Draw depth and stencil, read and rewrite each plane in compute
dispatches, and check the stored values with depth-tested and
stencil-tested draws, a following dispatch and the flushed guest bytes.
The array view, multisampled and two-view refusals are checked through
dispatches as well.
A 2D array or cube view with the plane's extent and format reached the
ordinary path and read guest bytes the depth was never written to; it
throws again, with the message main has for it. A multisampled surface
is refused before the plane copy, as sampling it already is. A written
view that another view of the same plane replaced had its results
dropped at store-back; that throws now.
Update the debt entry to what is supported and what still throws.
A D16_UNORM_S8_UINT surface is stored as D24_UNORM_S8_UINT or
D32_SFLOAT_S8_UINT on devices without the 16-bit format. Copying its
depth aspect yields 4 bytes per texel, so the 16-bit storage image of
the depth plane would receive the wrong layout. Such an access now
throws, naming the surface and both formats; the stencil plane keeps
its 8-bit layout and stays supported.
Compute shaders bind the depth and stencil planes of a depth surface as
storage images, to read the depth or to write it before later draws
test against it. The driver kept depth on the GPU and refused such
bindings.
A depth surface now owns one storage image per plane (R32_SFLOAT or
R16_UNORM for depth, R8_UINT for stencil). Binding copies the plane
into it through a staging buffer; a written element is copied back into
the depth image during write-back, so the next draw sees the shader's
depth.
A view whose extent differs from the surface's means the memory was
reused for another texture and takes the ordinary texture path; this
applies to sampled views of a depth surface too.
PPSA15304 copies depth and stencil through storage images every frame.
Sampling a depth array, cube or R16_UINT view of depth surfaces went
through DepthPlaneCopy::Refresh on every use. Each use copied every slice
a depth surface holds into the staging buffer and the whole staging buffer
into the copy image, with three ALL_COMMANDS barriers, although nothing
had written the slices since the previous use.
Each depth surface now carries a write serial, bumped when a draw binds it
as its depth target and when a pending fast clear is applied. The copy
keeps the image and serial of every slice it copied. A use copies only the
slices whose surface or serial changed and the guest layers that changed
(as before), and records nothing when none did. A slice whose surface is
the depth target of the latest depth draw is copied at every use until
another depth target is bound, since that draw may still be recorded after
the copy.
Test: agc_driver_depth_plane_guest_layers counts the recorded slice copies
and copy fills; a second use with nothing written records none (it records
one of each without this change), a draw to a slice's surface or a CPU write
to a guest layer copies only that layer.
A multisampled target's samples live only in its host image, so a fill
of its color memory never reached them: a title that clears its MSAA
targets that way (with no CMASK) kept drawing over the previous frame.
A uniform fill over the whole color memory now clears the host image to
that value at the target's next use, the same way a CMASK fast clear
does, and a pending CMASK clear still takes precedence. The color memory
is sized with addrlib's block dimensions for the sample count
(ComputeThinBlockDimension): a 64 KiB block holds width x height x
samples elements, laid out width first for 1x and 4x. A fill over part
of it, over a target whose footprint is not computed, or with a value
that has no exact clear value in the format throws at the next use.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
PPSA34063 (NHL 27) calls it with a 16-byte buffer outside a coredump
handler and expects 0x81180003 there. The registered handler is never
invoked, so every call is outside one.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
(cherry picked from commit d04f5d600e52372b968ce0f06139f519fe068724)
With SPIRV-Tools enabled the optimizer replaces a window that is only
indexed by constants with scalars, so the sampler spill case found no
array. It now reads M0 from the thread group id, as the first case does.
The direct access test reads and writes lanes across a wave32, which a
device with 8-lane subgroups cannot hold; it skips there like the
v_readlane and v_writelane tests.
Write window registers directly (VALU, v_writelane_b32, buffer load,
v_movrels_b32 results), read them back directly and through
v_movrels_b32 at several M0 values, including after a direct rewrite,
and feed a v_readlane_b32 of the written lane into the output.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01V1W4jdNSKTV7xwuS6xQPJV
A compute program reads v4 relatively with v_movrels_b32, spills sampler dword
0 into v4 with v_writelane_b32, restores it with v_readlane_b32 and samples
with it. On main the restore reads the window array and resource analysis
refuses GetSamplerResource with ReadLane(LoadVectorWindow(Immediate),
Immediate).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01V1W4jdNSKTV7xwuS6xQPJV
A program that uses relative VGPR addressing placed every register from the
lowest relatively addressed one upward in the window array, so even direct
accesses became array loads and stores. A descriptor spilled with v_writelane
and restored with v_readlane then lost its definition, and resource analysis
refused GetSamplerResource with ReadLane(LoadVectorWindow(Immediate)) (GTA V,
PPSA04264, shader 0x25a889400).
When the program has no indexed writes (v_movreld, v_movrelsd, v_swaprel),
direct accesses stay SSA registers and each direct write is mirrored into the
window for the relative reads.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01V1W4jdNSKTV7xwuS6xQPJV
A relinked executable that cannot load a library reports
"GetLastError: 126 - The specified module could not be found.", which also
covers a library whose dependent DLLs are missing. On Windows a self-built
libs/ directory needs libgcc_s_seh-1.dll, libstdc++-6.dll and
libwinpthread-1.dll next to it. For error 126 the stub now adds a line naming
them.
Refs #4482
Animal Well (PPSA22520) checks for its save with a CREATE2 mount it never
unmounts, then saves with a second mount of the same directory. That
mount returns BUSY, and the title keeps using the first mount point for
sceSaveDataPrepare, its save file and sceSaveDataUmount2.
sceSaveDataMount3 cleared the result before its checks, so the save was
written to "/save" in the game folder instead of the save directory, and
the first mount was never released. The result is now written only when
the mount succeeds, as shadPS4 does.
The multisampled target guest access test now also reads the target's
memory through ReadCommitted and ReadCommittedUnsynced and expects both
to throw.
ReadCommittedUnsynced skipped the read guard ReadCommitted runs before its
flush hook, so a storage image capture over a multisampled target's
memory read the bytes instead of throwing. Both reads now run the guard,
ReadCommitted still before its flush hook, and share the copy.
FreeBSD's pollscan clears POLLOUT whenever POLLHUP is set, so a write end
whose read end is closed reports POLLHUP alone, with POLLIN and POLLRDNORM
when they were asked for; both host paths reported POLLOUT | POLLHUP.
POLLOUT on a read end now throws. FreeBSD opens both ends FREAD | FWRITE
and pipe_poll reports the read end writable, which a one-way host pipe
cannot back.
guest_poll drained 1 KiB from the full pipe before expecting POLLOUT, but
Linux reports it only once a whole 4 KiB page is free, so the test aborted
there. It now drains the pipe, which is writable on every host.
powf(1.0, nan) returned 0x7fc00001; FreeBSD msun (lib/msun/src/e_powf.c)
returns 0x3f800000. That case now follows FreeBSD; other inputs are
unchanged.
Co-Authored-By: Claude Haiku 5.5 <[email protected]>
A compute pass can write a block-compressed surface through an uncompressed
storage view whose element is one block (32_32_UINT for 8-byte blocks,
32_32_32_32_UINT for 16-byte ones). cachedTexture rejected such a storage
image for the BC descriptor, so every sample stored the whole surface to
guest memory, compared it with the snapshot and uploaded it again.
Texture::CanBlockCopyFrom accepts a storage image over the same memory,
tiling and swizzle whose element is the block and whose extent is the
surface's extent in blocks, with whole blocks on every copied level. The
sampled texture then owns a BC image that vkCmdCopyImage refreshes from the
storage image when its version moved, through the same refreshed-on-reuse
path as the depth copy.