The guest is LP64, so vwarnx consumes a full 64-bit slot for %ld. On LLP64 hosts (Windows) the 123456789L argument is only 32 bits wide and leaves the upper half of that slot undefined, so the check saw garbage in the high bits.
v_fma_f16, v_fmac_f16, v_fmamk_f16, v_fmaak_f16 and v_fma_mix_f32 with
f16 sources left the NaN of an invalid operation to the driver, so
inf * 0 gave 0x7fff and 0x7fffffff on NVIDIA where the hardware gives
the default NaN 0xfe00 and 0xffc00000. An inf * 0 product, or a NaN
from sources that are not NaN, now gives the default NaN; NaN sources
are still left to the driver.
A storage image's write-back keeps the 64 KiB blocks written since its
layers were last in sync, since the memory may have been reused. A
depth plane's image is overwritten whole by every store, but it kept
the sync state of its creation or last reload. A plane bound behind an
HTILE fast clear never reloads, so once guest memory over it had been
written (another render target over the same memory), every later
store kept those blocks and the drawn depth never reached guest memory.
A store now marks the image as holding the whole plane, as a whole-image
copy does (StorageTexture::MarkWholeWritten, split out of CopyFrom).
agc_driver_depth_plane_buffer_memory gains the case: store a plane,
write its memory, clear its HTILE and draw, then fetch the plane. It
fails without the change (the fetch reads the guest write).
AI-assisted: yes
MinGW libstdc++ up to GCC 16 does not treat a reparse point as a link in
std::filesystem::remove_all, so a host tree that holds a symlink is walked
through the link and never returns. Add RemoveTree, which removes the tree
itself on Windows, and use it where save data, app content and the shader
disk cache removed host trees. The libstdc++ fix is in GCC 17 (88856ad855ae).
Queue the stream in the table of the 8 standard stream
slots of Dinkumware's ios.cpp: the first free slot or the one
that already holds the stream, with a reference count per slot,
and the destructor suppresses the destruction of a standard
stream while its slot still has open references.
The Linux executable sorts its PT_LOAD entries, but guest modules (*.guest.prx) kept them in the input table order. A module whose data segment comes before its text segment in the table was written with PT_LOAD entries out of address order, which the gABI forbids: glibc reserves the span from the first to the last entry, so with 0x2000, 0x1000, 0x4000 it reserved 0x2230 bytes instead of 0x3230 and mapped the text below the reservation. The PT_LOAD entries are now sorted in place, as for the executable.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Code analysis rejected R_X86_64_64, GLOB_DAT and JUMP_SLOT relocations whose symbol index is 0 (STN_UNDEF) with 'invalid relocation symbol', so the Windows and macOS conversions failed while Linux converted the same input. The pipeline already resolves such relocations to 0 plus the addend, as the gABI defines and as the relinker technical debt entry records for null symbol entries; only an all-zero entry at a nonzero index was accepted. Index 0 is now treated as an import slot like that entry.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A bundled libc.prx can export the ten allocator NIDs while forwarding
them to HLE, so adopting its exports for a title whose replacement
table is empty sends HLE allocations back into themselves. Keep the
default heap in that case, as before the guest SDK adoption.
A title can relocate a registered shader header, and the register, special and
semantic arrays it points at, into memory of its own and resolve the ABI with
that copy (Astro's Playroom, PPSA01325, #2914). SameHeader accepted such a copy
only while every pointer inside it stayed put, so a moved array left the
resolution throwing "refers to a replaced shader header".
Accept the copy when every array it names still holds the registered bytes: the
registered header then decodes what the copy describes, nothing is copied and
ShaderSnapshot stays immutable. A copy whose arrays differ or are unreadable
still throws.
Address review: check the msghdr, iovec array, iovec bases and name
are mapped before MessageLength or the receive loop touches them,
pairing the HostWrite guard with committed-range validation. Add
regression tests for forged iovec-array and output pointers.
recvmsg_nid_postfix wrote the msghdr, every iovec base and the sender
address with only null checks, unlike recv_nid_postfix and the
sceNetRecvfrom sender outputs which all gate on GuestArena::HostWrite.
Validate the message, each iovec base and the name buffer the same way
so a forged pointer fails with EFAULT instead of writing received bytes
to an arbitrary host address.
Add sceSysmoduleUnloadModuleInternalWithArg to match the existing
sceSysmoduleLoadModuleInternalWithArg export. Decrement the module load
count on valid internal IDs, check module existence in kModuleTable,
and set the return pointer when provided.
Add unit test coverage in GuestSysmodule for invalid values, unloaded
modules, successful argument unload, and unknown IDs. Update technical
debt documentation.
A guest buffer region that is copied rather than imported gets a buffer
with storage (and, when addressable, device-address) usage only. Host
imports, sparse imports and chunk imports carry VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
so a buffer view of imported guest memory can be read back with
vkCmdCopyBuffer, but not one of a copied region. agc_sparse_run_import_copied
does that readback, and the Khronos validation layer reports
VUID-vkCmdCopyBuffer-srcBuffer-00118 for it.
Copied regions now carry transfer-source usage too. The sparse buffer
hole tests seed the buffer pool with the usage a copied region asks for,
so their seed buffer gets transfer-source usage as well.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Off Windows, the GPU fill case now runs with host imports kept watched, so it
always checks the absorbed clear, and a new case runs it with imports left
unwatched, which must be refused. On Windows a settled import is watched again
when its settle is polled, possibly before the draw takes the fill, so an
unwatched fill may be either refused or drawn, and a drawn one is checked.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
When a fill of the metadata could not be taken because one of its ranges was
no longer watched, the check reached a watched range that the fill had
changed first and reported the write instead of the unwatched range.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A multisampled DCC color target imports its uniform DCC fast clear on
first use and then refuses any later change to its color, DCC or CMASK
memory. Titles built on the PS5 Mesa stack fast-clear such a target
every frame with two buffer fills, the CMASK to 0xcc (FMASK cleared,
color expanded) and the DCC to a uniform clear key, so the second
frame stopped on "writes to a resident multisampled DCC target or its
metadata are not implemented".
The fills of a resident DCC target's metadata are now noted. When a
fill covered the whole DCC range since the last use and the range holds
its key once pending writes land (LandedUniformMetadataByte, which
reads the bytes directly rather than through the resident read guard),
the next use clears every sample to that key's color, as the import
does, and takes the new DCC and CMASK generations. A CMASK written
since must have been filled whole too. Partial fills, other keys,
CMASK-only writes and any write to the color memory are still refused.
Fills of a DCC target's CMASK no longer go to the CMASK-only fast-clear
tracker, which refused the expanded code 0xcc.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
An indirect draw drained queue 0's draw pipeline on entry and recorded every
record on the worker, so titles that draw mostly through DRAW_INDIRECT,
DRAW_INDEX_INDIRECT and DRAW_INDEX_INDIRECT_MULTI got no overlap between the
worker's capture of one draw and the committer's recording of the previous.
The draw now drains only when its records or its count overlap a write still
queued on the pipeline. Records drawn inline drain first, so they stay in
order, and the last drawn record is queued like a direct draw, carrying its
write ranges. APS5_NO_PIPELINED_INDIRECT=1 restores the drain on every
indirect draw.
agc_driver_pipelined_indirect_draw holds the committer with a blocking item and
checks that two indirect draws queue behind it and draw what a direct draw
does, and that a draw whose record a queued label writes waits for it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>