Commit Graph
14017 Commits
Author SHA1 Message Date
Dean b0c2e05ba0 Merge pull request #619 from oneandonlydean/fix/agc-writeback-block-padding
fix(agc): keep the guest's bytes in the padding a storage write-back stores
2026-10-05 21:21:54 +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
Dean 50e7712002 Merge pull request #608 from adriadam10/test/scalar-program-flow
fix(shader): wave-wide exec and vcc branch conditions
2026-10-05 18:13:07 +13:00
Dean f809199b0a Merge pull request #606 from adriadam10/fix/permlane16-inactive-source
fix(shader): keep v_permlane16 lanes whose source lane is inactive
2026-10-05 18:12:26 +13:00
Dean Galvin 60c655211d perf(recompiler): let exec-guarded memory and exports end a masked select
A register written under EXEC is usually consumed by an LDS or buffer
access or an export under the same EXEC. MaskedSelectEliminator kept
the select in that case, which leaves the NGG mesh shaders where they
were.

The emitter performs buffer and LDS loads and stores (8 to 128 bits,
GPU-selected V# included) and SetAttribute only in lanes whose active
operand is true: stores and exports sit in an if on it, loads return 0
outside it. Every other operand is read only in those lanes. So such an
access whose active operand implies the select's condition reads the
derived value only where it equals the original, and it now ends the
search like a masked select does. The active operand itself, atomics,
append/consume, scratch and address-space accesses and image accesses
still keep the select.
2026-10-05 18:12:23 +13:00
Dean Galvin dd2a70bc13 perf(recompiler): drop exec selects whose inactive lanes nobody reads
Every VGPR write under EXEC is translated to Select(exec, new, old), so
in SSA each register's previous value stays live until the next write,
even when the guest only used the register as a temporary. In NGG mesh
shaders at 255 registers that keeps dead values alive and the driver
spills them to local memory.

MaskedSelectEliminator (after SSA, folding and the readlane pass)
replaces r = Select(m, new, old) by new when no lane where m is false
can observe r:
- every value derived from r is either a lane-local pure op or a phi,
  and their uses are checked the same way;
- or the derived value reaches the true operand of a select, or an
  operand of a LogicalAnd, whose condition implies m: m itself, a
  LogicalAnd containing m, or a thread bit rebuilt from a ballot of
  such a condition (also through ANDs of the mask words);
- anything else (cross-lane ops, ballots, readfirstlane, DPP, swizzle,
  permutes, stores, exports, atomics, branch references, implicit-LOD
  pixel samples, the false operand of any select) keeps the select.
The select and every value it reaches must be in blocks outside loops,
so each of them runs at most once per invocation and every use sees the
same instance of m. Selects whose condition is the full wave
((0xffffffff >> (lane & 31)) & 1) are replaced in any block.

Exact: in lanes where m is true r equals new, so every derived value is
unchanged there; in lanes where m is false only derived values change,
and each path from them ends in a select or AND that discards those
lanes. The selects are removed latest first and dead code is removed
between rounds, so chains of writes to one register collapse.
2026-10-05 18:12:23 +13:00
Dean e074483ab7 Merge pull request #604 from adriadam10/fix/smem-buffer-offset-overflow
fix(shader): return zero when an s_buffer_load offset passes 2^32
2026-10-05 18:11:43 +13:00
Dean e90d2edf54 Merge pull request #596 from adriadam10/fix/vop3-pack-ldexp-bits
fix(shader): compute v_cvt_pknorm_*_f32, v_ldexp_f32 and v_pack_b32_f16 on the bits
2026-10-05 18:11:01 +13:00
Dean bdd10f1929 Merge pull request #475 from adriadam10/feat/mimg-coarse-g16
feat(shader): implement image_sample_cd/_g16 variants and fix a16 gradient layout
2026-10-05 18:10:20 +13:00
Dean 71f248ad54 Merge pull request #568 from adriadam10/fix/f32-minmax-nan
fix(shader): return src0 when both f32 min/max sources are NaN
2026-10-05 18:09:38 +13:00
Dean 4ca60c434c Merge pull request #524 from DotDebian/feat/mimg-bvh64-intersect-ray
feat(shader): implement image_bvh64_intersect_ray
2026-10-05 18:08:57 +13:00
Dean 1e0f62e118 Merge pull request #515 from adriadam10/fix/dpp16-inactive-source
fix(shader): DPP16 lanes whose source lane is inactive
2026-10-05 18:08:46 +13:00
Dean a84d759dd2 Merge pull request #498 from adriadam10/feat/vop2-dpp-sdwa-float-mods
feat(shader): accept float modifiers on v_cndmask_b32, v_mul_legacy_f32 and v_ldexp_f16
2026-10-05 18:08:04 +13:00
Dean 0087fb6369 Merge pull request #567 from adriadam10/fix/f32-omod-zero
fix(shader): apply the f32 output modifier on the bits like the hardware
2026-10-05 18:07:22 +13:00
Dean dbfdcb1c79 Merge pull request #537 from adriadam10/test/vop1-float-unary
fix(shader): choose unary f32/f16 special results on the bits, as RDNA does
2026-10-05 18:06:40 +13:00
Dean 9f5fac08c8 Merge pull request #323 from adriadam10/fix/f16-result-clamp
fix(shader): apply clamp but not omod to f16 results, as RDNA does
2026-10-05 18:06:29 +13:00
Dean 3e92cefb4c Merge pull request #613 from nicolasabosch/feat/ult-blocking-queues
feat(ult): implement blocking queues and shared data pools
2026-10-05 18:06:19 +13:00
Dean f7ecd24ddb Merge pull request #610 from adriadam10/feat/div-fmas-fixup-clamp
feat(shader): accept clamp on v_div_fmas/fixup and omod on their f64 forms
2026-10-05 18:05:38 +13:00
Dean 3067a93fe9 Merge pull request #609 from nicolasabosch/fix/rtc-arithmetic-bounds
fix(rtc): reject out-of-range source ticks in date arithmetic
2026-10-05 18:04:57 +13:00
Nicolas Abosch 93efde8056 fix(relinker): merge function symbol alias extents 2026-10-05 01:50:14 -03:00
Dean Galvin 1c4aadb3e3 fix(agc): route compacted color exports to the slots CB_SHADER_MASK enables
Pixel shader color exports are compacted: export MRTi goes to the i-th
MRT slot with a non-zero CB_SHADER_MASK nibble and takes the i-th
SPI_SHADER_COL_FORMAT field. Draws still mapped export i to slot i and
read slot i's format field, so a shader with CB_SHADER_MASK 0xf000f and
SPI_SHADER_COL_FORMAT 0x44 (export 1 to slot 4) was refused with
"color export format 0".

Each color target now carries its export index next to its slot.
Attachment references, blend states, export mappings and the pipeline
and pass keys follow the export index; the color buffer, blend control
and target mask come from the slot. An unwritten export below the
highest written one stays an unused attachment.
2026-10-05 17:03:43 +13:00
Nicolas Abosch 043332ba32 docs(ult): avoid overlapping AvPlayer debt note 2026-10-05 00:57:02 -03:00
Dean 4dac9d6373 Merge pull request #602 from NumberGuan/fix/relinker-prx-directory
fix(relinker): discover bundled modules in prx directories
2026-10-05 16:54:18 +13:00
Nicolas Abosch 65c139336e feat(ult): implement blocking queues and shared data pools 2026-10-05 00:52:22 -03:00
Adrià FranchandClaude c6df07e604 feat(shader): accept clamp on v_div_fmas/fixup and omod on their f64 forms
Co-Authored-By: Claude <[email protected]>
2026-10-05 05:19:06 +02:00
Nicolas Abosch 76b7294f06 fix(rtc): reject out-of-range source ticks in date arithmetic 2026-10-05 00:15:57 -03:00
Dean e91eecc402 Merge pull request #607 from adriadam10/test/setpc
fix(shader): refuse s_setpc_b64 after s_sub with the immediate first
2026-10-05 16:10:53 +13:00
Dean 3aedbbc128 Merge pull request #605 from adriadam10/test/ds-swizzle
test(shader): execute ds_swizzle_b32 in all three offset modes
2026-10-05 16:10:11 +13:00
Dean 202a73b543 Merge pull request #603 from nicolasabosch/fix/libc-long-integer-conversions
fix(libc): preserve 64-bit strtol and strtoul results on Windows
2026-10-05 16:09:30 +13:00
Adrià FranchandClaude c67634a15c feat(shader): implement the float and 64-bit inc/dec flat and global atomics
Co-Authored-By: Claude <[email protected]>
2026-10-05 05:05:10 +02:00
Adrià FranchandClaude 183a0f09b4 feat(shader): accept the glc, slc and dlc cache bits on flat, global and scratch
Loads and stores with glc or dlc are coherent, as MUBUF already does; slc
is a cache hint and changes no result. Atomics keep glc as the return bit.
lds, segment 3 and scratch atomics still throw.

Co-Authored-By: Claude <[email protected]>
2026-10-05 05:05:10 +02:00
Adrià FranchandClaude 038ded6382 feat(shader): implement the integer flat and global atomics
Co-Authored-By: Claude <[email protected]>
2026-10-05 05:05:03 +02:00
DotDebianandClaude Opus 5.5 be866e4214 feat(shader): store through flat and global addresses
flat_store_* and global_store_* decoded and translated, but a store whose
segment is not scratch was refused when the SPIR-V was emitted ("writable
FLAT/GLOBAL addresses require GPU ownership tracking").

Such a store now goes through the BDA page table like a store through a
GPU-selected V#: the write lookup needs Write permission, which only a
writable registered range imported in place has, and the written page is
noted for the host to mark GPU-written. Byte and short stores, and dword
stores to an address that is not dword aligned, are stored byte by byte.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-05 05:05:03 +02:00