Commit Graph
5577 Commits
Author SHA1 Message Date
DotDebianandClaude Opus 5.5 6a20036154 feat(libs): implement NpCppWebApi Common::String constructor, destructor and c_str
The constructor was a silent stub that left the guest object
uninitialised and c_str threw. The constructor now writes the 0x20-byte
object, c_str returns the buffer or an empty string, and the destructor
throws for a non-null buffer, whose release needs the LibContext
allocator.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-05 11:12:56 +02:00
Dean d0cf2a408c Merge pull request #624 from DotDebian/feat/audioout-get-last-output-time
feat(libSceAudioOut): implement sceAudioOutGetLastOutputTime
2026-10-05 22:05:30 +13:00
Dean ca6bd2f593 Merge pull request #623 from DotDebian/fix/freebsd-clock-ids
fix(libkernel): give CLOCK_VIRTUAL, CLOCK_PROF and CLOCK_SECOND their FreeBSD meaning
2026-10-05 22:04:48 +13:00
Dean 93fb226496 Merge pull request #621 from DotDebian/feat/font-get-pixel-resolution
feat(font): implement sceFontGetPixelResolution
2026-10-05 22:04:06 +13:00
Dean 3bf9ac5794 Merge pull request #620 from DotDebian/feat/libc-snwprintf-s
feat(libc): implement snwprintf_s
2026-10-05 22:03:24 +13:00
Adrià FranchandClaude f457d87bbd feat(shader): accept clamp on v_cube*_f32 and match their zero and subnormal results
Co-Authored-By: Claude <[email protected]>
2026-10-05 10:57:27 +02:00
Adrià FranchandClaude 7bb6c59e83 fix(shader): v_mullit_f32 legacy rules, v_cvt_pk_u8_f32 rounding and VOP3 neg/abs
Co-Authored-By: Claude <[email protected]>
2026-10-05 10:53:50 +02:00
Dean 8040d09ad0 Merge pull request #628 from oneandonlydean/perf/agc-query-entry-points-once
perf(agc): resolve the recorder's query and fold entry points once
2026-10-05 21:49:12 +13:00
Dean c760129beb Merge pull request #627 from oneandonlydean/perf/agc-large-label-stores
perf(agc): keep label stores larger than 64 bytes out of the label table
2026-10-05 21:48:28 +13:00
Dean 6df3301700 Merge pull request #503 from oneandonlydean/feat/agc-3d-thick-mip-tails
feat(agc): thick mip tails of mipmapped 3D textures
2026-10-05 21:46:40 +13:00
Dean 2cce4bde41 Merge pull request #469 from Pacuka/fix/agc-null-pixel-program
fix(agc): draw without a pixel program when SPI_SHADER_PGM_PS is unset
2026-10-05 21:36:35 +13:00
Dean 698c23d81e Merge pull request #528 from adriadam10/test/vop1-vop2-integer
fix(shader): v_cvt_rpi/flr_i32_f32 NaN and exact round-half-up, VOP1/VOP2 integer test
2026-10-05 21:35:53 +13:00
Dean e3e1dfae16 Merge pull request #526 from adriadam10/test/scalar-sop1
fix(shader): s_wqm SCC and s_andn{1,2}_wrexec destination, SOP1/SOPC/SOPK execution test
2026-10-05 21:35:11 +13:00
Dean 5ad0c99f98 Merge pull request #525 from adriadam10/test/scalar-alu
fix(shader): s_lshlN_add SCC and s_bfe_[iu]32 fields past bit 31
2026-10-05 21:34:30 +13:00
Dean 1e37ed456a Merge pull request #514 from adriadam10/fix/dpp16-movrels-pk-fmac
fix(shader): DPP16 operands of v_pk_fmac_f16 and the relative moves
2026-10-05 21:33:48 +13:00
Dean 6fd9739d9d Merge pull request #510 from adriadam10/feat/sdwa-vop2-integer-clamp
feat(shader): saturate VOP2 integer SDWA results on clamp
2026-10-05 21:33:38 +13:00
Dean 070ed19249 Merge pull request #509 from adriadam10/feat/sdwa-vop2-integer
feat(shader): accept every SDWA selector on VOP2 integer ops
2026-10-05 21:32:55 +13:00
Dean 17ef50b681 Merge pull request #504 from adriadam10/feat/vop3-opsel-16
fix(shader): VOP3 op_sel on v_alignbit/alignbyte_b32 and 16-bit max3/min3/med3
2026-10-05 21:32:13 +13:00
Dean Galvin 16f19c51ad feat(agc): thick mip tails of mipmapped 3D textures
3D textures in SW_4KB_S or SW_64KB_S whose smaller levels reach the mip
tail were refused ("3D texture mip tails are not implemented"). The
tail now follows addrlib's GFX10 thick layout
(Gfx10Lib::ComputeSurfaceInfoMacroTiled):

- a level enters the tail once its size, rounded up, fits the thick
  tail extent (the block with its height halved for 4 KiB blocks and
  its width halved for 64 KiB blocks) and at most GetMaxNumMipsInTail
  levels remain (5 for 4 KiB, 10 for 64 KiB);
- each slab starts with one tail block, then the other levels from the
  smallest to level 0;
- tail level i sits in slot maxMipsInTail - 1 - i, at the element offset
  addrlib derives from that slot's byte offset and the 256-byte thick
  micro block, at every depth slice.

The tests check element addresses of five volumes (4 KiB and 64 KiB
blocks, 1 to 16 bytes per element, odd sizes, a chain that starts in
the tail) against Mesa addrlib's Addr2ComputeSurfaceAddrFromCoord for
a Navi10 configuration.
2026-10-05 21:32:06 +13:00
Dean bbedad3b00 Merge pull request #500 from adriadam10/fix/f32-clamp-bits
fix(shader): clamp f32 results to +0 for NaN and -0
2026-10-05 21:31:31 +13:00
DotDebianandClaude Opus 5.5 84974a9b2a fix(shader): locate image LOD, mip and sample index by the instruction's dimension
The address operands of a MIMG instruction are laid out by its own DIM
field: the decoder counts them that way. The SPIR-V emitter located the
gradients, the LOD, the LOD clamp, the mip level and the sample index
after the coordinate count of the bound T# instead, so an array
instruction on a non-array texture took the slice as its LOD.

An instruction that addresses fewer coordinates than its image has is
refused instead of reading the next address component as a coordinate.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-05 10:29:48 +02:00
Dean Galvin 23d67b59a7 perf(agc): keep label stores larger than 64 bytes out of the label table
PPSA21564 clears each occlusion query slot with a 256-byte WRITE_DATA
before its begin dump, about 8,400 times per frame in one level. The
clear is larger than a deferred label, so it is recorded at once, and
Recorder::NoteLabel entered all 64 of its dwords in the pending-label
table: 64 map inserts, 64 batch dword entries and 64 group entries, then
64 lookups in CloseLabelGroup and 64 erases when the batch is reaped. A
replay of that pattern (21 clears per batch, 20 batches in flight) costs
1.6 us for the inserts, 0.7 us for the close and 1.3 us for the erases
per clear, about 31 ms of the graphics worker per frame there. The new
path costs 0.07 us per clear in the same replay.

The table serves WAIT_REG_MEM values and CPU pollers, which read 4 or 8
bytes. A store larger than 64 bytes (the bound the driver's own label
history already uses) now enters one range instead of its dwords:
- table entries inside the range are removed, as the store replaced
  them before: a lookup there finds no value and falls back to the
  pending-write path, where it used to find the store's value;
- the range leaves with its batch, like the dword entries;
- PendingLabelIn sees the range, and the write-evidence check, which
  syncs a capture read over any pending label dword, now also syncs
  over a pending range (Recorder::WideLabelIn).
The store is still a pending write of the open batch (the flush hook
syncs CPU readers), still starts the label flush deadline and is
recorded exactly as before. Stores of 64 bytes or less are unchanged.

Test: agc_driver_recorder_tests largeLabelTests (a 256-byte label enters
no dwords and removes the older entry under it but not one beside it,
its range, pending write and deadline, a later 4-byte label over it,
a 64-byte label entered in full, everything gone after the batch).
2026-10-05 21:28:34 +13:00
Dean Galvin 2b388e0b0e perf(agc): resolve the recorder's query and fold entry points once
Every occlusion counter dump the recorder handles on the GPU ends the
batch's occlusion query, copies the pending results, folds them with a
compute dispatch, then resets and begins a new query. Each of those
commands was resolved through vkGetDeviceProcAddr, a loader name lookup,
on every call: seven lookups per dump on the graphics worker, and a title
dumps the counter twice per occlusion query. The mesh argument and timing
paths resolved their bind, push, dispatch and reset per call too.

They join the entry points the recorder already resolves in its
constructor: vkCmdBeginQuery, vkCmdEndQuery, vkCmdResetQueryPool,
vkCmdCopyQueryPoolResults, vkCmdBindPipeline, vkCmdPushConstants and
vkCmdDispatch. The same functions are called with the same arguments;
APS5_NO_PROC_TABLE=1 still resolves every call.
2026-10-05 21:27:15 +13:00
Dean ceeab79cff Merge pull request #618 from oneandonlydean/fix/relinker-linux-host-libc-needed
fix(relinker): keep the host libc.prx needed on Linux when a title bundles its own
2026-10-05 21:26:07 +13:00
DotDebianandClaude Opus 5.5 63711450f4 feat(libSceAudioOut): implement sceAudioOutGetLastOutputTime
Report the process time at which sceAudioOutOutput or sceAudioOutOutputs
accepted the port's last block. A port that never output reports 0, and
waiting with a null pointer does not move the time.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-05 10:25:30 +02:00
Dean fbd6ccbc36 Merge pull request #611 from oneandonlydean/perf/recompiler-masked-select-elim
perf(recompiler): drop exec selects whose inactive lanes nobody reads
2026-10-05 21:25:25 +13:00
Dean d18fa1367c Merge pull request #612 from oneandonlydean/perf/recompiler-lds-constant-slots
perf(recompiler): index lane-strided per-invocation LDS by constant slots
2026-10-05 21:24:42 +13:00
DotDebianandClaude Opus 5.5 096bdb38c2 fix(libkernel): give CLOCK_VIRTUAL, CLOCK_PROF and CLOCK_SECOND their FreeBSD meaning
clock_gettime and clock_getres served three FreeBSD clock ids with the wrong
clock or not at all:

- CLOCK_VIRTUAL (1) was the monotonic clock on Windows and threw on Linux; it
  is the user CPU time of the process.
- CLOCK_PROF (2) threw on both hosts; it is the user plus system CPU time of
  the process.
- CLOCK_SECOND (13) returned the coarse realtime clock with nanoseconds and a
  sub-second resolution; it is the current second with tv_nsec 0 and a
  resolution of one second.

Behaviour follows FreeBSD 11 clock_gettime(2) and kern_clock_gettime /
kern_clock_getres in sys/kern/kern_time.c.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-05 10:24:22 +02:00
Dean cf716ff268 Merge pull request #586 from oneandonlydean/fix/recompiler-lds-array-bound
fix(recompiler): size per-invocation LDS arrays to the addresses they reach
2026-10-05 21:24:00 +13:00
Dean Galvin 604826c138 perf(agc): pin the queue workers to the performance cores on Linux
CpuTopology::Get and Pin did nothing off Windows, so on a hybrid CPU the
queue workers, the draw front end and the presenter ran wherever the
scheduler put them. On a Linux kernel that reports the same capacity for
every CPU, those threads spent part of each frame on the efficiency cores.

Get now reads the process affinity with sched_getaffinity and the core
classes from /sys/devices/cpu_core/cpus and /sys/devices/cpu_atom/cpus, and
Pin restricts the calling thread with pthread_setaffinity_np. A CPU is
hybrid only when both lists exist and are disjoint, so non-hybrid CPUs are
never pinned. On Linux the workers are pinned to the performance cores of
a hybrid CPU by default; APS5_NO_WORKER_AFFINITY=1 leaves them free.
Windows keeps the APS5_WORKER_AFFINITY=1 opt-in, and
APS5_WORKER_AFFINITY_MASK=<hex> still picks the cores on any platform.

PPSA21564 on a hybrid CPU, pinned against unpinned (2 runs each): title
46.7 to 49.0 fps, menu 45.4 to 47.7, intro level 37.2 to 41.3 (space) and
31.7 to 37.6 (ships). Hub descent 6.56 to 7.92 fps (3 runs each).
2026-10-05 21:23:34 +13:00
Dean c0e8c89e2e Merge pull request #505 from oneandonlydean/fix/agc-compacted-color-exports
fix(agc): route compacted color exports to the slots CB_SHADER_MASK enables
2026-10-05 21:23:18 +13:00
Dean ef88b5be00 Merge pull request #490 from oneandonlydean/fix/agc-views-past-max-mip
fix(agc): address texture views that start past the surface's last mip
2026-10-05 21:22:36 +13:00
DotDebianandClaude Opus 5.5 c0d293ff7b feat(font): implement sceFontGetPixelResolution
Report the sub-pixel resolution of the library's driver.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-05 10:05:31 +02:00
DotDebianandClaude Opus 5.5 9837c69f0d feat(agc): implement sceAgcDcbPrimeUtcl2 and its size query
The DCB variant threw "not implemented" while the ACB one wrote a
5-dword packet. Both now go through Agc::Command::WritePrimeUtcl2 and
the size query returns 20 bytes.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-05 10:05:28 +02:00
DotDebianandClaude Opus 5.5 992933b95c feat(libc): implement snwprintf_s
Format through the shared wide formatter, truncate to the buffer and
return the full length, as C11 K.3.9.1.3 specifies. A null buffer or
format, a zero or oversized n, %n and a null %s argument are
runtime-constraint violations that return a negative value.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-05 09:59:30 +02:00
Dean Galvin a3ec50aefa fix(agc): keep the guest's bytes in the padding a storage write-back stores
A GPU-direct storage write-back retiles the image's elements into an
uninitialised device scratch buffer and then copies whole ranges of it
into the import or the import's unit shadow. The retile writes only the
bytes elements occupy, so every other byte of the copied ranges was
stored from uninitialised scratch memory: the padding of the tile blocks
a surface covers only partly (its last block column and row), mip tail
blocks, the bytes between mips and the pitch padding of linear surfaces.
Another surface over the same memory, or the CPU, then read garbage
there instead of what the memory held. Both the block-window path and
the whole-layer path did this.

Before the retile, the bytes of the copied ranges that no element holds
are now copied into the scratch from where they are current (a fresh unit
shadow, else the import), so the write-back stores them unchanged. Whole
tile blocks every byte of which holds an element are left out
(CoveredMipBytes), so only partly covered blocks pay for the extra copy.

Tests: CoveredMipBytes against the XOR address equations of the four
64 KiB XOR modes at every element size; a device test that stores
cleared images over patterned memory (tiled with and without mip chains,
off a 64 KiB boundary, 4 KiB standard, linear; plain and watched memory)
and checks every byte that is not a texel kept its pattern.
2026-10-05 20:51:34 +13:00
Dean Galvin 7103f390cf fix(relinker): keep the host libc.prx needed on Linux when a title bundles its own
A title that ships sce_module/libc.prx makes addHost drop the host
libc.prx from the executable's dependencies. Every host prx needs it, but
their DT_RUNPATH is empty, so loading fails with "libc.prx: cannot open
shared object file".

Mirror the Windows rule from WindowsImportBuilder: when libSceLibcInternal.prx
is a host dependency and no host libc.prx remains, append libc.prx as the
last host dependency. The title's own imports still bind to the guest
modules first.

Refs #476
2026-10-05 20:36:29 +13:00
Dean e7bf72d503 Merge pull request #616 from adriadam10/feat/mimg-tfe-lwe
feat(shader): accept tfe and lwe on MIMG loads, stores and samples
2026-10-05 20:29:00 +13:00
Dean 05ed3e29dc Merge pull request #614 from nicolasabosch/fix/relinker-function-aliases
fix(relinker): allow function aliases with different sizes
2026-10-05 20:28:18 +13:00
Dean 56acdef2f5 Merge pull request #569 from adriadam10/feat/global-store-addtid
feat(shader): implement global_store_dword_addtid
2026-10-05 20:27:36 +13:00
Dean 033ac78439 Merge pull request #563 from adriadam10/feat/vop3-mad64-clamp
feat(shader): implement clamp on v_mad_u64_u32 and v_mad_i64_i32
2026-10-05 20:26:55 +13:00
Erige005 fb16cb3b19 test(agc): discard the results of recompiles expected to be refused 2026-10-05 07:12:32 +00:00
Adrià FranchandClaude d044384a89 feat(shader): implement global_store_dword_addtid
Decode FLAT opcode 0x17 in the global segment and store the data VGPR of
each active lane at the SGPR pair base plus the signed offset plus four
times the lane id, sharing the address path of global_load_dword_addtid.

Co-Authored-By: Claude <[email protected]>
2026-10-05 08:41:19 +02:00
Adrià FranchandClaude 1cc11cee57 feat(shader): accept tfe and lwe on MIMG loads, stores and samples
Co-Authored-By: Claude <[email protected]>
2026-10-05 08:25:57 +02:00
Dean Galvin 31af5a9d22 perf(recompiler): index lane-strided per-invocation LDS by constant slots
Stages without workgroup memory keep LDS in a per-invocation Function
array. With the array sized to the addresses it reaches (#586),
PPSA21564's intro pixel shader still takes 864 bytes of local memory
per thread on NVIDIA: its accesses are lane * 4 + {0, 256, 512}, so
the index stays dynamic and the 192-dword array lives in local memory.

When every LDS access's address is lane * stride + constant (lane id,
constants, adds, multiplies and left shifts), with one stride, a whole
number of dwords, for all of them and no wrap (the bound analysis
already proves that), the emitter now addresses each access by its
constant plus its instruction offset. The lane id is the same for
every access of an invocation, so taking lane * stride out maps the
addresses one to one, keeps which accesses alias and keeps every
access in bounds; the array sees only constant indices and the driver
keeps it in registers. Shaders with any other address form are
emitted as before.
2026-10-05 18:18:29 +13:00
Dean Galvin bdf39840cf fix(recompiler): size per-invocation LDS arrays to the addresses they reach
Stages without workgroup memory (vertex, pixel, ...) keep LDS in a
per-invocation Function array of 8192 dwords. PPSA21564 creates a pixel
shader that keeps three lane-strided slots there (lane * 4 at byte
offsets 0, 256 and 512). On NVIDIA (driver 610.57) the array becomes
32864 bytes of local memory per thread, and about 15 s after the
pipeline is created the GPU hangs: Xid 109 (CTX SWITCH TIMEOUT), or
Xid 31 (FAULT_PDE VIRT_WRITE) with VK_EXT_device_fault enabled, at an
address no Vulkan object ever held.

The analysis now bounds each LDS access's address over lane ids,
constants, adds, multiplies, shifts, ands, ors, xors, min/max, selects,
bitfield extracts and phis of those. A loop-carried or otherwise
unknown address, an add that could wrap with the instruction offset,
or a shared access whose width is not listed has no bound. The array
becomes the dwords the accesses can reach, rounded up to 64, and stays
at 8192 when any access is unbounded. No access can reach past the
smaller array, so the bounds checks and results are unchanged. The
pixel shader above now takes 192 dwords.
2026-10-05 18:18:18 +13:00
Dean 3655c2ae34 Merge pull request #506 from adriadam10/feat/global-atomics-float
feat(shader): implement the float and 64-bit inc/dec flat and global atomics
2026-10-05 18:15:22 +13:00
Dean 2afc403a04 Merge pull request #495 from adriadam10/feat/flat-cache-bits
feat(shader): accept the glc, slc and dlc cache bits on flat, global and scratch
2026-10-05 18:14:41 +13:00
Dean 12cf58256f Merge pull request #491 from adriadam10/feat/global-atomics
feat(shader): implement the integer flat and global atomics
2026-10-05 18:13:59 +13:00
Dean 7db3e55c6a Merge pull request #591 from hamb3r/fix/avplayer-decode-ahead
fix(avplayer): add decode-ahead buffers for application video output
2026-10-05 18:13:18 +13:00