Commit Graph
12196 Commits
Author SHA1 Message Date
Nithishvelan M e92484a251 feat(libSceUserService): implement sceUserServiceGetAccessibilityKeyremapEnable and sceUserServiceGetAccessibilityZoom 2026-10-16 08:42:16 +05:30
hypermistandClaude Opus 5.5 20edd079e4 fix(libc): store the sign of gamma in an exported signgam from lgamma
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-16 16:11:02 +13:00
Yunus Shaikh 6522b92fde fix(agc): stop and join the shader disk cache writer at shutdown
The shader disk cache's writer, started with the cache at the first
shader lookup, was detached and never stopped. It stayed parked in a
timed wait on its queue until the process exit killed it, and entries
still queued at exit were never written. A process that exited right
after its first shaders could kill the writer inside its first wait,
which takes winpthreads' global condition-variable lock, as with the
driver's own threads.

The writer is now joinable. The driver's shutdown stops it after the
other driver threads: the writer writes the entries still queued and
leaves, and the shutdown joins it. A store after that is written on the
caller, and a cache first used after the shutdown starts no writer.
ShaderDiskCache::Shutdown joins the names the cache key check has
reviewed, since it changes nothing a recompile produces.
2026-10-15 19:57:51 -07:00
Yunus Shaikh 966da79fcb fix(agc): stop and join the draw pipeline's committer at shutdown
The committer of pipelined draws, started at the first pipelined
submission, was never stopped. The driver's shutdown joined the queue
workers and left the committer parked on its queue, and a commit the
last submission left queued, such as its deferred completion, could
still run after the shutdown had reset the device. A process that
exited right after its first pipelined submissions could kill the
committer inside its first wait on the queue, which takes winpthreads'
global condition-variable lock, as with the preparation workers.

The driver's shutdown now stops the committer after joining the queue
workers and before taking the GPU lock. The committer runs the commits
still queued and leaves, and the shutdown joins it. A commit enqueued
after that runs on the caller.
2026-10-15 19:57:51 -07:00
Nicolas AboschandClaude Opus 5.5 6ce90a7286 perf(libkernel): keep the sleep wake include and debt entry off lines other PRs change
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 23:42:41 -03:00
Yunus Shaikh fcaa432840 perf(agc): settle Windows imports under 1 MiB without waiting
Since #6060 a Windows host import of private write-watched memory stays
in the write watch only after its settle, a 4-byte GPU read that the
importing thread waits for, and only imports of 1 MiB or more are
settled: SuperTuxKart imports a 64 KiB buffer around every submission,
and the wait cost it about 19% of its frame rate. A smaller import is
compared instead, and its range leaves the write watch for good.
Resident Evil Village maps its GPU heap in 64 KiB pieces, so every
texture over that heap is compared with guest memory.

An import under 1 MiB is still compared when it is made, but its read is
now queued. The next import lookup that holds the device lock records
the reads queued since into one batch on the settle queue and submits
it, so the thread that maps and imports neither submits nor waits.
Once the batch's fence has signalled, a later lookup returns the
imports' blocks to the write watch, except where storage results are
pending over them, which waits for a later lookup. An import retired
while its read is in flight waits for that batch first.

A settled import whose range had already left the write watch, such as
a whole range imported over a piece that was compared, returns to it
the same way.
2026-10-15 19:42:17 -07:00
Yunus Shaikh 356d2a9dfa fix(agc): plan a sparse heap again when its mirror's range has left the write watch
A sparse heap mirror, made for a heap with uncommitted pages, is
refreshed from the write watch through its committed pieces. The check
that a reused heap mirror's range is still watched covered the heap
mirrors acquireMirror reuses and the cached space's heap runs, not
sparse ones: once a committed piece left the watch, refreshSparseMirror
threw "a sparse heap mirror's range is no longer write-watched" from
acquireMirror's reuse and from a cache hit's sparse refresh.

refreshSparseMirror now returns false when a piece is no longer
watched. Both callers already take false as not reusable: acquireMirror
makes the mirror again, finds the range unwatched, drops the stale
mirror and leaves the range to a copy, and a cache hit gives up the
cached space.

agc_sparse_heap_mirror_unwatch mirrors a 1 MiB reservation with 256 KiB
committed, takes one committed block off the write watch and stores new
bytes there from the CPU; the next build must not reuse the mirror and
must serve the new bytes. agc_sparse_heap_mirror_unwatch_no_space_cache
runs the same without the address-space cache. Without the fix both
throw. They are registered on Linux; the Windows path uses the guest
arena as the existing sparse heap test does and has not run on Windows.
2026-10-16 01:52:33 +00:00
Nicolas AboschandClaude Opus 5.5 82dd286192 perf(libkernel): end short sleeps when the GPU or a flip completes
A sleep of 1 ms or less returns once the AGC driver sees a GPU batch
complete (a thread waits on the recorder's timeline semaphore), runs a
batch's completion actions, or VideoOut completes a flip. A thread
returns early at most 8 times in a run of back-to-back sleeps; the run
restarts when the thread submits AGC work or did not sleep for the
requested time. APS5_NO_SLEEP_WAKE=1 keeps every sleep in full.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 22:50:57 -03:00
Yuri Olive 630ab4c20b feat(libSceHttp): implement sceHttpUriCopy 2026-10-15 22:46:40 -03:00
JJenkx 522696d1ce fix(agc): retain front-half offchip LDS enable during shader fusion 2026-10-15 21:42:43 -04:00
Jota ce316bfce8 fix(relinker): validate the PT_TLS layout when reading program headers
The Linux output passed a PT_TLS whose initialization image is outside every PT_LOAD, whose file size exceeds its memory size, whose alignment is not a power of two, or that follows another PT_TLS, straight to the dynamic loader, which reads the image from p_vaddr when it sets up TLS. The Windows and macOS writers already refuse these layouts. Reject them in ElfReader so every target, and guest modules, see the same rule. An empty PT_TLS placeholder is still accepted.
2026-10-15 22:38:08 -03:00
Yunus Shaikh 8be2de862b feat(agc): return whole 64 KiB blocks to the Windows write watch
GuestMemory::Rewatch takes ranges that left the write watch back into
it. Only whole tracker blocks whose pages can be collected return:
their write-watch marks are collected and dropped, and every block is
stamped as a CPU store with a new generation, so a snapshot or a proof
made before the block left the watch reads as changed, and the blocks'
untracked hints stop applying. It does nothing outside Windows.
2026-10-15 18:37:10 -07:00
Yunus Shaikh af58b9562a fix(agc): stop the pipeline library worker before the device is reset
Driver::stop reset the device and then stopped the worker. No job could
outlive the device, because ClearPipelineLibraries waits for the
device's jobs to finish, but that was only visible inside the wait.

The worker now stops first: a running job finishes, queued jobs are
dropped, and no job runs once the device's teardown starts.
agc_driver_draw_cache_reuse checks that the driver's own shutdown
leaves no library worker running.
2026-10-15 18:02:44 -07:00
hamb3r 026e69fa60 test(agc): cover arrayed multisample runtime views and GPU fetches 2026-10-16 03:53:53 +03:00
hamb3r 729558cc66 fix(agc): bind array image views for Image2DMultisampleArray descriptors 2026-10-16 03:53:34 +03:00
Yunus Shaikh e986ee0f7a fix(agc): leave the rect-list pairs a pipeline ABI cannot build to their first draw
sceAgcLinkShaders resolves the rect-list pairing of a pipeline when the
title creates it, and three cases ended the title there although the
rect-list draw that uses the pipeline builds its pair itself:

- a pipeline without a pixel shader reached ResolveGraphicsAbi with a
  null pixel, which required both stages, although the draw pairs the
  front stage with the null pixel program;
- a stage with no artifact yet, such as a pixel shader that exports
  stencil on a device without VK_EXT_shader_stencil_export, failed the
  missing stage artifacts check;
- a pair that BuildRectListShaders refuses, such as a pixel input with
  passthrough interpolation, threw from the builder.

The ABI now skips the first two, and logs the third once as a deferral
of the pixel shader without recording the pair, so the pair's draw
builds it again and fails with the builder's reason. When a draw builds
the rectangles of its front stage, only the pair of its own fragment can
fail it; the pair of another fragment that has no artifact or that the
builder refuses is left to that fragment's draw.

A new mode resolves a front stage with a null pixel, with a pixel before
it has an artifact, with a pixel that never gets one and with the first
pixel's passthrough variant, and expects one deferral with the
builder's reason. It then draws the front stage as a rect list with the
null pixel program, which succeeds although the other two pairs cannot
be built, and with the passthrough pixel, which fails with the
builder's reason.
2026-10-16 00:48:18 +00:00
Yunus Shaikh 502085c15c fix(agc): leave a pipeline ABI stage whose vertex inputs do not decode to its first use
PrepareGraphicsStages decodes each front-end stage's vertex inputs from
its AGC header before it prepares the stage, outside the catch that
defers a stage the recompiler cannot prepare. A header the decode
refuses, such as a semantic with a statically bound vertex buffer,
threw out of sceAgcDriverResolveGraphicsStagesAbi and ended a title that
creates its pipelines ahead of drawing. Registration leaves such a stage
alone when it is an NGG vertex shader that uses its workgroup, or a
mesh, hull or domain stage, so the pipeline ABI is the first to decode
it.

A decode failure now defers the stage the same way a preparation
failure does. The draw that uses it decodes the same header with the
draw's own user data and fails there with the same reason.

A new mode registers an NGG vertex shader with vertex buffer and
attribute tables and one statically bound semantic, resolves its
pipeline ABI twice inside a scope, and expects one deferral with the
decode's reason and no front-end build, then the same reason from its
first draw.
2026-10-16 00:40:03 +00:00
Yunus Shaikh 19a3e07106 fix(agc): leave a stage whose registration preparation failed to its first use
A failure stored by a shader's background registration preparation was
rethrown by every pipeline ABI call that touched the stage. The
ShaderPreparationScope that sceAgcLinkShaders, sceAgcCreatePrimState and
sceAgcCreateInterpolantMapping open settled the stages and threw first,
and ResolveShaderAbi, ResolveGraphicsStagesAbi and ResolveGraphicsAbi
threw it again from their reads of the stage. A title that creates its
pipelines ahead of drawing ended there, although the draw or dispatch
that uses the stage rethrows the same stored failure.

Settling a scope no longer rethrows. Each ABI call logs such a stage
once with its stored reason, marks it deferred and prepares the other
stages of the call as before. ResolveGraphicsStagesAbi keeps its ABI
record on the first stage that did not fail, PrepareGraphicsStages skips
a failed program, and ResolvePreparedGraphics records no rectangle for
a failed stage and never adds a failed fragment to a front stage, where
the rectangle draw of another fragment would meet it.

The compute mode no longer expects the stored failure from the ABI call.
A new mode registers a compute, a pixel and a vertex shader whose
registration preparation fails, resolves them through every ABI entry
point inside a scope twice, and expects three deferrals with the stored
reason the first time and none the second, then the stored reason from
the compute shader's dispatch.
2026-10-16 00:26:43 +00:00
Yunus Shaikh 48c17f97dd test(agc): plan a heap again once its mirror's range has left the write watch
agc_heap_mirror_unwatch registers a 2 MiB heap, a 1 MiB idle range and a
64 KiB busy range, imports the idle and busy ranges and sets the import
budget so the heap's import is refused: the first address-based build
mirrors the heap. One 64 KiB block of the heap then leaves the write
watch and the CPU stores new bytes there, so the second build must drop
the mirror and serve the new bytes, here from a copy.
agc_heap_mirror_unwatch_no_space_cache runs the same without the
address-space cache.

agc_heap_mirror_unwatched_import takes the heap off the watch through a
host import instead: once the budget holds the heap, an import that does
not keep the watch (ImportWatch::Unwatch) covers it, and the next build
must take that import instead of the cached space's mirror. It is not
registered on Windows, where an import of private memory may keep the
watch through a shared alias or a settle, which the mock does not model.

Without the fix each one throws "a heap mirror's range is no longer
write-watched": the first and third from the cached space's heap runs,
the second from the build's own heap refresh.
2026-10-15 17:18:48 -07:00
MarcZX100 680095be7a test(agc): set DLL path for descriptor cache test 2026-10-16 00:04:17 +00:00
Ishmam Ahmed 0ea7055c21 fix(libSceZlib): report a truncated stream as fatal when the output is full
inflate returns Z_BUF_ERROR both when the output is full and when the
input ends early. sceZlibInflate treated every Z_BUF_ERROR with no
output space left as insufficient output, so a stream cut off after
its last data byte, such as one missing its Adler-32 trailer, reported
0x8112001C when the output capacity equalled its decoded length, and
0x811200FF with any larger buffer. Report insufficient output only
while input remains, as zlib's uncompress2 and miniz's mz_uncompress2
do and as the technical debt entry describes.
2026-10-16 01:02:41 +01:00
hamb3r a7b8a697de fix(libc): align steady_clock source on macOS in PreciseWait 2026-10-16 02:56:01 +03:00
hamb3r b155e1d0eb test(shader,agc): cover Image2DMultisampleArray descriptor binding and dimension check 2026-10-16 02:51:04 +03:00
hamb3r 90896ff0ce fix(agc): handle Image2DMultisampleArray in GuestTextureResource 2026-10-16 02:45:36 +03:00
hamb3r b88f97ae41 fix(shader): map multisampled array images in DescriptorBindingBuilder 2026-10-16 02:45:12 +03:00
hamb3r 893b48208a feat(shader): add Image2DMultisampleArray to DescriptorImageShape 2026-10-16 02:44:55 +03:00
Eli Yarson d70e9fb6c8 test(libc): skip the failed heap commit check when the host overcommits 2026-10-15 20:30:18 -03:00
hamb3r 78ce0b8361 test(libc): cover zero-epoch and coarse steady_clock deadlines in PreciseWait 2026-10-16 02:13:39 +03:00
hamb3r c07d26ea34 perf(libc): add POSIX steady_clock fast path in PreciseSleepUntil 2026-10-16 02:13:14 +03:00
hamb3r 56ce6a5079 perf(libc): add Windows 10 MHz steady_clock fast path in PreciseSleepUntil 2026-10-16 02:12:42 +03:00
hamb3r b4bc6ebc3e refactor(libc): extract PreciseQpcFrequency helper in PreciseWait 2026-10-16 02:12:11 +03:00
Hashaam ZafarandClaude Opus 5.5 75f5beffa0 fix(agc): present EOP flips when draws are pipelined
With the queue-0 draw pipeline on, the default since #1202, the packet
loop hands every label-writing packet to the pipeline and skips the rest
of the loop. A RELEASE_MEM that completes a reserved EOP flip
(sceVideoOutSubmitEopFlip, #5539) is a label write, so its label landed
but the flip branch never ran: the reservation was consumed and the flip
never presented. video_out_flip_eop and video_out_flip_eop_main failed
and video_out_flip_eop_aftergpu timed out.

Keep packets that carry a reserved flip out of the pipeline. They take
the normal path, which drains the pipeline before the flip as it does
for flip packets.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 16:07:18 -07:00
Get-fix a9fa0e8b08 fix(relinker): ignore unwind records that cover no code
An FDE whose address range is 0 describes no instructions, and an
unwinder never matches a pc in it. The exception-table reader rejected
it with "inconsistent FDE function range", which stopped the
conversion of Limbo (CUSA01664): one of its 17328 FDEs covers 0 bytes
at 0x47dd0, where the next record starts. Such a record is now read
and left out of the function list.
2026-10-16 02:05:40 +03:00
MarcZX100 0627bc6bde fix(agc): free released lavapipe descriptor sets 2026-10-15 23:02:19 +00:00
Yunus Shaikh 661d3cba8d test(agc): defer the stage of a pipeline ABI whose geometry state does not decode
A fifth ABI deferral mode, abi_deferred_undecodable_state. A vertex
shader whose specials route it through geometry (VGT_SHADER_STAGES_EN
0x2030), which registration leaves alone, is resolved through
ResolveGraphicsStagesAbi with the context and primitive registers that
sceAgcCreatePrimState passes for it. DecodeShaderStages refuses its
VGT_GS_OUT_PRIM_TYPE of 1.

The call must not throw and must log the stage once with the decode's
reason, and a second call must neither prepare nor log it again. A draw
that routes the stage through the vertex path then prepares it at its
first use without reporting it as missing a registration artifact.
2026-10-15 22:47:49 +00:00
GalaxyGamingFRandClaude Opus 5.5 78ede8c3b9 fix(relinker): keep imports reached by indexing a live table base
A lea of a table base recorded only the exact base address as address-taken, so import slots after it in a function-pointer or vtable table were treated as dead. unused-filter=2 then stripped those NIDs and indexed calls hit unbound slots. The base walk now marks every consecutive import slot or relocated pointer starting at the base.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 15:31:22 -07:00
Kovalev Vladislav 925f9a84b0 fix(agc): resolve sparse indirect index ranges per record 2026-10-16 04:27:23 +06:00
Kovalev Vladislav ee49195b4e test(agc): reproduce sparse indirect index ranges 2026-10-16 04:27:23 +06:00
Yuri Olive b27e4c9710 feat(libScePad): export missing firmware pad interfaces 2026-10-15 19:24:39 -03:00
MarcZX100andAdam Franke 083f1cc9d8 test(libkernel): drop backup privileges in denied parent watch
An elevated Windows process can bypass the parent directory DACL while holding SeBackupPrivilege or SeRestorePrivilege. Remove both privileges before DeniedParentWatch so the test exercises the denied-open path reliably.

Co-Authored-By: Adam Franke <[email protected]>
2026-10-15 22:24:04 +00:00
Yunus Shaikh 6bd8647c27 fix(agc): leave the stages of a pipeline ABI whose state does not decode to their first use
A title's graphics pipeline ABI call decodes the stage routing and programs
from the registered state and the call's own context and primitive
registers. When that decode refused the state, the exception left the
call and ended the title, although the draws that later use the stages
decode their own state.

The decode failure now defers every stage of the call the same way a
stage whose preparation fails is deferred: each is prepared when a draw
uses it.
2026-10-15 15:22:38 -07:00
Yunus Shaikh fae2221c47 Merge #6537's head into perf/shader-image-table-reuse-v3-pr
Keeps each set's image table writes in its own draw snapshot set, which 007 First Light reaches with this branch.
2026-10-15 15:17:15 -07:00
Mehran 5234ab2f4a perf(agc): rule out pending write overlaps from the published union 2026-10-16 01:11:18 +03:00
Yunus Shaikh 0ba4f056cd fix(agc): stop and join the compare helpers and the pipeline library worker at shutdown
Two more detached driver threads were never stopped: the helpers of the
parallel compare pool, started at the first large compare, and the
pipeline library's job thread, started at the first link-time optimized
pipeline. A process that exited right after starting them killed them
inside the first waits that take winpthreads' global condition-variable
lock, as with the preparation workers.

The driver's shutdown now stops both and joins them, after the device
is reset. A compare in progress finishes first and later compares run
on the caller. The library worker finishes the job it is running, the
jobs still queued are dropped and counted off their device, and later
pipelines are not optimized in the background.
2026-10-15 15:09:33 -07:00
Yunus Shaikh afb1d0aad8 fix(agc): join the shader preparation workers when their pool closes
Closing a preparation pool waited until its queue was empty, but its
detached workers stayed parked on the queue until ExitProcess killed
them. A pool first used shortly before shutdown still had workers
starting at exit, inside the first waits that take winpthreads' global
condition-variable lock, which the next DLL-detach destructor of an
unwaited static condition variable then waits for forever.

The workers are now joinable and leave once their pool is closed and
idle, and Close joins them, so after the driver's shutdown no
preparation worker is running or starting.
2026-10-15 15:05:12 -07:00
Yunus Shaikh 0365a367f9 fix(agc): close only the shader preparation pools that exist at shutdown
CloseRegistrationPreparation took RegistrationPreparePool::Instance(),
which creates the pool and starts its detached workers (half the
hardware threads, at least two) when nothing was queued for preparation
yet. In a process that prepared nothing in the background, the driver's
shutdown started the workers only to close the pool, and the process
exited while they were still starting. Their first waits take the
global lock of winpthreads' statically initialized condition variables;
ExitProcess killed them holding it, and the destructor of the next
static condition variable that was never waited on spun on it forever
at DLL detach (~DeviceUseGate in ~Driver, or one of libkernel's). On
GitHub's Windows runners agc_interpolant_mapping hung that way in 15 of
60 rounds of eight test runs.

Shutdown now closes only the pools that exist, and a pool first used
after it starts no workers, so later preparations run on the caller as
they did on a closed pool.
2026-10-15 15:04:17 -07:00
Adrià 5d9dcc42d2 Merge pull request #6372 from AlxcBTW/perf/pipeline-cache-once
perf(agc): load the pipeline cache file only on the windowed device and save without re-reading an unchanged file
2026-10-15 23:58:29 +02:00
Adrià 7b20318e89 Merge pull request #5882 from billythemenace2/fix/agc-msaa-target-without-msaa-enable
fix(agc): rasterize a multisampled target without MSAA_ENABLE at the pixel center
2026-10-15 23:58:24 +02:00
Felipe Arce 46d49131e7 feat(libkernel): support EVFILT_READ on the read end of a pipe
kevent threw for any descriptor that is not a guest socket. The read end
of a pipe now gets the descriptor knote, following FreeBSD 11's
filt_piperead: data is the number of buffered bytes and EV_EOF is set
once the write end is closed. GuestSockets::Ready falls back to the new
PipeReadState for a descriptor that is not a socket, and WaitAny waits on
the pipe with ppoll on Linux or in 1 ms WSAPoll slices on Windows, only
when the queue holds a pipe. On Windows the equeue waker now starts
Winsock itself, since a queue can wait on a pipe before any socket exists.
2026-10-15 21:56:19 +00:00
Yuri Olive 51e9e5e825 feat(libSceRtc): implement the remaining firmware exports 2026-10-15 18:54:39 -03:00