Commit Graph

6138 Commits

Author SHA1 Message Date
Michon c1a7a23588 fix(shader): v_writelane_b32 ignores EXEC
V_WRITELANE_B32 writes the selected lane regardless of EXEC, but the
translation routed it through the exec-masked VGPR write, so a spill to an
inactive lane was dropped. The WriteLane test now writes lane 5 while only
lane 0 is active.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 23:42:49 +02:00
Dean Galvin 2351bb39cd perf(recompiler): memoize SRT evaluation in a flat table and inline IrValue's hot accessors
Every draw stage's capture walks the shader's SRT plan with an Evaluator
whose per-value memo was a std::unordered_map: a node allocation per
evaluated value, and out-of-line calls for Opcode, IsIdentity, Resolve
and Argument on every step. The walk took ~17 us of every capture at
PPSA21564's title (about 1.25 s of the queue worker's 10 s).

The memo is now an open-addressing table keyed by the value pointer,
and the accessors are inline. Evaluation order, results and failures
are unchanged. The capture walk drops to ~10 us.
2026-10-03 10:05:11 +13:00
Dean Galvin ad72175a67 fix(recompiler): split image reads whose T# or S# is a Phi of SRT reads
A sampler (or texture) chosen by scalar control flow reaches the image
operation as a Phi of two ReadConst values. The SRT walker only accepts
invariant Phis, so GetHandle threw "GetSamplerResource dword 0 is not a
valid runtime value" and the draw was skipped (G-buffer and HDR draws
in PPSA21564).

Before tracking, a read-only image operation (sample, gather, LOD query,
size query, load) whose descriptor dwords are Phis of one block is
copied once per distinct incoming descriptor. Each copy gets its own
memory entry and descriptor handles whose dwords are the edge's values,
recomputed before the operation (SRT reads, user data, the shader base
and pure uniform arithmetic over them only). The results are selected
by a Bool Phi of the edge that entered the Phi block. The copies run
where the original did, so implicit derivatives are unchanged, and the
host binds every edge's descriptor. Any other shape (a nested Phi, a
dynamic read on an edge, a store or atomic) is left alone and still
throws.
2026-10-03 10:02:51 +13:00
Dean Galvin d209a2e5c1 fix(recompiler): give an early-return selection that joins its parent's merge a merge of its own
A selection whose one arm only returns (kill or s_endpgm) and whose other
arm branches straight to the merge of an enclosing selection had no
structured merge, so the draw was skipped. PPSA21564's BotEye G-buffer
pixel shaders (eight variants) have this shape.

When no other split applies, the edge from such a header to the shared
join is now split into an empty block, which becomes the header's merge.
2026-10-03 10:01:45 +13:00
Dean Galvin a3ffb73309 perf(agc): deliver end-of-pipe interrupts after their work without draining
A RELEASE_MEM with an interrupt select drained the device: the queue
worker submitted everything recorded and waited for the GPU before it
stored the label and delivered the interrupt. PPSA21564 issues about 300
of them per frame, so the worker and the GPU took turns.

The label is now recorded like any other (on the GPU behind the work, or
as a completion action behind pending write-backs), and the delivery
becomes a completion action of the batch holding the work before the
packet (Recorder::AfterRecordedWork, after the batch's earlier
completions). It is counted with the completion labels, so idle workers
and pollers reap it, and it starts the label flush deadline. With draws
or dispatches recorded since the last submit the batch is submitted at
once. A batch holding only label stores stays open and goes out with the
next work, at the label flush deadline, at a wait, at a flip or at the
end of the submission, like any other pending label. A label the GPU
cannot store, or one that does not decode, still drains.

The interrupt so never arrives before the work ahead of it completed and
its label landed; it can only arrive later, by at most the flush
deadline plus the work recorded into the same batch.
2026-10-03 09:56:05 +13:00
Dean Galvin 947912357f perf(agc): copy the interleaved attributes of a vertex buffer once per draw
Every vertex attribute copied its own range of guest memory, so a draw
over an interleaved buffer copied it once per attribute (seven or eleven
times for PPSA21564's level meshes). Attributes with the same stride and
input rate whose first elements lie within one record now share one copy
of their union, each bound at its offset into it.
2026-10-03 09:52:04 +13:00
Dean Galvin a4264793b1 perf(agc): keep a queue's registers in flat arrays instead of a std::map
Every SET_*_REG packet stored each register into a std::map, and every
draw read dozens of them back through map lookups (the decoders, the
draw key's range walks, the prechecks). PPSA21564 sends ~350k register
packets per 10 s at the title, and the map's node allocations and tree
walks were a visible share of the graphics queue worker's time.

Registers is now a flat value array with a presence bitmap per bank. It
keeps the map's interface and semantics: absent registers stay absent,
iteration and lower_bound walk the present registers in offset order,
emplace does not overwrite and at() throws for an unset register.
2026-10-03 09:48:44 +13:00
Pouare514 92f3cb3916 fix(libc): return NULL with ENOENT for missing files in fopen 2026-10-02 22:41:57 +02:00
boykopovar 7d40a57d18
Merge pull request #308 from asimplestray/feat/shader-vop3-mad
feat(shader): implement legacy float multiply-add ops
2026-10-02 23:29:05 +03:00
boykopovar 5540d1953b
Merge pull request #384 from DotDebian/feat/vop3-lerp-u8
feat(shader): implement v_lerp_u8
2026-10-02 23:28:28 +03:00
boykopovar b68c8c27f1
Merge pull request #379 from DotDebian/feat/shader-vop3-sad
feat(shader): implement v_sad_u8, v_sad_hi_u8, v_sad_u16 and v_msad_u8
2026-10-02 23:28:10 +03:00
boykopovar 95f4503aab
Merge pull request #358 from Pouare514/feat/cyberpunk2077-loading
feat(libs): Cyberpunk 2077 loading support (REDGalaxy + stubs)
2026-10-02 23:26:45 +03:00
Pouare514 1c724c0228 feat(libs): Cyberpunk 2077 loading support (REDGalaxy + stubs)
# Conflicts:
#	core/libs/prx/libSceContentExport/Export.cpp
#	core/libs/prx/libScePlayGoDialog/Export.cpp
2026-10-02 23:14:04 +03:00
boykopovar 8ff209a865
Merge pull request #300 from Pouare514/feat/libScePlayGoDialog
feat(libScePlayGoDialog): add PlayGo install dialog
2026-10-02 23:08:55 +03:00
boykopovar d098840dbc
Merge pull request #307 from oneandonlydean/feat/avplayer-ffmpeg
feat(avplayer): decode H.264 and AAC with FFmpeg
2026-10-02 23:07:49 +03:00
boykopovar b45d521224
Merge pull request #287 from SP4C3B4R-8/feat/pad-tilt-correction
feat(libScePad): implement scePadSetTiltCorrectionState
2026-10-02 23:02:26 +03:00
Dean Galvin 6142e82aa0 perf(agc): keep the 10-bit scanout resident and present it with the guest path's pixels
PPSA21564's final composite renders into 4K 10-bit scanout buffers
(COLOR_2_10_10_10 with the alternate swap, A2R10G10B10). No guest texture
format matched that color format, so the target stayed non-resident:
every frame's composite draw ran synchronously (about 11 ms, 143 per 10 s
at the title) and the flip read the frame back through guest memory.

The blue-low 10-bit color target now keeps its bits in the storage image
of its surface's red-low 2-10-10-10 format, as B8G8R8A8 targets map to
R8G8B8A8.

Presenting it: DisplayTexelFormat names a display buffer's texel order as
the guest-memory path reads it (R8G8B8A8 base: red low, else blue low;
the 10-bit variant: A2B10G10R10 or A2R10G10B10). ResidentPresentPath
blits a resident image only when it holds the display's 8-bit texel
format (an exact copy). A 10-bit image (whose blit would round where the
guest path drops the low two bits), the other 8-bit order or an sRGB type
is converted instead: GpuColorTransfer::DetileImage copies the image's
texels raw and runs the guest path's own conversion shader on them, so
both paths present the same pixels.

The image's write-back is unchanged: its results stay pending like any
resident target's and are stored when a reader of the memory flushes
them.

Tests: agc_driver_recorder_tests checks the format decision for both
8-bit and both 10-bit orders, and converts an image in each order,
comparing it with the CPU decode and the GPU detile of the same words in
guest memory.
2026-10-03 08:49:27 +13:00
boykopovar 48752c1132
Merge pull request #280 from arreina/pr/rdna-truncated-modifier
fix(shader): reject SDWA and DPP instructions without their modifier word
2026-10-02 22:45:32 +03:00
boykopovar 82bd115159
Merge pull request #275 from oneandonlydean/fix/recompiler-exit-tail-merge
fix(recompiler): give a loop's exit-tail branch a selection merge
2026-10-02 22:44:47 +03:00
boykopovar 5026351b3f
Merge pull request #274 from RomainROCH/codex/fix-directory-buffer-errors
fix(libkernel): report undersized Windows directory buffers
2026-10-02 22:39:37 +03:00
boykopovar 4181fbd521
Merge pull request #279 from Pouare514/fix/dreaming-sarah-boot
fix(libkernel): boot Dreaming Sarah past unwind and debug raise
2026-10-02 22:38:49 +03:00
boykopovar 7831d57aed
Merge pull request #277 from oneandonlydean/perf/agc-draw-input-reuse
perf(agc): reuse a draw's index and vertex copies while the guest bytes are unchanged
2026-10-02 22:33:32 +03:00
boykopovar f9e0b8ba69
Merge pull request #276 from oneandonlydean/perf/agc-draw-snapshot-reuse
perf(agc): reuse unchanged draw input snapshots across draws
2026-10-02 22:33:18 +03:00
boykopovar 55cea557ee
Merge pull request #273 from RomainROCH/codex/fix-save-memory-growth
fix(savedata): preserve memory saves when growth reads fail
2026-10-02 22:32:56 +03:00
boykopovar 11814ad660
Merge pull request #349 from DotDebian/feat/sync-on-address
feat(libkernel): implement sceKernelSyncOnAddressWait and sceKernelSyncOnAddressWake
2026-10-02 22:31:45 +03:00
Michon df8c0f1a3a perf(agc): build the color target swizzle tables once per element size
ColorTargetLayout built its SW_64KB_R_X offset tables in every
constructor, and every draw constructs a layout per color target while
decoding and again while setting the target up. The tables depend only on
the element size; they are now built once per size under std::call_once
and the layout points into them.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 21:27:43 +02:00
boykopovar 27edcac156
Merge pull request #261 from MichonGoddijn231849/fix/rect-list-per-vertex-parameters
fix(shader): rect lists take explicitly interpolated fragment parameters and refuse only custom ones
2026-10-02 22:23:14 +03:00
boykopovar 4503ec54af
Merge pull request #260 from adriadam10/fix/vop3-compare-neg
fix(shader): accept neg on VOP3-encoded float compares
2026-10-02 22:22:18 +03:00
boykopovar 2af9dda269
Merge pull request #255 from adriadam10/feat/scalar-bit-count-ops
feat(shader): implement s_bcnt0_i32_b64, s_ff0_i32_b64, s_flbit_i32(_i64), s_quadmask_b32
2026-10-02 22:21:49 +03:00
boykopovar d399b4e04c
Merge pull request #245 from RomainROCH/codex/fix-windows-directory-close
fix(libkernel): clear directory metadata on close
2026-10-02 22:21:30 +03:00
boykopovar 41cb304326
Merge pull request #244 from RomainROCH/codex/fix-save-replacement
fix(savedata): preserve existing saves on replace failure
2026-10-02 22:20:58 +03:00
boykopovar 74bdce6f04
Merge pull request #232 from MichonGoddijn231849/fix/guest-read-destination
fix(libkernel): read, pread, AIO and APR write into guest memory as host writes
2026-10-02 22:19:46 +03:00
boykopovar 7db340de2b
Merge pull request #231 from MichonGoddijn231849/fix/guest-arena-reserve
fix(libc): reserve the guest arena at its fixed range around what Windows already placed in it
2026-10-02 22:15:26 +03:00
Dean Galvin b62d02c2af feat(avplayer): decode H.264 and AAC with FFmpeg
Replace the decoder-less AvPlayer with a player that demuxes MP4 sources
with FFmpeg (opened by path or through the title's file replacement),
decodes H.264 and AAC on their own threads, and hands out NV12 frames and
interleaved 16-bit PCM in buffers from the title's allocators, presented
on a media clock that audio drives when it is enabled.

Both libSceAvPlayer and libSceAvPlayer.native are built from the same
sources and link the shared ffmpeg target. The struct size checks stay,
next to the types in SceTypes.hpp. ChangeStream and GetStreamInfoEx are
implemented; Init without allocators, StartEx, SetAvailableBandwidth,
SetLogCallback and negative trick speeds succeed as before and are listed
in TechnicalDebt. HLS sources throw.

guest_avplayer plays an embedded 6 KB MP4 (H.264 plus two AAC tracks).
2026-10-03 08:10:55 +13:00
boykopovar 1cc9874ac1
Merge pull request #227 from adriadam10/feat/png-enc
feat(libScePngEnc): implement PNG encoding
2026-10-02 22:08:05 +03:00
boykopovar 4c7a9ea2b0
Merge pull request #226 from asimplestray/feat/shader-mimg-gather-sample
feat(shader): implement MIMG sample/gather flag variants
2026-10-02 22:07:36 +03:00
boykopovar 5572f6b143
Merge pull request #399 from boykopovar/fix/f16-nle-compare-lowering
fix(shader): lower f16 NLE comparisons through swapped unordered less…
2026-10-02 22:06:31 +03:00
boykopovar 0032decb6a ci(tests): run build tests three times 2026-10-02 22:02:20 +03:00
Michon 85c8beea48 perf(agc): index the pending storage images by guest range
Every guest memory read checks the pending storage images for results it
must store first (FlushPending, overlappingPending and the overlap test of
shader resources), each by a scan of the whole registry, and each scan read
the thread-local `refreshing` once per image (an emutls call with MinGW).
The registry now keeps a sorted, merged index of the ranges its images
cover, rebuilt on the first query after a change: a query that overlaps
none of them returns without a scan. The scans read `refreshing` once.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 21:01:26 +02:00
boykopovar 329c007514
Merge pull request #402 from boykopovar/docs/build-and-manual-md
Docs/build and manual md
2026-10-02 21:59:32 +03:00
boykopovar 545b137097 docs(usage): add relinker usage md doc 2026-10-02 21:50:35 +03:00
Alberto Ruiz 95c1b40e71 fix(savedata): reject invalid directory names in sceSaveDataDelete
sceSaveDataDelete appended the title's directory name to the save root
without any check and passed the result to std::filesystem::remove_all.
"../victim" removed a directory beside the save root, ".." the directory
holding the save root, and an empty name or "." every save. The name
now has to be terminated within its field, non-empty, not "." or "..",
and free of "/", "\" and ":", as sceSaveDataMount3 already requires;
otherwise the call returns SAVE_DATA_ERROR_PARAMETER and deletes nothing.

The native library gains its own CMakeLists.txt, with the same library
definition as the generic one, to register guest_savedata_delete.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R5WJS4ZdQynAJesCZKH5hb
2026-10-02 20:41:43 +02:00
boykopovar ee6a4a00f4 docs(build): add prject build md instruction 2026-10-02 21:40:38 +03:00
Michon ccb6697109 perf(agc): keep the buffer pool's free slots by key and retain 4096
Take scanned every retained slot of its tier for one with the same size,
usage and memory properties, so the slot bound stayed at 512. With 512
slots GTA V's in-game builds overflowed the small tier: each draw evicted
and recreated buffers, and the submission thread spent most of its time
in the driver's allocation and free calls. The slots are now kept in
lists per key, oldest first: Take pops the newest of its key, eviction
takes the oldest front. The bound is 4096 slots per tier, held to a sixth
of maxMemoryAllocationCount.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 20:20:50 +02:00
boykopovar a80d1fd09b fix(shader): lower f16 NLE comparisons through swapped unordered less-than 2026-10-02 21:17:18 +03:00
DotDebian b4506a359c feat(shader): decode image_sample_d_cl_o
MIMG opcode 0x33 samples with explicit derivatives, an LOD clamp and a
texel offset. The three address flags already exist; only the opcode was
missing from the decoder table.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 19:07:30 +02:00
DotDebian febf50447a fix(shader): let image samples clamp their LOD on devices with shaderResourceMinLod
The LOD clamp of an image sample looked for the MinLod capability in the
emitter's own requirement list, which nothing fills, so every sample with
a clamp failed to compile on every device. The check now reads the
capabilities of the target, and a sample that takes the MinLod operand
declares the capability in its module.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 19:03:29 +02:00
DotDebian 362ba8a1a6 feat(shader): implement the integer dot products
Decode and translate v_dot2_i32_i16, v_dot2_u32_u16, v_dot4_i32_i8,
v_dot4_u32_u8, v_dot8_i32_i4, v_dot8_u32_u4 (VOP3P 0x14-0x19) and
v_dot4c_i32_i8 (VOP2 0x0d).

Clamp, neg and the op_sel combinations whose behaviour is not
established throw.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 19:01:57 +02:00
DotDebian 4a4a1eddc1 feat(shader): implement v_lerp_u8
Decode VOP3 0x14d and translate it as the per-byte average of S0 and S1,
rounded up where bit 0 of the matching S2 byte is set and truncated
otherwise.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 18:57:06 +02:00
Nicolas Abosch 35b40b76c3 feat(audio3d): implement default open parameters 2026-10-02 13:54:01 -03:00