Commit Graph
12196 Commits
Author SHA1 Message Date
WallisSkillandClaude Opus 5.5 fc25ed9a71 perf(agc): cache freed small blocks per thread on Windows
Recording draws allocates and frees many small objects; on Windows about
a fifth of the queue worker's time went to RtlAllocateHeap and
RtlFreeHeap. The driver's operator new and delete keep up to 64 freed
blocks per 16-byte size class (up to 1 KiB) per thread.

Blocks are plain UCRT malloc blocks, so a block allocated here and freed
by libstdc++ (or the other way round) is still a matching malloc and
free. A freed block is filed under the size class its _msize can hold,
or under the size of a sized delete that is a whole number of granules.
A thread's cache is returned to the heap by a fiber-local-storage
callback when the thread ends; deletes that run later in its teardown go
straight to free. The operators are excluded from the driver's automatic
exports, so libSceAgc and libSceVideoOut keep binding to libstdc++'s.

The cache is reached through a native TLS slot because MinGW's emulated
thread_local costs more than it saves; the same applies to
PageStates::initialize, which now checks an atomic flag before
std::call_once. agc_driver_host_allocator covers every size up to 2 KiB,
sized deletes, buffers that libstdc++ reallocates, blocks freed on
another thread and threads that end with cached blocks; it also checks
that private bytes stay flat over 16 further waves of ending threads, where a
cache that is never given back grows them by about 23 MiB per wave.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-17 01:47:24 +07:00
thibautandClaude Opus 5.5 88ee391839 perf(agc): linear color targets over imported memory get a resident image
A linear color target took a synchronous draw (copy in, draw, copy out, CPU
wait) on every draw. When its memory already has a host import, it now gets a
resident image like tiled targets, and keepRecordedDraw stores its results back
to guest memory right after the draw with a recorded GPU store (FlushPending),
so CPU readers see them as before, without the wait. No import is created for
it (a lookup only): memory without one keeps the synchronous path.
APS5_NO_RESIDENT_LINEAR=1 restores the old path.

GTA V Story (RTX 4090, upstream main eb901bcf4 + #6488): 14.64 -> 16.47 FPS.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01X5rdnz9ZTN3ndFVUfizSvj
2026-10-16 20:42:45 +02:00
ps54allandClaude Opus 5.5 46fdfec852 fix(psml): check the shared resources and add the context under one lock
A concurrent scePsmlMfsrReleaseSharedResources could pass its "still used
by a context" check between the handle lookup and the context insertion.
The technical debt entry now says how KytyPS5's layout differs from the
calls in PPSA08330 and PPSA03016.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-16 20:41:44 +02:00
ps54allandClaude Opus 5.5 7ab3d441c1 feat(psml): implement the MFSR shared-resource and 800 context setup
scePsmlMfsrInit, the shared-resource calls and the 800M3_2 context calls
threw or answered "not initialized", so a title that sets PSSR up at
start-up stopped there even when it never uses PSSR on hardware without
it (PPSA08330 calls the setup unconditionally and only dispatches when
sceKernelIsTrinityMode is set, which AnyPS5 reports as 0).

The layouts come from the calls in PPSA08330 and PPSA03016: requirements
are {block bytes, alignment, block count}, handles are 8-byte values
written through the first argument, and a context parameter carries its
block list at 8/16 and the shared-resources handle at 0x38. Init sets
the initialized state, the requirements ask for four 2 MiB blocks (what
PPSA08330 allocates regardless of the returned count), and create and
release keep bookkeeping objects. Invalid arguments throw because their
error codes are unknown.

The 1100 calls, scePsmlMfsrCreateContext1300 and the 900/1000/1300
dispatch packets keep returning 0x8A810001 before Init and throw after
it; packet size, mip bias and capture still throw.

The guest test links libc and gets Windows unwinding so it can check the
refused calls.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-16 20:41:44 +02:00
Adrià 0936dc910a Merge pull request #5943 from zmeizy/claude/f16-conversion-float-mode
fix(shader): round and flush f16 conversion results by FLOAT_MODE in every denormal mode
2026-10-16 20:39:11 +02:00
Adrià Franch f19050534e fix(agc): disassemble the shared SPIR-V words in agc_shader_replay 2026-10-16 20:34:23 +02:00
fdfawef324andCodex f3fb9df3a0 feat(agc): replay prepared shader capture and materialization offline
Add a CPU replay mode that reaches the runtime descriptor checks and specialization used by prepared shader invocations. Test active and inactive guarded descriptors and continuation after a failed request.

Co-Authored-By: Codex <[email protected]>
2026-10-16 20:34:23 +02:00
Adrià FranchandClaude b8b42e61ed test(libSceNgs2): cover custom filter type 0 and unsupported types
Co-Authored-By: Claude <[email protected]>
2026-10-16 20:32:04 +02:00
alosta f888a236bc fix(libSceNgs2): support custom filter type 0 in Ngs2ApplyCustomParam
Allow custom voice filter type 0 to clear the destination filter,
matching the sampler filter convention. Type 1 continues to configure
the biquad frequency, Q and level. Other unsupported filter types
still throw.

This follows the listener-transform support in
fix/libSceNgs2-listener-transform and is needed for Dead Cells
(PPSA15552), which reaches this path after the custom sampler rack.

Depends on: fix(libSceNgs2): support listener transforms in sceNgs2GeomCalcListener- #5810
Unblocks: PPSA15552
AI assistance: yes
2026-10-16 20:31:18 +02:00
Ahmad e8c97bf926 fix(libkernel): append O_APPEND writes atomically on Windows
On Windows the C runtime appends by seeking to the end and then writing,
so concurrent appends through different descriptors overwrite each other
and lose data. Write and writev on an O_APPEND descriptor now go through
WriteFile at the end-of-file offset, which Windows appends atomically,
and writev gathers its buffers into one append as FreeBSD writes the
whole vector at the end.
2026-10-16 20:25:29 +02:00
xxLnolan 127e111048 test(keycode): cover non-US backslash mapping 2026-10-16 20:24:35 +02:00
xxLnolan 308ad40e46 fix(keycode): map HID non-US backslash key 2026-10-16 20:24:15 +02:00
Yunus Shaikh 583cca0993 fix(agc): keep the stand-in for every pass on a device without multisampled storage images
On such a device a pass with a multisampled color target is refused, because the color samples have no storage view to be reordered through, while a depth-only pass was still reordered. A depth target drawn by both then held its samples in the guest's order after the depth-only pass and was tested in the stand-in's order by the color pass, so on odd rows each sample met the depth of the other half-pixel's position. With #6451 alone both passes kept the stand-in's order. Such a device now refuses the exact order for every pass, so each of its depth targets keeps one order. On a device with multisampled storage images, a color format without a storage view at its sample count still refuses only its own passes, which the debt entry now says.
2026-10-16 11:22:54 -07:00
Alexej Szpevák d97d6efb1b fix(libkernel): refuse descriptor calls on app0.zar files
flock, fstatfs, ftruncate, fsync, fdatasync, getdirentries, fchmod, futimes and mmap on an archived descriptor acted on its null device and succeeded or failed with an unrelated errno. They now throw NotImplemented, each covered by the kernel archive test; mmap is noexcept, so its refusal is checked through the terminate handler.
2026-10-16 20:03:32 +02:00
Alexej Szpevák 9b911ed510 feat(libkernel): serve app0.zar files through the file calls
sceKernelOpen and open give an archived file a read-only null-device descriptor. Reads, positioned, vectored and AIO reads, seeks, fstat and FIONREAD are served from the archive; dup, dup2 and F_DUPFD share the position. sceKernelStat and sceKernelCheckReachability see archived paths.

Writing opens fail with EROFS, O_CREAT|O_EXCL with EEXIST and O_DIRECTORY on a file with ENOTDIR. Opening an archived directory or one merged with the disk throws until getdents can list it.
2026-10-16 20:03:32 +02:00
Alexej Szpevák b71434d9b7 feat(libc): read app0.zar beside app0 and refuse archive-only paths elsewhere
A ZArchive named app0.zar beside app0/ is a read-only layer under it. libc opens it at the first path resolution, looks paths missing from app0/ up case-insensitively, reads files across compressed blocks and keeps the archived descriptor table with shared positions.

Resolving an archive-only path through a call that does not read the archive throws instead of failing with ENOENT, as do opendir of a directory present in both places, fdopen of an archived descriptor and chdir into the archive. A path through .. in an archive-only directory resolves.
2026-10-16 20:03:26 +02:00
AlxcBTW 69b683a901 fix(agc): rate-limit the deferred unaligned BDA reports per instruction
One process-wide counter throttled the reports of every instruction
together, so a second faulting instruction stayed silent after the
first eight reports of the first. The count is kept per program counter
and the periodic line names it.
2026-10-16 19:56:19 +02:00
AlxcBTW e6cb236d67 fix(agc): write storage images back before reporting an unaligned BDA access
The synchronous write-back threw the unaligned access out of
WriteBackBuffers before it marked the written storage images dirty, so
their stores were lost although the shader only skips that access. The
images are now handled first and the report follows, as in the deferred
path.
2026-10-16 19:56:19 +02:00
AlxcBTW fcb48b774f fix(agc): publish after an unaligned BDA access only when it is the only fault
The fault record keeps the first fault of a dispatch, so an early
unaligned access could hide a later unmapped or permission fault, and
the write-back then published the stores of a dispatch that had a real
access fault. The shader now also sets a sticky flag in the record for
every fault of another kind. An unaligned record with that flag set
fails the command like any other fault, before anything is published.
2026-10-16 19:56:19 +02:00
Zinebyte 1295a80013 fix(nid): preserve PE forwarders when repacking export names 2026-10-16 13:52:53 -04:00
AlxcBTW 23a804e393 perf(agc): count the processors the process may run on for the hand-off spin guard
The automatic window needed 8 logical processors, which a 4-core CPU with SMT passes while the waited-for thread may run on a sibling thread, and ignored the process affinity. It now needs more than 8 processors in the affinity mask (CpuTopology), falling back to hardware_concurrency.
2026-10-16 19:52:11 +02:00
Nithishvelan M 301fdbe923 feat(libkernel): return getrlimit soft limit for _SC_OPEN_MAX in sysconf 2026-10-16 23:17:43 +05:30
Tamalero 4a9640677f fix(agc): invalidate cached pages when the arena changes 2026-10-16 17:44:34 +00:00
Tamalero 13a3902954 fix(agc): cache inaccessible guest pages
Remember inaccessible arena pages and Linux mapping gaps so repeated access checks do not rescan host mappings. Invalidate the cache when guest stack protections change.
2026-10-16 17:44:23 +00:00
Adrià 93e54cedd3 Merge pull request #5950 from mrfelek/test/sparse-dmabuf-skip-large-limit
test(agc): skip the sparse dma-buf import tests when udmabuf size_limit_mb is above 1024
2026-10-16 19:40:40 +02:00
Zinebyte 8363c01352 fix(nid): report failed library writes 2026-10-16 13:30:43 -04:00
Zinebyte 6b14c31437 fix(relinker): infer guest dependencies from referenced imports 2026-10-16 13:30:33 -04:00
Zinebyte 32ab27cecb fix(nid): rebuild SysV hashes after renaming ELF symbols 2026-10-16 13:28:19 -04:00
MarcZX100 3dca09e194 fix(agc): validate geometry shader capability 2026-10-16 17:22:42 +00:00
notaxeltvandCursor c32c26edb2 fix(recompiler): emit DEFAULT for missing interpolation bindings
After collector coverage, emit still rebuilt pixel input info from SPI and threw undefined attribute for the same UFC5 shader; return OFFSET 0x20 defaults from SPIR-V emission too.

Co-authored-by: Cursor <[email protected]>
2026-10-16 19:14:53 +02:00
notaxeltvandCursor 377301ef36 fix(recompiler): fill missing pixel interpolators as DEFAULT
PPSA03541 prepares a pixel shader that still reads attribute 0 while SPI_PS_IN_CONTROL.NUM_INTERP is 0; extend the CNTL table with OFFSET 0x20 defaults instead of throwing.

Co-authored-by: Cursor <[email protected]>
2026-10-16 19:14:53 +02:00
Yunus Shaikh f5fd23ee3b test(agc): fail the data hit test on the snapshot mismatches it causes
A plain build passes DispatchDataHitWords without the fix: AddSnapshot
compares the freed words with the live region, prints "guest snapshot
differs from registered memory" and lets the live region serve the GPU,
so the output is right. With APS5_SNAPSHOT_CHECK_FATAL=1 the throw lands
in the resolved-ahead rethrow, which re-runs the dispatch, and it still
passes.

AddSnapshot already counts those mismatches for its report. The count
now lives with the other snapshot compare counters, and
SnapshotMismatches() reads it. The test requires each data hit to add
none.
2026-10-16 17:02:18 +00:00
Daniele Giovane c1745992d7 test(recompiler): identify the executed no-carry GPU case 2026-10-16 18:56:16 +02:00
Daniele Giovane 3210b7130a test(recompiler): reject encoded modified offset forms 2026-10-16 18:56:16 +02:00
Daniele Giovane c637048055 fix(recompiler): recognize plain no-carry draw offset adds 2026-10-16 18:56:16 +02:00
Yunus Shaikh d8e7dd8256 fix(agc): keep a data hit's live words with the regions that span them
A dispatch-cache data hit copies the variant's words into a local
liveWords, patches the data words and builds its captured regions as
spans over that buffer.

When the dispatch is resolved ahead (every compute queue by default),
the parked entry copied both captured and liveWords: the copied regions
still pointed into the local buffer, which was freed on return. The
adopting dispatch then built its snapshots from those regions, and an
address-based program compared the freed words in AddSnapshot (an ASan
heap-use-after-free; the plain build reports "guest snapshot differs
from registered memory"). Moving both into the parked entry keeps the
buffer the regions point into.

The pipelined dispatch item had the same shape: its snapshots span the
local liveWords but the closure did not keep it. Capturing it by move
keeps the item self-contained.

DispatchDataHitWords submits an address-based dispatch whose constant
changes every round on a compute queue, so each data hit is resolved
ahead and adopted.
2026-10-16 16:51:22 +00:00
Adrià FranchandClaude 11f83f2d47 test(agc): keep the vertex BDA shader code static
Co-Authored-By: Claude <[email protected]>
2026-10-16 18:33:34 +02:00
Adrià FranchandClaude a65d42755b test(agc): bound the cancelled journal replay from its own start
The cancelled replay's bound was taken from the totals before the torn-tail replay, which already
adds one present pipeline; when a worker reached the graphics recipe before the cancel, the test
failed (13 of 600 runs with 24 in parallel).

Co-Authored-By: Claude <[email protected]>
2026-10-16 18:13:46 +02:00
MarcZX100 1271998d44 test(agc): check native MSAA source after alias attempts 2026-10-16 15:42:42 +00:00
Yunus Shaikh e97c9975bc fix(agc): initialize the async log's condition variables before its worker starts
A condition variable that winpthreads initializes statically is set up on its first wait, under one global spinlock for all such variables. The async log's worker made that first wait itself, right after the driver started it, so a process that exited soon after starting the driver, such as guest_shader_link, could end with ExitProcess killing the worker inside that setup. The spinlock then stayed held, and the next destructor of a never-used condition variable, in ~Driver, spun forever. The log's constructor now waits on each of its condition variables once with no timeout before it starts the worker, so the worker's waits never take that spinlock. A new shutdown test mode exits right after the driver starts.
2026-10-16 08:40:30 -07:00
Ondra97 a4485bd821 fix(agc): release unpublished buffer slabs on allocation failure 2026-10-16 17:40:21 +02:00
Scramblrrrr aa4018fdf2 fix(shader): poison unsupported biased volume table entries 2026-10-16 12:34:47 -03:00
fdfawef324andClaude Opus 5.5 b9a3296138 fix(shader): drop rebuilt IR when a prepared artifact serves the reload
Prepared captures pass their source handle to the plan reload. When the handle
matches the request, its artifact serves the draw, so the rebuilt resource
program is not kept even if the push layout differs from the artifact's.
A handle that does not match the source is rejected before the entry changes.
Same change as f1b42dae4 on top of c00b0dfb9.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-16 15:24:12 +00:00
fdfawef324andClaude Opus 5.5 d8911150d9 test(shader): cover plan reloads behind a relocated push layout
A prepared artifact also serves draws whose push constants start at another
offset. When such a capture reloads a released plan that is missing from the
disk cache, the rebuilt resource program must not stay on the source entry.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-16 15:24:12 +00:00
MarcZX100 45fcdbaa3c test(agc): isolate native index fixture cases 2026-10-16 15:13:16 +00:00
hugodearaujo 7b55176fa5 fix(libSceAudioOut): report the front left speaker at +30 degrees, as the console does
A PS5 (firmware 13.60) reports the front left speaker of its speaker info at +30 degrees and the front right one at -30, and -360 for the azimuth and elevation of every empty slot, in every HDMI device type and channel setting it offered. sceAudioOut2GetSpeakerInfo reported the front pair the other way round and empty slots as 0, the front centre direction. The type stays 0: the console's type followed the HDMI device type, and it reported 0 with the device set to TV.
2026-10-16 12:06:44 -03:00
Adrià FranchandClaude e1efda1274 fix(build): link the fixed-base loader test with ld.bfd
wild 0.10.0 gives no canonical PLT entry to a DSO function whose address a
non-PIE executable takes (wild-linker/wild#2469, fixed after the release by
#2480), so the absolute personality pointer in .eh_frame names a local stub
and every exception reaching main is unhandled.

Co-Authored-By: Claude <[email protected]>
2026-10-16 17:05:56 +02:00
pushkarreddyy 2de10e35ff feat(libkernel): allow lowering rlim_cur for RLIMIT_NOFILE in setrlimit 2026-10-16 20:33:46 +05:30
Yunus Shaikh 1f10c8afa5 fix(agc): flush the async log within its exit bound when the driver stops
The driver's static is destroyed from its DLL's atexit table at process exit, after ExitProcess has ended the async log's worker. Its stop() then flushed the log through Flush(), which takes the log's lock and waits for every queued line, so it never returned when the worker died holding that lock or with lines queued. #6800's bounded flush runs after it, because the log registers it while the driver is being constructed. stop() now uses that bounded flush, which reads the counters without the lock and gives up after EndFlushLimit, marking the log abandoned. A new shutdown test mode holds the log's lock from another thread and checks that the driver's shutdown still returns.
2026-10-16 07:58:37 -07:00
Daniele Giovane 8e671f4b93 test(agc): cover in-flight preparation and late cache shutdown 2026-10-16 07:58:04 -07:00