libkernel did not export sceKernelMapNamedFlexibleMemoryInternal, which
the libc bundled with SDK 9 titles imports. It now forwards to
sceKernelMapNamedFlexibleMemory: the mapping counts against the flexible
budget, gets the range name and is released by sceKernelMunmap. Older
libc builds call the public function at the same sites with the same
arguments and result handling.
The known callers pass flag 0x8000, whose meaning is unknown. It is
still rejected as an unsupported mapping flag and is recorded in
TechnicalDebt.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
sceKernelCancelSema was a throwing stub. It now releases every thread
blocked in sceKernelWaitSema with SCE_KERNEL_ERROR_ECANCELED without
consuming tokens, sets the count to setCount (the initial count when
setCount is negative) and reports how many threads were waiting. A
setCount above the maximum returns SCE_KERNEL_ERROR_EINVAL and changes
nothing.
Waiters are counted separately from waiterCount, which is only
decremented when a waiter leaves, so two cancels in a row do not report
the same thread twice.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
CLOCK_THREAD_CPUTIME_ID (14) and CLOCK_PROCESS_CPUTIME_ID (15) threw
"unsupported clock_id" on Windows while the Linux branch already maps
them to the native clocks. clock_gettime now returns the user + kernel
time from GetThreadTimes / GetProcessTimes, and clock_getres reports the
clock interrupt period from GetSystemTimeAdjustment, which is the step
those counters actually advance by.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Returns 1 when the address lies in an executable PT_LOAD segment of the
given dl_phdr_info, following FreeBSD lib/libc/gen/elf_utils.c (9.x and
11.x branches). The stub parameters become (dl_phdr_info*, void*) to
match the FreeBSD declaration; a null dl_phdr_info throws.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
sceKernelGetEventId, sceKernelGetEventFilter, sceKernelGetEventFflags,
sceKernelGetEventData and sceKernelGetEventUserData return the matching
field of the KernelEvent filled by sceKernelWaitEqueue and throw on a
null event. sceKernelGetEventError still throws NotImplemented.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A pixel wave starts with EXEC holding its covered pixels. The other lanes of
a partly covered quad run as helpers outside EXEC until the shader asks for
whole quads with s_wqm. Pixel shaders started with every invocation in EXEC,
Vulkan's helper invocations included. Those take part in subgroup
operations, so they counted in ballots (v_mbcnt, s_bcnt1 of EXEC,
v_readfirstlane), and a wave's single ds_append or atomic could be performed
by one of them: an atomic in a helper invocation does nothing and returns an
undefined value.
The entry prologue now starts a pixel shader's EXEC as !gl_HelperInvocation,
through a new StageInputKind::HelperInvocation builtin input. s_wqm still
adds the helpers of every quad with a covered pixel, so derivative code keeps
them.
The agc_driver_pixel_helper_lanes execution test draws triangles that leave
partly covered quads across the target with a pixel shader that stores each
covered pixel's v_mbcnt rank in EXEC, the s_bcnt1 count of EXEC and the
v_readfirstlane of a pixel id. Every wave's covered pixels must be lanes
0..n-1 of an n-lane EXEC whose first lane is one of them, in wave64 and
wave32. It skips on a subgroup narrower than 32, such as lavapipe's.
and throws for any non-zero word after it. Its layout matches shadPS4's
ServiceThreadParams instead: an unknown first word (16), a set-priority flag
and a priority (256..767), a set-affinity flag and a 64-bit CPU mask at
offset 16. PPSA21564 passes 16, 1, 0x100, 1 and 0x1FFF, so it stops at
startup on main.
sceVideoOutOpen now validates each field and reads the mask only when its
flag is set, so a 16-byte param with both flags clear still works. The
priority and affinity are not applied, since the present and vblank threads
are host threads; this and the unknown first word are listed in the
technical debt.
scePngEncQueryMemorySize, scePngEncCreate, scePngEncEncode and
scePngEncDelete encode R8G8B8A8 and B8G8R8A8 images with a pitch into
RGB or RGBA PNGs using the shared encoder in core/Decoder/Png.
Decoder::Png::Encode takes optional compression level and filter
options so the encode parameters are honoured.
Co-Authored-By: Claude <[email protected]>
s_movrels reads SGPR[src + M0] and s_movreld writes SGPR[dst + M0].
The 64-bit forms align the offset down to even (M0 & ~1), and
s_movrelsd_2_b32 takes the source offset from M0[9:0] and the
destination offset from M0[25:16], as measured on hardware. They use
the same select-over-registers lowering as the vector forms, over the
106 SGPRs. The embedded vertex-fetch scan forgets every tracked SGPR on
a relative write.
Co-Authored-By: Claude <[email protected]>
The decoder threw for these SOP1 opcodes. The 64-bit find-first-zero and
signed leading-bit counts reuse the existing 64-bit helpers with a flag;
s_quadmask_b32 is the 32-bit half of s_quadmask_b64. s_bcnt0 and s_quadmask
set SCC to result != 0; the find and leading-bit forms leave it.
Co-Authored-By: Claude <[email protected]>
The WriteLane IR takes {value, lane, previous}, as the translation and the
read-lane eliminator use it, but the SPIR-V emitter compared the lane id with
the previous value and selected between the lane index and the value. Every
v_writelane therefore wrote its value to all lanes (or the lane index to the
lane whose old value happened to equal its id).
Co-Authored-By: Claude <[email protected]>
All six exports are implemented: MP3 and AAC (ADTS or raw blocks) are
decoded with the bundled FFmpeg and ATRAC9 with LibAtrac9, one unit per
call, into interleaved S16 or float PCM, with the libSceAudiodec
validation and error codes. libSceAudiodec.native is built from the same
sources.
Co-Authored-By: Claude <[email protected]>
The parser descends recursively into every array and object without a
limit, so deeply nested input exhausts the stack and crashes the
process: 50000 levels on an 8 MB main thread and 5000 levels (10 KB of
brackets) on a 256 KB thread. sce::Json::Parser::parse now returns
JsonErrorParse when a document opens more than 512 nested arrays or
objects, which bounds the recursion for any input.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01R5WJS4ZdQynAJesCZKH5hb
Both SMEM opcodes read a 64-bit counter into an SGPR pair. They now
lower to OpReadClockKHR: s_memtime with subgroup scope (the shader
clock) and s_memrealtime with device scope (the constant real-time
clock). The device enables VK_KHR_shader_clock when it has both clocks
and the backend refuses the opcodes with a clear reason otherwise.
Co-Authored-By: Claude <[email protected]>
The hardware reads the lane select modulo the wave size (S1[4:0] in wave32,
S1[5:0] in wave64), as ReadLaneEliminator already assumes with
selector % waveSize. On the single-subgroup path EmitReadLane passed the raw
select to OpGroupNonUniformShuffle, which is undefined for an id at or above
the subgroup size. It is now masked with WaveSize() - 1, like v_writelane_b32.
The two-lane wave64 path already wrapped.
ds_rsub(_rtn)_u32, ds_inc_u32, ds_dec_u32, ds_mskor(_rtn)_b32,
ds_cmpst(_rtn)_b32/f32, ds_add(_rtn)_f32, ds_min/max_rtn_f32,
ds_wrap_rtn_b32 and ds_nop threw in the decoder. The new ones run as a
compare-exchange loop over the old value, with the semantics measured on an
RDNA2 GPU.
ds_min_f32 and ds_max_f32 take one data operand on gfx10, but compared the
memory with a second register (the unused data1 field, usually v0) and
stored data0 when that compare held. They now keep the minimum/maximum of
memory and data like the hardware: a NaN loses to a number, -0 < +0. Both
IR ops return the old value, so the _rtn forms share them.
Co-Authored-By: Claude <[email protected]>
v_ldexp_f16, v_frexp_mant_f16, v_frexp_exp_i16_f16, v_cvt_norm_i16/u16_f16,
v_cvt_pknorm_i16/u16_f16, v_cmp_class_f16, v_cmpx_class_f16,
v_sat_pk_u8_i16 and v_mul/mac_legacy_f32 threw in the decoder. The
behaviour was measured on an RDNA2 GPU: ldexp takes the exponent as an i16,
the norm conversions round to nearest even (done in integers, as x * 32767
does not fit f32 exactly), and a legacy multiply with a zero operand gives
+0 even for an infinite or NaN other operand. v_mac_legacy_f32 adds the
rounded product, like v_mac_f32.
Co-Authored-By: Claude <[email protected]>
SPIR-V float ops without NoContraction let the driver fuse or split them:
RADV contracted a guest v_mul_f32 + v_add_f32 into one fma, which made the
f32 division macro one ulp off. f32 add, sub, mul and fma now carry
NoContraction.
v_mad_f32, v_mac_f32, v_madmk_f32 and v_madak_f32 round the product before
the add, unlike their v_fma*/v_fmac* counterparts, but all of them were
translated to FPFma32. They now use a new FPMad32, emitted as a separate
NoContraction multiply and add.
Co-Authored-By: Claude <[email protected]>
f32 to f16 conversions (every f16 VALU result, v_cvt_f16_f32, f16 image
stores) used GLSL packHalf2x16, whose rounding is implementation-defined.
RADV truncates, so f16 results were off by one ulp and overflowed to
65504 instead of infinity. The conversion is now done with integer
operations: round to nearest even, subnormals, overflow to infinity and
quiet NaNs, as RDNA does. v_cvt_pkrtz keeps its own truncating op.
Co-Authored-By: Claude <[email protected]>