The settle read keeps a private import's window open for one round trip on the settle queue, so a
store from another thread can land inside it. CheckImportWindowOtherThread: a store of new bytes from
another thread within the window counts as written, and a same-value one keeps its possible CPU
touch. The debt entry notes the longer window.
On Windows a host import without a section alias left guest write tracking, and its changes were
found by comparison. Since resident direct memory became private MEM_WRITE_WATCH memory, its
imports take that path, and every storage-texture refresh over it compares its whole snapshot.
ProbeImportWriteProtection gets a Windows body on MEM_WRITE_WATCH scratch memory, and
decideImportWatch keeps direct imports of private read-write memory watched when GetWriteWatch
stays honest after an import's first GPU use. The driver marks every imported page written until
that use completes, so each such import is settled inside ImportWatched's window by a 4-byte read on
a second queue of the graphics family (the imports lock comes after GpuMutex, so the main queue
cannot be used there). APS5_NO_WATCHED_PRIVATE_IMPORTS=1 keeps the comparisons.
Since #757, a T# loaded from a buffer heap at a runtime offset is an
image table column, and every capture snapshots the whole heap, up to
65,536 records, even when user data or an SRT read fixes the offset.
When the T#'s eight dwords and its offset are runtime values the SRT
walker evaluates, the column is now selected: the offset is kept as a
descriptor source, the shader indexes entry 0, and the snapshot reads
only the record at the evaluated offset, with the heap base moved to
that record.
The column keeps a table's semantics. An invalid T#, an unmapped record
or an offset that carries past 32 bits is poison that faults only when a
lane selects it; an offset the walker cannot read faults the table
instead of throwing; the record's mode is picked per entry, so no
pipeline variant is added; and a dispatch that writes the record faults
it as written by its dispatch. Dwords past the heap read zeros, as the
scalar loads would, and a record past the key cap is read rather than
poisoned.
A column stays a whole table when its offset is chosen per lane, or when
the shader may write the memory the offset is read from at run time: the
buffer it is read from (by V#), or any memory when the read or a write
goes through a pointer or a GPU-only descriptor. Samplers are unchanged:
an S# the walker evaluates is already a direct sampler. The plan stores
the selection, so the disk cache format is 36.
Five agc_shader_memory and agc_shader_bindless checks asserted the old
planning and now assert the selected record:
- "image table SRT key": a key read through the SRT narrowed a 4-key
table to records 0 and 2. It now selects record 2 alone, captures no
other record, and a changed key moves the capture without changing the
module or its disk key.
- "image table key union" and "image table late key": two keys of one
heap shared one column with two value key domains. Each key now
selects its own record, as two one-record tables.
- "image table unkeyed access": a read keyed through the SRT shared a
whole column with a read keyed per lane. The first now selects its
record; the second keeps the whole, unnarrowed table.
- "uniform table image": the T# at a user data offset was one key of a
full table. It is now the one selected record, and the record the user
data does not select is not read.
A value key domain only arises for a key the walker evaluates, so it no
longer narrows an image column; key buffer domains (keys loaded per
lane) still do.
A draw with PA_SC_AA_CONFIG.MSAA_NUM_SAMPLES 2 (4x) and MSAA_ENABLE
clear into a 4x depth/stencil and color pair threw "multisampled
targets rasterized without MSAA_ENABLE are unsupported for points,
lines, a depth target or alpha-to-coverage", which stops METAL GEAR
SOLID: Peace Walker (PPSA18216) at its first presentation (draw B on
#5268). A depth target with the same sample count now gets the same
pixel center samples as the color targets, so each depth and stencil
sample is tested and written with the depth at the pixel center, as GL
allows when multisampling is disabled.
DB_EQAA Z interpolation or overrasterization and a sample-mask export
with a depth target throw on this path.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Decode the four PA_SC_AA_MASK fields at the rasterized sample count. Use the native Vulkan mask when all four pixels agree and apply varying masks in the fragment shader, preserving helpers and combining coverage with alpha-to-coverage and shader mask exports. Add the normalized masks to pipeline, draw and shader keys and the versioned replay request.
Refuse unsupported conservative-raster, centroid and early depth/stencil memory-write cases. Synthetic readbacks cover driver submission, depth/stencil suppression, fragment stores and one-sample and four-sample coverage.
Reject native sampled views of the depth image attached by the same draw before pipeline creation. Keep unrelated views, other devices and the single-sample path unaffected. Add unrun native-view refusal and scope controls; full dependency-stack build and runtime validation remain pending.
Adapt our preserved native-depth sampling work from c0d9edf and sample-aware footprint work from 6e35a877, retaining creation-time coherence and initial HTILE proof. The descriptor interface in upstream PR 4820 remains a separate prerequisite. This source draft has not been built or run.
EVENT_WRITE (PM4 opcode 0x46) with event type SAMPLE_STREAMOUTSTATS1-3
(0x01-0x03) or SAMPLE_STREAMOUTSTATS (0x20) failed submission validation
with "EVENT_WRITE event type 1 is not implemented". Minecraft Preview
(PPSA19639, discussion #1277, stop 9) submits a 2-dword type-1 packet
while entering a world, and the GPU thread aborted intermittently.
The four values are VGT_EVENT_TYPE entries in Linux
drivers/gpu/drm/amd/include/navi10_enum.h L14155-14188 at
0fcb05b72344f40806cbe810de8872f1698bf053.
drivers/gpu/drm/amd/amdgpu/nvd.h L326-347 at the same commit documents
these events only with the sampling index (3, or
EVENT_INDEX__SAMPLE_STREAMOUTSTATS* 8-11 on gfx10), followed by
ADDRESS_LO/HI. The 2-dword index-0 packet has no destination dwords, and
what the CP does with it is neither documented nor measured. AnyPS5 does
not emulate the VGT stream-out counters, so there is nothing to sample.
Packet execution already skips EVENT_WRITE.
These event types are now accepted on the graphics queue as 2-dword
packets with event index 0. The sampling indices 3 and 8-11 throw that
stream-out statistics sampling to memory is not implemented, before the
size and reserved-bit checks. Other indices, other sizes and the compute
queue still throw.
sceAgcDcbEventWrite ignores the address for every event type except 0x38
and 0x39, so a call with one of these event types and an address now
builds a packet that validates and writes nothing. This is recorded in
docs/dev/debt/libSceAgcDriver.md with the unmeasured hardware behaviour.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
On Windows every direct host import leaves the write watch, and a sampled
texture snapshot over it was compared with guest memory at every lookup:
its generation stays 0, so UnchangedSince never holds. ASTRO BOT
(PPSA21564) compared about 31 GB per 10 s at the title.
The lookup now keys such a snapshot by UntrackedHint, NewestStamp,
ForgetSerial and the recorder's newest write note, taken before the
snapshot is read or compared, as StorageTexture::compareUntracked does,
and skips the compare while the key is unchanged and no recorded work
writes the surface. The byte compare still decides after any mark.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Preserve instance and triangle order with one dynamic-reference shader pipeline. Require bounded references, complete export coverage, replay-safe mask control and resources; refuse unsupported side effects and feedback.
Co-Authored-By: Codex <[email protected]>
A draw with PA_SC_AA_CONFIG.MSAA_NUM_SAMPLES > 0 and
PA_SC_MODE_CNTL_0.MSAA_ENABLE clear threw. On GFX10 and later the bit
is what makes the rasterizer use the programmed sample locations; with
it clear the draw now keeps the target's sample count with every sample
at the pixel center. Points, lines, a depth target and
alpha-to-coverage still throw.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
A write-back stored on the GPU over memory outside the write watch left its
units without saved guest bytes (only the CPU path saved them), so the next
store of results landing there threw (#5711), and every refresh re-uploaded
the image. The stored ranges are now copied from the retile scratch into a
host-visible buffer behind the store and become the saved bytes when the
batch completes; a store or refresh that needs them first syncs that batch.
Units without a write generation pending when their range leaves the watch
save their bytes there too.
The second-store fixture waits for the GPU before its surface is freed on
every return, as #5790 does for the other cases.
An s_swappc_b64 whose target pair comes from an s_buffer_load of a buffer
whose descriptor is loaded from user data now calls the targets that buffer
holds: at dispatch the driver reads the buffer, links one copy of each
distinct callee after the caller and rewrites the call into a compare chain
that s_call_b64s the matching copy. A target that matches no copy, and any
other computed call, records an UnlinkedCall fault that the driver reports,
instead of failing the shader at compile time.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Since registered shaders are prepared in the background, a draw whose shader
was registered just before could wait seconds for its preparation inside the
queue worker. Under CPU load Goat Simulator 3's first submissions took ~3.7 s;
the title treated the GPU as hung, stopped submitting, and its 10 s garbage
collection timeout crashed it on every launch. Driver::Submit now waits for
the preparations queued before it, on the submitting thread, before the
commands reach the GPU.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Materialize runtime-indexed image and sampler records into descriptor
tables while keeping descriptor selection in the shader. Report invalid
active entries through the existing deferred fault buffer.
Bind fragment tables in the fragment set when pipeline libraries split it,
and reserve a physical descriptor for empty tables. Reject unsupported
sampler, border, cube and anisotropic pairings per entry. Keep one column
per heap access shape, one T# shared by several image operations included
(milescoviello's #5550 case), and narrow it to the union of its keys'
domains when every key has one (SleglJan's key-domain changes). Plan
columns read at (key << n) & mask over their whole domain (tibzejoker's
fix). Read records in runs through SleglJan's bulk reader, and reject
entries whose surface has no mapped byte, as Tamalero proposed. Store
table columns in disk plans; update the runtime ABI and disk format. Bound
table-sized entries in the resource cache (65,536 table elements) and the
dispatch cache (256 MiB of captured words), evicting LRU.
PA_SC_AA_SAMPLE_LOCS_PIXEL_* patterns that differ between the four pixels
of the guest's 2x2 grid threw. Pass them through VK_EXT_sample_locations
as a 2x2 sample location grid on devices whose maxSampleLocationGridSize
for the sample count allows it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A T# reading a depth surface's planes as a 2D array whose BASE_ARRAY is past slice 0 views the plane
copy from that slice (the copy holds slices 0 to LAST_ARRAY), instead of being refused. A 2D binding
of such a plane array reads its base slice through a one-slice view. Resident Evil Village
(PPSA01556: a D32 array read as R32F from slice 1) and Diablo II: Resurrected (PPSA03912: a D16 array
read as R16_UINT from slice 1) stopped on the refusal.
Rebased onto main from EagleBearerYS's adaptation to the current DepthPlaneCopy.
Co-Authored-By: EagleBearerYS <[email protected]>
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
PA_SC_MODE_CNTL_1 bit 16 (PS_ITER_SAMPLE) was rejected with the other scan
control bits. On a multisampled draw it now enables Vulkan sample shading with
a minimum rate of 1.0, and the draw throws when the device lacks
sampleRateShading. On a single-sample draw the bit has no effect and is
dropped. The flag is part of the pipeline, pipeline library and draw register
keys.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>