Commit Graph
14017 Commits
Author SHA1 Message Date
Adrià FranchandClaude ecda77d51d fix(agc): run wave32 compute programs on 32-wide subgroups
On devices whose default subgroup is 64 lanes (RADV, AMD on Windows) a
wave32 compute program was compiled for a 64-wide host subgroup, so the two
guest waves of a 64-thread workgroup shared one subgroup: ballots, EXEC,
v_mbcnt and lane reads of the second wave saw the first one's lanes.

With VK_EXT_subgroup_size_control, when compute can require 32 lanes, the
dispatch recompiles wave32 programs for a 32-wide host subgroup
(VulkanDevice::ComputeTarget) and the pipeline requires that size. The
result records the width it was compiled for (hostSubgroupSize, also in the
disk cache).

Co-Authored-By: Claude <[email protected]>
2026-10-02 06:28:08 +02:00
RomainROCH 74586bab57 fix(libkernel): avoid semaphore count overflow 2026-10-02 06:19:39 +02:00
Adrià FranchandClaude d06883aeff fix(shader): select the written lane in v_writelane_b32
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]>
2026-10-02 06:18:55 +02:00
RomainROCH 99fbcf0377 fix(libc): propagate file position errors 2026-10-02 06:15:14 +02:00
RomainROCH 193ec6e268 fix(savedata): report memory metadata write failures 2026-10-02 06:05:54 +02:00
asimplestray f2bfdd26f9 feat(shader): implement SOP1 saveexec/wrexec family 2026-10-02 00:22:41 +00:00
Dean Galvin 301f3b161e fix(recompiler): sample with texel offsets the guest computes, through maintenance8's Offset
image_sample_*_o takes its texel offset from an address VGPR. The emitter
accepted only an immediate there and failed with "requires a constant texel
offset for image sampling" for any other, including an offset the program
moves into the VGPR under EXEC.

An offset that resolves to a constant at its packed address position stays a
ConstOffset. Any other becomes the Offset image operand, which Vulkan allows
on sampling instructions only with VK_KHR_maintenance8's maintenance8 feature
and the ImageGatherExtended capability. The device enables maintenance8 when
available and reports it through SpirvTarget::nonConstantImageOffsets, which
the cache key, the request serialization (version 6) and the SPIRV-Tools
validator options follow. Without it the sample still fails.

agc_shader_replay --maintenance8 recompiles a request for such a device.
2026-10-02 12:26:31 +13:00
SP4C3B4R-8andClaude Opus 5.5 53aac1137a fix(libSceAgcDriver): destroy host imports of a replaced Vulkan device
Replacing the headless device with the windowed one dropped the import
registry without freeing its buffers and memory, and the replaced device
is kept alive, so the imported pinned host memory stayed allocated and
the new device ran out of memory importing the same ranges again.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-01 23:54:43 +02:00
SP4C3B4R-8andClaude Opus 5.5 c4be3f78f6 feat(libScePad): implement scePadSetTiltCorrectionState
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Bn7CrhG7pTPR6DT13tN6Me
2026-10-01 23:44:31 +02:00
SP4C3B4R-8andClaude Opus 5.5 d56ce19531 docs: record unknown NIDs of the newly declared exports
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-01 23:44:31 +02:00
SP4C3B4R-8andClaude Opus 5.5 4099ffb7d3 feat(libkernel): accept MAP_NO_OVERWRITE fixed mappings on Windows
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Bn7CrhG7pTPR6DT13tN6Me
2026-10-01 23:44:31 +02:00
SP4C3B4R-8andClaude Opus 5.5 f2deb00fa4 feat(libs): declare missing AudioPropagation, AudioIn, NpSessionSignaling and dialog exports
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Bn7CrhG7pTPR6DT13tN6Me
2026-10-01 23:44:31 +02:00
SP4C3B4R-8andClaude Opus 5.5 3fc3b993da feat(libkernel): honour non-fixed mapping address hints on Windows
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Bn7CrhG7pTPR6DT13tN6Me
2026-10-01 23:44:30 +02:00
SP4C3B4R-8andClaude Opus 5.5 8641b60265 fix(build): copy MinGW runtime next to test executables
Tests resolved libstdc++/libgcc/winpthread through PATH, so another MinGW
installation earlier in PATH (e.g. Git for Windows) made them fail with
STATUS_ENTRYPOINT_NOT_FOUND (0xc0000139).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Bn7CrhG7pTPR6DT13tN6Me
2026-10-01 23:44:29 +02:00
SP4C3B4R-8andClaude Opus 5.5 ef172bb5d1 fix(libSceAgcDriver): prefer a discrete GPU over the first suitable device
Physical device selection took the first Vulkan device with graphics,
compute and presentation support, so on systems with an integrated GPU
(e.g. Ryzen 7000 desktop CPUs) the enumeration order decided whether the
integrated or the discrete GPU was used. Rank candidates by device type.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Bn7CrhG7pTPR6DT13tN6Me
2026-10-01 23:44:29 +02:00
Dean Galvin e69de0df66 perf(agc): reuse a draw's index and vertex copies while the guest bytes are unchanged
Every draw copied its index and vertex ranges from guest memory into
fresh buffers and scanned the indices, although the draws of a frame read
the same meshes again: about 10 GiB of vertex copies per 10 s at
PPSA21564's title.

CopyDrawInput now keeps the copy in the recorder's draw snapshot cache
and binds it again while the write tracker proves the range unchanged
since the copy was taken, with the same rules as the storage-buffer
snapshots: UnchangedSince on the collect made right before the copy and
an unchanged allocation registry. As GuestMemory::Read does, the flush
hook runs first, so pending GPU results over the range are stored and
stamped before the check. Unwatched memory is copied every time. An index
copy keeps its highest index; the device limit is still checked for every
draw.

The cache key includes the snapshot's use (storage, vertex, 16-bit or
32-bit index), so each use keeps its own buffer with its own usage. A
vertex copy runs from the buffer's start to its highest fetched element,
so draws over one shared vertex pool ask for many sizes: a vertex
snapshot also serves a shorter read at the same address while that
read's bytes are unchanged, and a new one replaces the shorter ones.
Vertex and index snapshots have their own least recently used pool
(1 GiB, 16384 entries), so storage copies, most of which change every
frame, do not push them out before their next use.

Tests: agc_driver_recorder_tests copies index and vertex ranges of
write-watched memory and requires a reuse (with the stored highest index)
while the bytes are unchanged, a new copy with the current bytes after a
CPU store, a MarkWritten store and a registry mutation, separate copies
per use, no reuse without a recorder, prefix reuse for vertex reads only,
and storage snapshots not evicting vertex snapshots.
2026-10-02 10:30:36 +13:00
Dean Galvin 69a94208b7 perf(agc): reuse unchanged draw input snapshots across draws
A recorded draw binds a CPU copy of each read-only guest buffer it reads
in place, made for every draw. PPSA21564's title-stage draws bind the
same large light-list buffers written by compute passes (up to 16 MiB
each) hundreds of times per frame, so about 4 ms of every draw went into
copying about 30 MiB into freshly allocated host buffers.

The recorder now keeps the snapshots, least recently used first, under a
256 MiB budget and 1024 entries. A later draw of the same range binds the
kept, immutable copy while GuestMemory::UnchangedSince holds for the
write generation collected right before the copy and the guest allocation
registry generation is unchanged. A CPU store (stamped by a collect), a
driver or GPU store (MarkWritten) or a registry mutation makes the next
draw copy again. Unwatched memory has no generation and is copied for
every draw, as before.

A recency list (each entry holding its own position) gives the eviction
victim and moves a used entry to the back in O(1).

Tests: agc_driver_recorder_tests binds a write-watched, host-imported
range twice and requires the same snapshot, then a new copy with the new
bytes after a CPU store, a MarkWritten store and a registry mutation; and
checks the least recently used eviction order at the entry cap, the byte
budget and a CPU store dropping a kept snapshot.
2026-10-02 10:27:00 +13:00
RomainROCH 021eb65b51 fix(libkernel): report undersized Windows directory buffers 2026-10-01 23:24:41 +02:00
Dean Galvin 66ddf59c22 fix(recompiler): give a loop's exit-tail branch a selection merge
A conditional inside a loop with one target in the loop body and the
other outside it was taken for a break and emitted without a merge. When
the outside target is not the loop's merge but a tail of blocks that
reaches it, SPIR-V has no construct for that branch: spirv-val rejects
the module ("Selection must be structured") and the driver is free to
compile it into anything.

Such a branch now merges at its in-body target when the tail is private
to it (every tail block is dominated by the tail's first block, stays in
the loop construct and leaves only for the loop's merge), so the tail is
an "if (c) { tail; break; }" the loop already allows. Merges are given
to these after every other construct's, and one already taken leaves the
branch as before.

All 13 PPSA21564 programs whose V#s are read from GPU memory (the
deferred lighting and ray-traced passes) had two such branches in their
traversal loops. With this change none of the 74 dumped title programs
has one, and the 209 modules of a title-to-cinematic run validate apart
from three unrelated image-offset and entry-point errors.

Tests: agc_structurizer_tests structures a loop that exits through one
tail block and a loop with two exit tails, and requires every merge-less
conditional to target its loop's merge or continue.
2026-10-02 10:23:02 +13:00
MichonandClaude Opus 5.5 f9162abb84 fix(agc): color targets with gaps between written MRT slots, depth array slices
An MRT slot below the highest written one that the draw does not write is a VK_ATTACHMENT_UNUSED
reference with a disabled blend; color targets keep their slot for export mappings, pipeline and
pass keys. DB_DEPTH_VIEW SLICE_START moves the depth and stencil planes by whole slices, so each
slice of a depth array is its own depth surface.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-10-01 23:21:58 +02:00
MichonandClaude Opus 5.5 04691c0797 feat(libs): offline services GTA V reaches in Story Mode
Sign-in, web browser and player dialogs finish cancelled; the message dialog finishes at once;
NpAuth, entitlement consumption, reachability, account age and the NpUtility bandwidth test
report signed out; sceKernelMtypeprotect changes the protection (the memory type has no host
equivalent); the APR ForEach resolvers resolve every path and report each failure in its own
result entry. vswprintf's stub is dropped in favor of the existing wide-formatter
implementation, which already covers it on every platform.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-10-01 23:21:54 +02:00
RomainROCH c58f3f0a14 fix(savedata): preserve memory saves when growth reads fail 2026-10-01 23:20:39 +02:00
Alberto RuizandClaude Opus 5.5 fc68a04b0b fix(shader): reject SDWA and DPP instructions without their modifier word
The VOP1, VOP2 and VOPC SDWA and DPP decoders read the modifier word at
wordIndex + 1 before SetRdnaRawWords checked that it exists, so a code
span ending at such an instruction was read one word past its end.
AddressSanitizer reports a heap-buffer-overflow in decodeVop2Sdwa on a
synthetic program. The six decoders now throw "truncated <encoding>
instruction" first, as DecodeRdnaVop3 and DecodeRdnaVop3p already do.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01R5WJS4ZdQynAJesCZKH5hb
2026-10-01 22:49:38 +02:00
Adrià FranchandClaude 703afd5b10 fix(shader): accept neg on VOP3-encoded float compares
VOP3 compares have a scalar destination, so checkNativeVop3Modifiers sent
them through the carry/scalar-destination branch, which rejects neg. abs
already passed and both are applied to the sources by the VOPC path, so
v_cmp_lt_f32_e64 vcc_lo, -v1, v2 threw "VOP3 source modifiers are not
implemented". Float compares now accept neg there; integer ones still don't.

Co-Authored-By: Claude <[email protected]>
2026-10-01 22:45:25 +02:00
Adrià FranchandClaude b6376737bb feat(shader): implement the missing non-f64 VOPC compares
Fifty VOPC opcodes threw in the decoder: cmpx f/o/u/tru for f32, cmpx f/t
for i32/u32, the 64-bit integer compares except the seven already present,
and the f16 f/o/u/nge/nlg/ngt/nle/nlt/tru compares and their cmpx forms.
64-bit gt/le/ge are built from SLessThan64/ULessThan64 by swapping and
negating, as the IR has no other 64-bit orderings. emitFloatOrderedCompare
gains the f16 and cmpx forms.

Co-Authored-By: Claude <[email protected]>
2026-10-01 22:45:25 +02:00
Adrià FranchandClaude e144f43f05 feat(shader): implement VOP3 v_add/sub_nc_i32 with clamp, v_mul_lo_u16, v_mad_u16/i16/u32_u16/i32_i16, v_ashrrev_i64
These VOP3 opcodes threw in the decoder. v_add_nc_i32 and v_sub_nc_i32 are
what compilers emit for signed saturating add/sub, so their clamp saturates
to the int32 range. The 16-bit mads honour op_sel on their 16-bit sources;
the u32_u16/i32_i16 forms take a 32-bit addend and write all 32 bits, so
they do not get the 16-bit destination select.

Co-Authored-By: Claude <[email protected]>
2026-10-01 22:45:25 +02:00
Adrià FranchandClaude e56511f2b4 feat(shader): decode cache invalidations and performance hints as no-ops
s_icache_inv, s_incperflevel, s_decperflevel, s_ttracedata_imm, s_wait_idle,
s_gl1_inv, s_dcache_inv, s_dcache_wb, buffer_gl0_inv and buffer_gl1_inv threw
in the decoder. SPIR-V has no cache control, so they translate like s_clause
and s_waitcnt, which already emit nothing. The SMEM and MUBUF forms carry no
operands, so no pass sees a phantom base or destination register.

Co-Authored-By: Claude <[email protected]>
2026-10-01 22:45:25 +02:00
Adrià FranchandClaude d97c6aee63 feat(shader): decode VOP3 v_max/min_f16 and v_cvt_f32_f16/ubyte, accept abs/neg on f16 binaries
The VOP2/VOP1 forms already translate; the VOP3 encodings were rejected by the
decoder. VOP3 f16 add/sub/subrev/mul/min/max now take abs and neg, which
readF16AsF32 already applies. Clamp and omod stay rejected for them because
writeF16 does not apply result modifiers.

Co-Authored-By: Claude <[email protected]>
2026-10-01 22:45:25 +02:00
Adrià FranchandClaude 8ed454d2fa ci: run the shader execution tests on lavapipe
MixPrecision and SdwaDestination dispatch hand-assembled RDNA through the
recompiler and compare every lane with a CPU model, but were never in ctest.
Move them to tests/execution/, which is globbed into one test per file with
the same target names, so new execution tests add a file and no CMake lines.
They exit 77 (skipped) when the host has no Vulkan device; the Linux runner
installs lavapipe and sets ANYPS5_REQUIRE_VULKAN=1 so they cannot skip there.

Co-Authored-By: Claude <[email protected]>
2026-10-01 22:45:25 +02:00
RomainROCH 8f76c0a57f fix(libc): release aligned allocations through the application heap 2026-10-01 22:43:44 +02:00
boykopovar 709d7fe0fd Merge pull request #258 from boykopovar/fix/revert-pr-143
Revert "Merge pull request #143 from SamG-Coder/codex/shader-geometry…
2026-10-01 23:30:05 +03:00
MichonandClaude Opus 5.5 f5ae0b8106 fix(shader): rect lists take explicitly interpolated fragment parameters and refuse only custom ones
Explicit v_interp_p1/p2 interpolation (fragment-shader barycentrics) reads every interpolated
parameter per vertex, and the rect-list shaders refused every per-vertex parameter. Their
tessellation stage emits each corner's parameter value, which is what a per-vertex read of the
generated triangles needs. Only custom parameters (custom interpolation or passthrough), whose
fourth vertex has no value of its own, stay refused; FragmentParameter carries that flag.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-10-01 22:13:36 +02:00
boykopovar 7c5f8b6e12 Revert "Merge pull request #143 from SamG-Coder/codex/shader-geometry-validation"
This reverts commit de49f81697, reversing
changes made to cfb1d76e60.
2026-10-01 22:55:27 +03:00
MichonandClaude Opus 5.5 ecf73da860 fix(agc): the stage-A fast path leaves a view of a pending image whose keys were filled to the full lookup
A sampled read through a surface's keys after a uniform key fill with a clear code reads the
fill's clear value, not the image's pending results (cachedTexture's clear-through-keys). The
stage-A fast path returned the record's view of the pending image without that check, so a
read between the fill and the image's next refresh saw the previous results.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-10-01 21:12:26 +02:00
boykopovar 75434ee4ad Merge pull request #240 from adriadam10/feat/pad-small
feat(libScePad): implement scePadGetHandle and the embedded mic vibration option
2026-10-01 22:00:55 +03:00
boykopovar 643c8cfc99 Merge pull request #239 from adriadam10/fix/error-codes
fix(libs): correct VideoOut and Pad error codes
2026-10-01 21:59:04 +03:00
boykopovar 54c3f39680 Merge pull request #238 from adriadam10/feat/playgo-language-todo
feat(libScePlayGo): fix error codes, implement the language mask and to-do list
2026-10-01 21:58:12 +03:00
boykopovar ce6bd0c750 Merge pull request #233 from adriadam10/feat/fiber-context-size-check
feat(libSceFiber): implement context size checking and the thread frame pointer
2026-10-01 21:57:29 +03:00
boykopovar 171c9a97b2 Merge pull request #230 from asimplestray/feat/rt-miss-mode
feat(shader): add ray tracing miss fallback mode
2026-10-01 21:56:27 +03:00
boykopovar 1720539f86 Merge pull request #229 from adriadam10/fix/progress-stub-wrappers
fix(tools): count exports that call a local stub wrapper as unimplemented
2026-10-01 21:55:53 +03:00
boykopovar a360f162c6 Merge pull request #224 from adriadam10/feat/ces-cp1252
feat(libSceCesCs): convert single characters between CP1252 and UTF-8
2026-10-01 21:53:01 +03:00
boykopovar e0f7866205 Merge pull request #223 from adriadam10/feat/http2-ssl-stubs
feat(libSceSsl): implement CA certificate queries and sceHttp2AbortRequest
2026-10-01 21:52:19 +03:00
boykopovar 0567aca352 Merge pull request #225 from adriadam10/feat/keyboard-key2char
feat(libSceKeyboard): implement the keyboard library
2026-10-01 21:50:25 +03:00
boykopovar 938b632784 Merge pull request #221 from adriadam10/feat/http-uri
feat(libSceHttp): implement URI parse, build and escape
2026-10-01 21:48:06 +03:00
boykopovar 01e1074efc Merge pull request #219 from asimplestray/feat/shader-vop3-minmax16
feat(shader): implement VOP3 I16/U16 min/max/med3
2026-10-01 21:42:12 +03:00
Dean Galvin ea0f13027e fix(agc): end a key fill's hold when the fill clears the image at once
An image's filledKeys stands for "the pending results predate the title's
key fill": sampled reads through those keys bind the clear value, and
(with APS5_KEYS_FILL_WRITEBACK_KEEP=1) a write-back leaves the keys at the
fill's code. A refresh that clears the image under the new keys ends that
hold (upload resets it), but the immediate clear of APS5_KEYS_FILL_CLEAR=1
did not. Results drawn after such a fill were then treated as dead: reads
through the keys saw the clear and a write-back kept the keys clear over
them. The immediate clear now ends the hold as the refresh does.
2026-10-02 07:41:50 +13:00
RomainROCH 9c07fc0a98 style(savedata): remove namespace comment 2026-10-01 20:35:18 +02:00
boykopovar 1ffaa66173 Merge pull request #215 from julienlgy/feat/lib-sce-hmd-stub
feat(libSceHmd): add a disconnected-headset HLE stub
2026-10-01 21:28:09 +03:00
boykopovar c19448f834 Merge pull request #214 from oneandonlydean/fix/recompiler-sdwa-dword-dst
fix(recompiler): zero the high half of 16-bit SDWA results written as a whole dword
2026-10-01 21:27:50 +03:00
boykopovar e6a0af7e09 Merge pull request #213 from arreina/pr/cache-empty-memcpy
fix(shader): skip the push constant copy when there is nothing to copy
2026-10-01 21:22:29 +03:00