A title that never writes SPI_PS_INPUT_CNTL_0 relies on its clear-state
value 0, but the register was absent from the initial context, so every
draw of a pixel shader with interpolants was rejected with "missing
register at DWORD 0x191". All 32 SPI_PS_INPUT_CNTL registers now start at
0, as in the GFX10 clear state, both initially and after CLEAR_STATE.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
v_fma_f16, v_fmac_f16, v_fmamk_f16, v_fmaak_f16, v_pk_fma_f16 and
v_pk_fmac_f16 rounded an f32 fused multiply-add to f16, rounding twice.
The product of two f16 values is exact in f32, so the sum is now rounded
to odd in f32 with an exact error term and then rounded to nearest even
in f16, which rounds the exact result once.
computePostDominators iterates its sets to a fixed point, visiting the
blocks in id order. Post-dominance flows from a block's successors back to
it, and successors mostly have higher ids, so each pass moved the sets back
by about one block: a long program needed about as many passes as it has
blocks, each costing O(blocks^2). recomputeAnalyses runs it after every
split of splitSharedMergeBlocks, up to four times per block.
Visit the blocks in post-order of the CFG (successors first), then any the
entry does not reach. The sets start from every block and only shrink, so
the iteration still converges to the same greatest fixed point, now in a
few passes.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
CB_COLOR_ATTRIB3.RESOURCE_TYPE 0 is a 1D surface (AddrResourceType
ADDR_RSRC_TEX_1D in addrlib). On GFX10, addrlib allows a 1D surface the
linear and render swizzle modes (Gfx10Rsrc1dSwModeMask) and picks its
swizzle pattern the same way as for a 2D surface (GetSwizzlePatternInfo
only tells 3D apart). So a 1D color target one row high is laid out
exactly like a 2D target one row tall, and is decoded as one.
A 1D target with a standard swizzle mode is rejected as invalid; one
with more than one row is not modeled and is rejected.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
With f32 denormals flushed, every f32 multiply and fma checks whether the
exact product is below 2^-126 (#1850): two exponent extracts, a 32-bit
significand multiply-high and a chain of compares and selects. When a
factor is a literal or inline constant, its exponent settles the check
during translation:
- a factor that is zero (after the input flush), infinite, NaN or at least
1 in magnitude never gives a tiny product, so the check is not emitted;
- a power-of-two factor never carries out of the significand product, so
the multiply-high is not emitted.
Constant sources are folded with their abs, neg and denormal flush, so the
factor reaches the check as a constant.
With f32 denormals flushed, every f32 result is flushed when it is
written and every f32 source when it is read, so a source computed by an
earlier flushing op is flushed twice. A flush returns any value that is
not a denormal unchanged, and the driver can't tell that the first flush
already removed them.
DenormalFlushEliminator replaces a flush whose source can't be a
denormal with the source: a flush, a normal or zero constant, a sign
change, absolute value, clamp or bit cast of such a value, an integer or
f16 converted to f32, and a select or phi of such values.
sceHttp2GetMemoryPoolStats, sceSslGetMemoryPoolStats and
sceNetGetMemoryPoolStats threw. PPSA16064 (Minecraft Dungeons II,
Unreal Engine) queries all three while its HTTP module starts, and
aborted there.
Each library now records the pool size given at sceHttp2Init,
sceSslInit or sceNetPoolCreate and reports it with a peak and current
use of 0: the offline Http2 and Ssl models and the host-socket Net
library allocate nothing from these pools. The layouts follow the PS4
SDK's *MemoryPoolStats structures. Net returns EBADF for an unknown
pool and EINVAL for a null output, like its other pool calls; Http2 and
Ssl throw for both, as their error codes are unknown. Terminating a
context or destroying a pool forgets its size.
sceHttp2SetResolveRetry, which the title calls next, accepts and
ignores its value like the other Http2 settings. The four Http2
WebSocket exports the title imports are added as unimplemented.
guest_http2, guest_ssl and guest_sce_net check the reported sizes;
guest_sce_net also checks the null-output and unknown-pool errors.
A program's entry EXEC is the ballot of !gl_HelperInvocation in a pixel program and the ballot of true in vertex, local and tessellation programs (emitEntryPrologue). The half-wave reduction matcher only accepted the pixel form, so a wave64 vertex program that scans keys selected under its EXEC and reads lane 63 threw that the lane is outside the 32-lane host subgroup.
EntryLaneWalk now also accepts a ballot of true as within the entry EXEC for those stages. Every invocation is live at their entry, and a later ballot of true holds only invocations that are still active. Pixel programs keep the !gl_HelperInvocation form, because a ballot of true there includes helper invocations. Compute and mesh programs keep their own form too, because their entry EXEC can bound the local invocation index.
A draw's guest buffer region inside a host import at an offset off
minStorageBufferOffsetAlignment was copied per build (a new buffer, an
input snapshot, a vkCmdCopyBuffer that ends the open render pass), and
DirectRegions refused such builds as templates.
Descriptor already binds any DWORD-aligned view from the aligned offset
below it and passes the remainder through the shader's memory offset
slot. A draw build that is not address-based and whose every guest buffer
element has such a slot (a push constant byte, or a shader data byte
inside its data buffer) now binds a region whose offset in its import is
DWORD aligned in place, like an aligned one: its read-only views are
snapshotted per draw by PrepareDrawBindings at address - adjustment, the
import serial keys the template, and Revalidate proves it per use.
Dispatches keep the copy (they read in-place inputs at execution, not at
record).
agc_driver_recorder_tests misalignedRegionTests: a misaligned read-only
draw region is read in place, the build is reusable, the push constant
carries the adjustment, and the per-draw snapshot starts at the aligned
offset below the view.
CachedPipeline keeps at most 256 pipelines. A level with a larger working
set thrashes the LRU: every miss creates a new VkPipeline (modules,
layout, render pass and a driver compile from the pipeline cache). The
bound is now 1024. A cached pipeline is a pure function of its key, so
the bound changes only memory and time.
The half-wave reduction read (v_readlane_b32 of lane 31 or 63 after a DPP row scan) is exact on a narrower host subgroup only when the scan's keys are the identity outside the entry EXEC. EntryLaneWalk::ZeroBit now also proves that through a constant false, a SelectU1 whose two values both prove it, and a bool Phi whose inputs all do. A mask written inside a divergent branch reaches the key select in that form, so such a scan threw that lane 63 is outside the 32-lane host subgroup.
A draw with DB_RENDER_CONTROL.RESUMMARIZE_ENABLE recomputes the HTILE summary of the bound depth surface from its depth values. HTILE is not modeled, so such a draw with depth and stencil tests off and no color writes changes no modeled state. It now passes the maintenance check and draws nothing, instead of throwing. Resummarize draws with depth, stencil or color work, and copy and decompress draws, still throw.
ctest loads the libraries from libs/unpatched, so an import that nid_patcher
renames out of another library's exports only shows when a title loads the
patched prx. patched_libraries loads each patched .prx with LoadLibraryEx on
Windows and dlopen(RTLD_NOW) on Linux, and depends on the libs target so the
patched files are current.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The unified and service entitlement info list requests and polls threw.
They now return SCE_NP_ERROR_SIGNED_OUT, like the consume requests in
the same library. Their signatures are unknown, so they stay declared
without parameters.
PPSA15657 calls the unified request during start-up and continues past
the error.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_0134RWCyiyydJBbfKz8g9Bwe
Sackboy: A Big Adventure (PPSA01289) imports nine functions that no library
exports, so eager binding fails before it starts.
- libSceVoiceChat: sceVoiceChatRequestLeaveVoiceChatGroup and
sceVoiceChatRequestDeleteVoiceChatGroup, offline requests like the other
sceVoiceChatRequest* calls
- libSceNpSessionSignaling: sceNpSessionSignalingGetConnectionFromPeerAddress,
a throwing stub; the signature is unknown
- libSceCdlgG2P, a new library: the six sceG2PDialog* functions, throwing
stubs declared without parameters
TechnicalDebt records the assumed and unknown signatures.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The param is void*, as RommPS declares it. The test also passes a null and an empty URI and a param that must stay untouched, and compares against 0x8002002D itself. The debt entries now say the error is returned for any arguments and that the param layout and the console's argument checks are unknown.
PPSA01289 (Sackboy: A Big Adventure) calls sceAudioOut2MasteringTerm when it
replaces its world, which threw. Like Init and SetParam it has no effect, as
there is no mastering stage. The title creates its next world's audio device
before it destroys the previous one, so Init runs twice before Term runs
twice; whether the console reports an error for either is unknown, so both
return 0 and the case is recorded in TechnicalDebt.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
sceSystemServiceLaunchWebBrowser fails with the kernel's EOPNOTSUPP: there is no web browser to open. RommPS PPSA76677 stops on main at this import and shows a QR code instead when the browser does not open.
sceAmprCommandBufferClearBuffer detaches a command buffer's memory and
returns it so the caller can free it. It returned 0. PPSA01289 (Sackboy: A
Big Adventure) frees the result after every streaming read, so each read
leaked its 16 KiB command buffer until the allocator ran out of memory
during the first world load.
Co-Authored-By: Claude Opus 5.5 <[email protected]>