An implicit-LOD or gradient sample with a texel offset through an
unnormalized S# was refused at bind time with "unnormalized guest sampler
is used by an implicit-LOD sample". PPSA01317 aborts on boot on such a
pixel image_sample_o. The base-level path already samples these through
OpImageSampleExplicitLod with LOD 0, which Vulkan allows for unnormalized
samplers, but it dropped the offset. It now adds the offset to the
coordinates in that branch, as the explicit-LOD offset fold does, so a
sampler whose uses also include offsets takes the base-level path. A
normalized S# keeps the offset operand.
AI-assisted: yes
On Linux the kernel maps each PT_LOAD from the start of its first page.
When a segment begins inside the page that holds the end of the previous
segment's zero-filled memory, that page is mapped again from the file, and
the bss tail reads whatever bytes precede the segment in the file. Nuvio
Max'd 0.5.27 (PPSA99288) keeps a mutex there and crashes at launch.
A segment whose page would read wrong bytes is now appended to the output
with that page prefix rebuilt from the segments below it. Outputs whose
pages already read right are unchanged.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The flattened SRT, the BDA page table and the image table map are filled
by the host and only loaded by the shader, but they were declared as
writable storage buffers. A program that also stores through device
addresses then gives the driver no way to know those loads are not
aliased by its stores, so every descriptor read stays a separate load.
Crimson Desert's largest compute program reads the flattened SRT 12,362
times; with the decoration NVIDIA 595.99 creates its pipeline in 90 s
with a 4.3 GiB peak, against 200 s and 10.6 GiB.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A scissor whose top-left corner lies past its bottom-right corner passes
no pixels; RADV writes such a viewport scissor whenever a viewport lies
outside the application's scissor, and radeonsi encodes its empty GFX12
scissor that way. PSSwanStation (PPSA99248) draws through one and
stopped on the throw.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
MXGP 26 (PPSA30839) opens TCP sockets with libkernel's socket() and
later closes them with sceNetSocketClose. libSceNet only looked in its
own socket table, so every one of those closes failed with
SCE_NET_ERROR_EBADF and the host socket stayed open. On the console both
calls work on the same kernel sockets.
A descriptor libSceNet does not own but libkernel has open as a socket
is now closed through libkernel's close(). Anything else still fails
with EBADF. The fallback runs after g_mutex is released, because
libkernel's close() first asks libSceNet's socket closer, which takes it.
guest_sce_net closes a libkernel TCP socket with sceNetSocketClose,
checks that libkernel no longer has it open, and checks that a second
close fails with EBADF.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Dusklight (PPSA99305) aborts on main as soon as its Select disc image
item is chosen: SDL's file dialog probes "zenity --version" through
posix_spawnp, and posix_spawnp throws "process creation not implemented".
FreeBSD 11.4's posix_spawn returns the error of the child's exec, and
an exec of a program that is in no directory of PATH (_PATH_DEFPATH
when PATH is unset) fails with ENOENT. Both calls now return ENOENT
without writing the process ID when the program is not in the guest
file system, and keep throwing when it is. SDL then reports the file
dialog as unsupported and the title stays on its menu.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Link's Awakening for PS5 (PPSA99670) imports both and does not load
without them. They wrap the host directory stream that opendir
already holds, under the stream's lock.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
FreeBSD's freeifaddrs is a plain free of the list, and Doom 3 BFG
(PPSA99313) releases the list with free. The list came from host malloc,
so the guest free stopped on an unregistered allocation; it now comes
from the application heap, and freeifaddrs returns it there.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A 64-thread compute kernel (23 dwords) stores pattern[i % 4], the pattern
in s4..s7, to dword i of a 4-byte-stride buffer for every i below
min(launched threads, s8, num_records), with the group id in s9.
PPSA01317 fast-clears its render-target DCC keys with it every frame. As a
plain dispatch its writes had no known value, so every key read of those
targets waited for the GPU under the GPU mutex.
The dispatch still runs as before. When it stores one repeated key code,
its keys are noted in the key-store memo right after the dispatch is
recorded, as a buffer fill of keys already is; the memo answers only while
the dispatch's own write note is the newest over the range, so any later
writer still makes the read wait. The key codes come from KeysFillMemo, as
for the memory-value fill kernel.
AI-assisted: yes
A dynamic-mip storage image reserved four mip slots, so a compute shader
whose T# spans more levels failed with "runtime storage image mip capacity
exceeded". PPSA01317 hits it on boot with a 512x512 surface of ten levels
and aborts. An RDNA T# addresses at most sixteen levels (4-bit BASE_LEVEL
and LAST_LEVEL), so a dynamic-mip image now reserves sixteen slots, and a
typed storage heap holds 64 elements so four such images still share one
class. Heap arrays keep their compact length. The runtime ABI goes to 14,
so existing shader caches are invalidated.
AI-assisted: yes
Prospero Themes (PPSA90210) imports nmount (3YnXspQNyw8) from libkernel
and fails to load without it:
"./app.elf: symbol lookup error: ./app.elf: undefined symbol: 3YnXspQNyw8".
Mounting file systems is not supported, so it throws if called, like
execvp does for executable replacement. The title opens its theme
library without calling it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Sovthwyu4H63RMbRVha2Sy
PSFlyCast (PPSA99247) imports pthread_condattr_setpshared (3BpP850hBT4)
from libkernel and fails to load without it:
"./app.elf: symbol lookup error: ./app.elf: undefined symbol: 3BpP850hBT4".
The attribute stores PTHREAD_PROCESS_PRIVATE (0) or
PTHREAD_PROCESS_SHARED (1); a null or uninitialized attribute and any
other value return EINVAL without changing it, following FreeBSD 11
libthr thr_condattr.c and pthread_mutexattr_setpshared here. Sharing
across processes is not modeled, as for mutexes.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Sovthwyu4H63RMbRVha2Sy
A device that imports shared memory through host pointers, such as lavapipe, imports the unaligned range that way, and a host-pointer import has no lead.
A unit shadow published its units into the import's buffer at the guest offset from the import's
base, without the import's lead, so a sparse import that starts below its range (HostImport::lead)
got the units lead bytes before their place. The shadow keeps the lead with the import's base and
buffer, and the shadow verify reads the guest bytes at the same place.
agc_driver_sparse_dma_buf_import publishes a unit shadow of its unaligned import and checks the
unit's guest bytes and the bytes around it; without the lead it fails there.
A sparse import binds whole 64 KiB blocks, so a range whose memfd offset
is not a multiple of 64 KiB fell back to one UDMABUF_CREATE and, above
udmabuf's size limit, to copies. The sparse buffer now starts at the
block below the range: HostImport::lead holds that distance, the
import's device address points at the range itself, and every offset
into the import's buffer goes through HostImportOffset.
The [dispmove] line printed refused 0 next to a rebuild count that came mostly from PrepareDispatch dropping the hit. The line now reports the refusals at stage A and at record separately, each with its reasons.
EmitBdaAnchors declared the u64 type before checking for anchors, so every
program got a 64-bit integer type, and programs without the Int64 capability
failed SPIR-V validation. It now returns before declaring anything when the
program has no anchors. A compute program without BDA reads is checked to
declare no 64-bit integer type and no Int64 capability.
AI-assisted: yes
select(c, a, select(c, b, d)) is select(c, a, d), and
select(c, select(c, a, b), d) is select(c, a, d). The recompiler leaves
these behind when a register is written more than once under the same
lane mask and when the f32 NaN selection tests the same source twice,
and nothing folded them. The constant folder now takes the inner arm
the outer condition already decides, then folds a select whose arms
became equal.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Goosebumps Terror in Little Creek (PPSA27305) aborts in gameplay with
"unsupported color format 16 number type 0 component swap 2": it renders
into a COLOR_5_6_5 UNORM target. The target now renders into
R5G6B5_UNORM_PACK16. AMD keeps X in bits 0-4 and Z in bits 11-15, and
Mesa's ac_translate_colorswap programs SWAP_STD_REV for a surface with
red in bits 11-15, so with SWAP_STD_REV the exports are written as they
are and with SWAP_STD they are written with X and Z exchanged, as for
1_5_5_5. The alternate swaps and other number types keep throwing.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
With #6014 merged, the first draw of METAL GEAR SOLID: Peace Walker's
(PPSA18216) opening movie stops on "the depth target's sample count
differs from the rasterizer's" (mrfelek on #6196). The state he reported
is a 4x PA_SC_AA_CONFIG, MSAA_ENABLE clear, a one-sample 1440x810 depth
target and no color target; on main alone it throws earlier, on "a depth
target". Like the one-sample color targets of bb877791a, such
a depth target, with or without one-sample color targets, is now drawn
as a one-sample draw at the pixel center, before the multisampled-target
check and instead of the sample-0 path, which needs MSAA_ENABLE.
Points, lines, alpha-to-coverage, a sample-mask export and DB_EQAA Z
interpolation or overrasterization throw on this path, and so do
PS_ITER_SAMPLE and ANCILLARY or SAMPLE_COVERAGE pixel inputs when the
pixel program runs. A skipped pixel program is replaced by the null
program, which uses neither.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Prevent reached null conversion destinations from crashing sscanf_s and vsscanf_s. Return EOF before writes and retain earlier assignments. Add regression coverage through both guest ABI entry points.
AI-assisted: yes (OpenAI Codex). Windows WinLibs GCC 15.2 Release: production baseline crashes with the new regression; fixed shared libc passes guest_scan_count, guest_formatting, guest_wide_formatting and guest_strings (4/4). Conventions pass. Full all-target build was deliberately stopped after 83s with 3691 pending targets, not completed. No title or console run; constraint-handler invocation remains unimplemented as documented. No performance or coverage-percentage claim.
Adds tests for nine implemented libSceRudp functions that previously
lacked coverage:
- sceRudpActivate (returns 0 always)
- sceRudpEnableInternalIOThread (NOT_INITIALIZED before init, 0 after)
- sceRudpSetEventHandler (returns 0)
- sceRudpBind (NOT_INITIALIZED, INVALID_CONTEXT_ID, 0 on success)
- sceRudpSetOption (NOT_INITIALIZED, INVALID_CONTEXT_ID, 0 on success)
- sceRudpInitiate (NOT_INITIALIZED, INVALID_CONTEXT_ID, CONN_REFUSED)
- sceRudpGetContextStatus (NOT_INITIALIZED, INVALID_CONTEXT_ID, fills
status with 0, null status allowed)
- sceRudpWrite (NOT_INITIALIZED, INVALID_CONTEXT_ID, CONN_RESET)
- sceRudpRead (NOT_INITIALIZED, INVALID_CONTEXT_ID, CONN_RESET)
Each assertion mirrors the exact implementation in Export.cpp. Error
codes and return values are the constants hardcoded in the source.
No console measurement needed — these are pure offline behaviors.
AI-assisted: yes
A v_mul_f32 in a FLOAT_MODE that flushes f32 denormals emits the
nearest-even tininess check, the NaN result selection and then a
result flush. The check already turns every product that rounds below
2^-126 into a zero of its sign, so the flush can't change what it
keeps. DenormalFlushEliminator now proves that: a select arm guarded
by the tiny-product check of the same denormal-free factors, an arm a
select takes only when its own bits are NaN, and an and with a mask
that has no significand bits are denormal-free.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A guest path is resolved by appending its components to the host root or
to a mount alias directory through std::filesystem::path. On Windows a
component such as "C:" that came first in the appended part was parsed as
a root name, so operator/ replaced the host directory instead of
appending: "/savedata0/C:/Windows/win.ini" and "/app0/../C:/Windows/win.ini"
resolved to "C:\Windows\win.ini", and "/C:/x" lost the component and
resolved to "<root>\x". A colon is an ordinary character in a FreeBSD
file name, so those names belong under the mount.
Guest paths are now split into component names and joined to the host
directory as text. Explicit native drive paths are still passed through.
On NTFS a name containing ":" still opens an alternate data stream; the
libc debt list now records it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
MayEvaluate and the evaluator track the first-lane reads they are inside, so a read reached again through a loop-carried phi or a constant slot is not evaluable instead of recursing.