The write-back padding test gains an unpadded surface, a padded one and
one that spans two slabs, writes each of them back twice and checks the
stored texels and the untouched bytes after each write-back. The storage
refresh, write-back padding and single-pass tests run as
agc_storage_write_back.
writeBackWindows retiled every window into a device scratch buffer and
then copied the kept bytes from the scratch into the unit-shadow slabs,
so each stored byte was written twice.
A window now retiles straight into its slabs, one dispatch per slab
piece, when its kept range is its whole tiled range, every piece goes to
a slab that needs no seed, the pieces are tile-block and 4-byte aligned,
and it is not a tail, thick or saved slice. The bytes no element covers
are copied into the slab from their current source before the retile,
or left alone when the slab already holds them. Every other window keeps
the scratch path, and the scratch is not allocated when no window needs it.
readDccKeys publishes the shadowed units over the keys and then waited for every recorded batch. The publish notes its copies as pending writes, so waiting through the keys' newest writer is enough, and nothing needs a wait when neither the publish nor another recorded write covers them (a stale unit's slab is dropped, not copied).
A direct mesh draw with fewer indices than its input primitive threw "mesh draw
contains no complete primitive" (about 1800 skipped draws per 10 s in PPSA08427's
hub, each paying an exception). The hardware assembles no primitive from it, as
Vulkan does for a non-mesh draw that short, so it is now an empty draw. A mesh
pipeline grouping zero primitives still throws, with its own message.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Uzy15wqYTt6iWyxYXEzUWo
In a payload process on a PS5 (firmware 12.70), I386_GET_FSBASE (7) and
I386_GET_GSBASE (9) wrote 4 bytes, the low 32 bits of the FS and GS
bases, and failed with EFAULT for a null argument; both threw here. On
Linux x86-64 hosts they now do the same.
The nine operation numbers tried that FreeBSD 11's amd64 sysarch has no
case for (2, 5, 6, 12, 127, 133, 134, 1000 and -1), each with a null
argument, failed with EINVAL there, as its default case does, and threw
here. Every such number now returns EINVAL on every host.
Threads made with pthread_create and scePthreadCreate started with their
creator's GS base there; the test now checks that a guest thread does so
on Linux. The sysarch debt entry records these measurements and what
AMD64_GET_XFPUSTATE and I386_GET_XFPUSTATE returned there; both still
throw here.
Locking, trylocking, unlocking a destroyed mutex and signalling, broadcasting,
waiting on or destroying a destroyed condition variable threw a C++ exception
into the guest. FreeBSD 11.4 libthr returns EINVAL for all of them (thr_mutex.c
check_and_init_mutex and mutex_unlock_common compare against THR_MUTEX_DESTROYED,
thr_cond.c CHECK_AND_INIT_COND and _pthread_cond_destroy against
THR_COND_DESTROYED). The condition wait path already reported EINVAL for a
destroyed mutex.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
reachingWriter followed only fall-through and direct branches, so a V#
load on a path that reaches the loop through an s_setpc_b64 jump the
control flow analysis resolves was not seen, and another load could be
taken as the only writer. The walk now follows those jumps. It also
fails at s_call_b64 targets, whose callers it does not follow, instead
of walking from a function entry into the code above it.
Co-Authored-By: Claude <[email protected]>
The 30 ms limit gated all controller output, so a rumble pulse shorter
than the interval could be lost and a stop could wait up to 30 ms.
Rumble goes out on every output change again, as on main; SDL already
skips repeated values and merges consecutive rumble reports. Only the
light bar is paced: a changed colour is sent at most every 30 ms, always
the latest one, and a colour SDL refuses is retried after the interval.
The trigger effect is cached only when SDL_GameControllerSendEffect
succeeds, so a refused effect is sent again on the next update as it was
before. LightBarPacer and TriggerEffectCache hold these decisions;
pad_output_pacing covers changes, retries, a new controller and a light
bar animated every frame at 120 Hz.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
With APS5_DUMP_SHADERS set, PrepareShaderWithDiagnostics wrote a request
whose preparation failed under the same shader_<address>.req name that
dispatch and draw captures use. A preparation request has no captured
resources: the registration-time one carries placeholder (zero) user
data and only the code and header memory. Replaying such a file as a
dispatch capture follows the null user-data pointer into the SRT and
fails in SrtWalker, which looks like a walker bug but is not one.
dumpRequest also de-duplicated by address, so once a preparation
failure had been dumped, a later dispatch dump of the same shader was
silently dropped and the real capture was lost.
Preparation-failure dumps are now written as shader_<address>.prepare.req,
and dumpRequest de-duplicates by file name, so the later dispatch dump
of the same address is still written. agc_shader_replay's usage text
says to replay .prepare.req files with --prepare.
The FailureCapture test expects the .prepare.req name, no plain .req
from a preparation failure, and a subsequent dispatch dump of the same
address to be written with the serialized request.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
SPIR-V specialization emitted a new OpConstant for every folded result.
A folded value now reuses the id of an existing constant of the same
type and value for the operands the specialization decodes
(VisitInputs); consumers it does not decode, such as subgroup and
extended instructions, keep their own constant definitions, and the
unused-constant removal keeps those definitions while anything names
them. An OpBitcast to its operand's type or back to the type before a
previous bitcast becomes a copy. A compute program with one formatted
load shrinks from 10730 to 1117 words, so the formatted-load sharing
check compares the words two more loads add with the words the first
one added instead of with the module size.
IEqual32 and INotEqual32 against a constant fold when the other
operand has a value set of at most 64 values (built through shifts,
bitfield extracts, and/or/xor/mul/umin with a constant, add and
select) that excludes the constant or holds only it, or when a known
bit of the operand contradicts the constant. Known bits come from
constants, shifts and bitfield extracts by constants, and/or/xor, add
(up to the first unknown bit), mul (trailing zeros), umin, select, phi
and lane reads. The value set of x & mask leaves out the known bits of
x. ULessThan32 against a constant folds from the known-bit and
value-set bounds.
A fold pass computes the known bits and value set of each compared
operand once, so a chain of compares against one operand does not
repeat the analysis, and a sum is not enumerated when its two operand
sets hold more than 65 values together, since without wraparound it
then has more than 64 values.
All folds are identities of the operand's possible values; out-of-range
M0 handling of the relative indexing lowerings is unchanged. With
M0 = 4i + k, three of every four entries of an s_movrels/s_movreld
compare chain fold away.