Commit Graph
5577 Commits
Author SHA1 Message Date
JohnMandClaude Opus 5.5 d1c14102ab fix(relinker): reject a relocation target whose range wraps the address space
A jump slot whose r_offset is 0xFFFFFFFFFFFFFFF8 or higher makes
targetGotOrPltAddress + 8 wrap, so the upper lower_bound lands before
the lower one and the call-site loop walks past the end of the map
(SIGSEGV; ASan heap-buffer-overflow in ResolveCallSites).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 11:03:16 +08:00
Dean Galvin 19d620dec5 test(videoout): skip the output mode test without a display
guest_video_out_output_mode (#1496) opens VideoOut directly, which needs
a Vulkan-capable SDL window, and aborts on the CI runners that have none.
Skip with 77 like the other VideoOut window tests, unless
ANYPS5_REQUIRE_DISPLAY is set.
2026-10-10 15:36:07 +13:00
Joey Fisher f2d201fbbf fix(ajm, apr): keep AJM and APR state alive through static teardown
AJM's instance and batch tables and APR's file, directory and AMM
state were namespace-scope statics, destroyed by std::exit while the
title's threads keep calling the libraries. A decoder thread then read
a freed instance (an unknown codec), sceAjmBatchWait no longer found
its batch, and APR resolved file ids through a freed vector. The state
is now allocated once and never destroyed.
2026-10-09 20:14:04 -06:00
Raihan Abdul MajidandClaude Opus 5.5 144e60f836 fix(audioout): play every AudioOut2 port buffer set between pushes, one per grain
A port kept only the last PCM buffer set before a push and played it again
at every later push without a new one. PPSA12544 sets one grain of a ring
buffer per call on its object port, often two or three between pushes and
then none for a few, so all but the last of each burst were dropped and the
stale grain repeated: a buzz on loud sounds and after a sound stopped.

Buffers set between pushes are now queued and played in order, at most 16
queued. A push without a new buffer repeats the last one only for a port
that has always been given the same buffer (rewritten in place, as the
timing tests do); a port whose buffers move on plays silence.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 09:11:23 +07:00
overlordxrz-source e607b1ce4e feat(libkernel): implement shm_open for anonymous objects 2026-10-09 22:05:57 -04:00
Oguzhan Ozdemir 2e01ba2832 fix(audio): bind singular propagation path setter as unsupported 2026-10-10 03:50:02 +02:00
Dean c963432db0 Merge pull request #1645 from XairRrR/fix/raise-open-file-limit
fix(libkernel): raise the open file soft limit on Linux
2026-10-10 14:44:55 +13:00
Dean ee50132692 Merge pull request #1626 from mohdfaour03/fix/sysmodule-unloaded-error
fix(sysmodule): report a module that is not loaded as SCE_SYSMODULE_ERROR_UNLOADED
2026-10-10 14:42:18 +13:00
Dean 771510096f Merge pull request #1622 from TheAggie/fix/agc-suspend-writes-queued-labels
fix(agc): write queued labels at a suspend point before a device exists
2026-10-10 14:42:08 +13:00
Dean e6f9348b31 Merge pull request #1621 from TheAggie/fix/libc-heap-32-byte-alignment
fix(libc): align guest heap allocations to 32 bytes
2026-10-10 14:41:57 +13:00
validation agent 32eb8b27e3 test(libkernel): cover the scaled process clock origin 2026-10-10 09:28:51 +08:00
hazzardouslysolid fb1eb20ed4 fix(rtc): floor pre-epoch timestamps for timezone lookup 2026-10-10 09:28:30 +08:00
hazzardouslysolid b5903e80da fix(png): bound transparency chunk detection to the input 2026-10-10 09:28:30 +08:00
hazzardouslysolid 7accd92281 fix(libkernel): initialise scaled clock origin before reading time 2026-10-10 09:28:30 +08:00
arcwiser a18955ee97 fix(relinker): keep fixed Windows images loadable 2026-10-10 12:26:02 +11:00
russhil 4a2e60546c feat(shader): emulate fragment barycentrics with a generated geometry stage
Without VK_KHR_fragment_shader_barycentric the recompiler dropped
v_interp_p1_f32 and made v_interp_p2_f32 read the attribute Vulkan
interpolated, but never wrote the I/J VGPRs: a pixel shader that read
them for anything else got 0, and v_interp_mov_f32 of P10/P20 (or P0 of
an interpolated input) needed PerVertexKHR and failed pipeline
validation.

The fallback translation now loads the I/J VGPRs and marks v_interp_p1
and v_interp_p2 with witnesses. After the front-end simplification
(SSA, folding, DCE, read-lane and masked-select elimination),
HostInterpolationChecker requires every p2 to read its J, and its p1's
I, from a barycentric of the parameter's kind, every p1 result to reach
only the matching p2 (through a write masked by the p2's EXEC, whose
inactive lanes keep the old register), no parameter read as raw
vertices and no slot shared by different interpolations. It then
lowers the witnesses to the host-interpolated attribute as before,
reruns DCE and masked-select elimination, and accepts the program only
when no barycentric read remains, so reusing the I/J VGPRs after
interpolating keeps host interpolation and the previous SPIR-V. Any other
program is translated with the barycentric path and marked as emulated:
its barycentrics become vec3 inputs (NoPerspective for the linear
weights) and its per-vertex parameters flat vec4[3] inputs, placed in
the free locations by LayoutBarycentricEmulation. The driver then
inserts a generated geometry stage between the vertex and fragment
shaders that copies the position and parameters, writes the one-hot
weights of each vertex and the three vertices' parameter values, so the
rasterizer interpolates the same weights the extension provides.

The stage needs geometryShader and a vertex shader before it;
tessellation, mesh and rect-list pipelines, other primitive types and
interfaces beyond 32 locations or the device's geometry limits throw.
CompiledShaderArtifact carries the emulation (shader disk cache format 21).

Hardware snaps window corners to 1/256 pixel before interpolating
(measured by yahya308 on an RTX 4070 Laptop and a Radeon 780M in #1547);
lavapipe snaps only for coverage (lp_rast.h FIXED_ORDER 8), so the test
accepts either reference per pixel at the original 1e-4 margin.

Sources:
- v_interp_p1_f32/v_interp_p2_f32/v_interp_mov_f32 semantics (P0,
  P10, P20, I/J): AMD RDNA2 ISA, "Parameter Interpolation".
- BaryCoordKHR/BaryCoordNoPerspKHR weights and PerVertexKHR vertex order:
  SPV_KHR_fragment_shader_barycentric, VK_KHR_fragment_shader_barycentric.
- Geometry shader triangle input order and provoking vertex: Vulkan
  specification, "Primitive Topologies" and "Geometry Shading".
- Interpolation decorations decided by the fragment input: Vulkan
  specification, "Interpolation Decorations".
- lavapipe interpolation: Mesa src/gallium/drivers/llvmpipe/lp_rast.h
  (FIXED_ORDER 8), lp_setup_tri.c (subpixel_snap for coverage only),
  lp_state_setup.c (init_args, plane setup from float positions).
2026-10-10 03:24:50 +02:00
Dean Galvin 7638c11841 perf(agc): keep occlusion counter dumps inside the open render pass
A PIXEL_PIPE_STAT_DUMP event (EVENT_WRITE 0x39, Recorder::DumpSamples)
ended the render pass the previous draw left open: the dump ended the
batch-long occlusion query, copied its result with
vkCmdCopyQueryPoolResults and ran the fold kernel, none of which Vulkan
allows inside a render pass. VulkanDevice::DumpSamplesOnGpu also flushed
the queued store run over the dumped bytes first, which ended the pass
and recorded the run's barriers as well. A title that clears each query
slot with WRITE_DATA and brackets every bounding draw with a begin and an
end dump gets a render pass, two copy barriers and a label run per draw.

Samples are now counted in segments. A segment is one slot of a
per-batch occlusion query pool (128 slots, reset outside any pass when the
batch's first pass needs one). It begins at the first draw recorded after
a pass begins or after a dump, inside that pass's subpass, and ends at the
next dump or right before vkCmdEndRenderPass, so each query begins and
ends in one subpass. A pass whose pool has no free slot left is not
continued, so a new pool can be reset. The draw path that records a whole
pass of its own prepares a slot before its pass and ends its segment
before ending it.

A dump ends the open segment and is queued in the batch's store run with
the number of segments before it; it no longer ends the pass and no
longer flushes the queued stores. The run is recorded where queued stores
already are: at Submit, or earlier when a later command reads or writes
the queued bytes. Its recording copies the results of the segments the
dumps need (one vkCmdCopyQueryPoolResults per contiguous slot range) and
the dump list, then records the queue in groups: a group's stores, then
one dispatch of the SampleDumps kernel, which adds each dump's segments to
the running total and stores the 16 counters in queue order. A store over
bytes a dump of the current group writes starts a new group, so every
byte ends with the value of its last write in program order
(Recorder::QueuedWriteGroups). At Submit, segments no dump consumed are
folded the same way once 64 are pending.

No reader sees a dump later than before: a CPU reader of the dumped bytes
syncs the batch (the dump still notes them as a pending write), and Submit
records the run before the batch ends; a later label or store is queued
after the dump in the same run; GPU work that reads or writes the queued
bytes flushes the run first, as for queued label stores. No reader sees it
earlier either: the dump is recorded after every draw whose samples it
counts, and its segments end at the dump. Without the GPU sample counter
(no buffer device addresses) the batch-long query is kept as before.

Tests (agc_driver_recorder_tests, GPU, run by hand): QueuedWriteGroups
keeps the program order's bytes for 20,000 random store and dump
sequences; a queued dump does not land before its run is recorded, a
reader of other bytes leaves it queued and a reader of its bytes records
it; clear, dump and store orders over shared bytes; two dumps inside one
render pass keep it open (the next draw continues it) and split its three
draws' samples exactly with precise queries; a reader flushing a dump
inside a pass ends the pass; 160 dumps in one pass past a pool's 128
slots; 70 passes without a dump folded at Submit.
2026-10-10 14:24:27 +13:00
Dean Galvin 77373c0380 fix(agc): pass the depth bounds test when both depth planes are absent
Main renders depth and stencil tests without a depth target when DB_Z_INFO and DB_STENCIL_INFO both have FORMAT INVALID (48ebf3195e): with no plane, the DB has nothing to test, and every test passes. The depth bounds test (DB_DEPTH_CONTROL bit 3) reads the same absent depth plane, but such a draw still threw "depth bounds without a depth surface". A title does this when a level loads.

Depth bounds now follow the same rule when both planes are absent. With an absent depth plane beside a present stencil plane, the bounds test still throws ("depth bounds without a depth plane"), as before.
2026-10-10 14:24:26 +13:00
Hannah Lyons c970ca73a0 fix(relinker): read LSDA call-site tables only under a personality routine 2026-10-09 21:23:27 -04:00
Hannah Lyons d7e52cb295 feat(libkernel): implement madvise 2026-10-09 21:22:44 -04:00
Hannah Lyons 94a33bfa5c fix(libkernel): honour open flags when Windows falls back to a directory descriptor 2026-10-09 21:22:23 -04:00
alfalfa-starandClaude Opus 5.5 b7443c4424 perf(agc): share one dma-buf import per 64 MiB of Linux direct memory
Every direct memory allocation had a memfd of its own, so each one the
GPU used became its own udmabuf and its own imported buffer object. An
imported buffer object cannot be always valid in the GPU VM: amdgpu
validates every one of them at every command submission. PPSA14632
(LEGO Horizon Adventures) imports about 7000 allocations, 5800 of them
64 KiB, and each vkQueueSubmit took about 2.3 ms (5 s per 10 s, held
under the GPU mutex). A standalone test shows the cost follows the
count of imported dma-buf buffer objects, not their size or the count
of ordinary allocations.

- libkernel: on Linux all direct memory lives in one sparse memfd of
  DIRECT_MEMORY_SIZE, at file offset = physical address
  (PhysicalBacking keeps the file and its offset; SharedBacking returns
  that offset). A range allocated again is zeroed through a temporary
  mapping, as the old per-allocation memfd was.
- Driver: an import of shared direct memory that lies inside one
  64 MiB chunk of the file binds its own VkBuffer into that chunk's
  memory, one udmabuf import per chunk (HostImport::chunk holds it, so
  it lives until the last buffer bound to it retires). Ranges that
  cross a chunk or do not meet the buffer alignment are imported alone
  as before.

On PPSA14632 vkQueueSubmit drops from about 2400 us to 46 us on
average, the GPU idles 36 ms instead of 172 ms per present, and
presents go from about 40 to 80-97 per 10 s.

Released direct memory stays committed in the file (see
TechnicalDebt.md): a live chunk import pins its pages.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 03:21:53 +02:00
Sanjaysrinivas 140c46093c fix(shader): guard runtime MODE changes
Read MODE rounding fields from the declared initial mode. Accept only
constant writes that preserve it; diagnose unsupported runtime changes.
Document the supported contract and add decoder-to-recompiler regressions.

Refs #1668, #981
2026-10-10 03:16:25 +02:00
Adrià c9da0f93cf Merge pull request #1559 from ctj01/fix/relinker-pt-load-order
fix(relinker): write Linux PT_LOAD headers in ascending address order
2026-10-10 03:16:06 +02:00
Adrià 67bb99865a Merge pull request #1518 from ArjenS-LA/fix/windows-file-timestamps
fix(libkernel): preserve Windows file timestamp precision
2026-10-10 03:15:32 +02:00
Adrià 426fe62282 Merge pull request #2028 from overlordxrz-source/feat/libkernel-get-module-list
feat(libkernel): implement sceKernelGetModuleList and sceKernelGetModuleInfo
2026-10-10 03:15:01 +02:00
Adrià 419069e6d3 Merge pull request #1606 from mohdfaour03/fix/libc-guest-tm-layout
fix(libc): convert times into the guest's 56-byte tm on Windows
2026-10-10 03:14:40 +02:00
Adrià b255a3b998 Merge pull request #1604 from Zheorgyan/fix/host-thread-local-async-teardown
test(libc): wait for std::async thread teardown in host_thread_local
2026-10-10 03:14:22 +02:00
Adrià 2d58760056 Merge pull request #1602 from krishnaraya4/fix/agc-linear-volume-mip-rounding
fix(agc): round linear volume mip extents up as addrlib does
2026-10-10 03:14:01 +02:00
Adrià 6637eee34d Merge pull request #1600 from awake-devel/fix/libkernel-unwind-info-linux
fix(libkernel): report guest unwind tables in sceKernelGetModuleInfoForUnwind on Linux
2026-10-10 03:13:40 +02:00
Adrià 3181e7116d Merge pull request #1597 from mugurc/macos-relinker
feat(relinker): write Mach-O output for macOS with --macos
2026-10-10 03:13:21 +02:00
Adrià 16602061e0 Merge pull request #1589 from krishnaraya4/fix/rdna-mubuf-lds-refused
fix(shader): refuse the MUBUF lds modifier instead of decoding a VGPR load
2026-10-10 03:13:01 +02:00
Adrià d11caf7519 Merge pull request #1588 from Roojool/fix/net-epoll-precise-timeout
fix(net): use native Windows condition waits for empty epoll
2026-10-10 03:12:41 +02:00
Adrià b2f4218ad2 Merge pull request #1587 from krishnaraya4/fix/agc-release-mem-int-sel-bounds
fix(libSceAgcDriver): read the RELEASE_MEM interrupt select only from RELEASE_MEM packets
2026-10-10 03:12:22 +02:00
Sasha PapoandClaude Opus 5.5 98b4bdf843 fix(agc): skip an indexed draw whose indices are all restart markers
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-09 21:12:16 -04:00
Sasha PapoandClaude Opus 5.5 c0a88ce392 fix(agc): leave the primitive restart index out of an indexed draw's vertex range
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-09 21:12:16 -04:00
Adrià a9ac7bc4c3 Merge pull request #1580 from Zheorgyan/feat/storage-buffers-update-after-bind
feat(agc): bind storage buffers update-after-bind above the per-stage limit
2026-10-10 03:12:01 +02:00
Adrià b9d7fd6448 Merge pull request #1571 from Zheorgyan/fix/exp-f32-smallest-normal
fix(shader): keep v_exp_f32 at or above the smallest normal for inputs from -126
2026-10-10 03:11:42 +02:00
Elijah De GuzmanandClaude Opus 5.5 80b0bab279 feat(libc): write watch on macOS hosts
macOS has no counterpart to userfaultfd write-protect or
MEM_WRITE_WATCH, so GuestWriteWatch had no backend there and the driver
re-read every guest buffer on each use.

The macOS backend write-protects watched pages. The first write to a
page faults, the SIGBUS/SIGSEGV handler records the page and restores
its protection, and Collect reports the recorded pages and protects
them again. A page is protected before its record is cleared, under the
lock the handler takes, so a write that lands in between is recorded.
The lock hands out turns in order: an unfair one starved writers under
Rosetta.

The protection is real, which adds three entry points:
- GuestWriteWatchBeginHostWrite/EndHostWrite lift it around a system
  call that writes guest memory, which would otherwise fail with
  EFAULT. GuestArena::HostWrite calls them, as it calls the Windows
  equivalent.
- GuestWriteWatchProtectionChanged tells the watch the protection given
  to watched pages by mprotect or a new mapping.
- GuestWriteWatchProtection reports that protection, since a watched
  page is read-only between a collection and the next write.

Register keeps the recorded protection of a page it already watches:
read from the kernel it would be the watch's own read-only protection,
and the page would never be watched again.

The tests build without the prx libraries and run natively and through
Rosetta.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-09 21:11:40 -04:00
Adrià 206df95c36 Merge pull request #1565 from Zheorgyan/fix/exec-host-lanes-vertex-subgroups
test(agc): skip the exec host lanes vertex draw without vertex subgroups
2026-10-10 03:11:21 +02:00
Dean 8542c7323c Merge pull request #1501 from TideOPL/fix/kernel-process-time-start
fix(libkernel): read the process start before the clock in process time
2026-10-10 14:10:57 +13:00
Adrià 7876b46ff3 Merge pull request #1534 from hamb3r/codex/clearmrt-stencil-clear
fix(agc): preserve ClearMRT color writes and validate stencil clears
2026-10-10 03:09:58 +02:00
Adrià 69cee68d4b Merge pull request #1522 from silentone12725/perf/relinker-strict-reachability
perf(relinker): replace O(n²) zero-padding scan in StrictReachability
2026-10-10 03:08:57 +02:00
Adrià b8cf0eb24f Merge pull request #1520 from popcoder565/fix/kernel-nested-sleep-timer
fix(libkernel): give a sleep nested in an APC its own timer on Windows
2026-10-10 03:07:46 +02:00
Adrià 7f1b6a0b30 Merge pull request #1507 from ArjenS-LA/fix/libc-wcsrtombs
fix(libc): convert wcsrtombs using guest characters
2026-10-10 03:05:55 +02:00
Adrià 395d24697c Merge pull request #1506 from kali113/fix/linux-guest-stack-header
fix(relinker): give Linux guest modules a default non-executable stack
2026-10-10 03:05:35 +02:00
Adrià be3441903b Merge pull request #1503 from eliasbruno124-dev/fix/guest-required-identities
fix(relinker): discover required guest module identities
2026-10-10 03:05:15 +02:00
Adrià 0eb7f098dd Merge pull request #1499 from yabanana/codex/macos-unwind-register-context
feat(libc): support x86-64 unwind register contexts on macOS
2026-10-10 03:04:54 +02:00
Adrià 85d4bfcf34 Merge pull request #1496 from hugodearaujo/fix/videoout-output-mode-errors
fix(videoout): answer output mode queries with the console's codes
2026-10-10 03:04:33 +02:00
Adrià 806ff29e5a Merge pull request #1495 from TideOPL/fix/agc-depth-memory-reuse
fix(agc): treat other-shaped views of a depth surface's memory as reused memory
2026-10-10 03:04:14 +02:00