Commit Graph
14017 Commits
Author SHA1 Message Date
Yunus Shaikh 9c308c739b fix(agc): drop the expand import requester that no path uses
Expand named a DB expand's store, but nothing passes it: main has no DB
expand, and the open DB expand change stores its planes only where host
imports already hold them, through HostImportOverlaps and the storage
write-back, without making or retiring an import. The requester could
never count, so the shutdown line always ended with expand 0/0/0.

agc_driver_graphics checks the requester names and the shutdown report
without it.
2026-10-15 11:45:59 -07:00
AlxcBTW e44ab157e0 docs: describe the log queue, its flush points and the stream order in ARCHITECTURE.md
The logger thread, the bounded queue that blocks its caller, the LogSink
hook, APS5_LOG_SYNC and APS5_LOG_STATS, where the queue is flushed and
what stays outside it: direct fprintf(stderr) and printf calls are written
at once, so they can appear before older queued lines.
2026-10-15 20:42:16 +02:00
AlxcBTW b82d688ed8 fix(agc): flush the log queue, bounded, where the process ends without exit handlers
Lines queued behind the logger were lost when the process ended through
abort(), std::terminate, the Windows crash report or a guest _Exit,
because only driver failure, Driver::stop and a normal exit flushed the
queue.

libc keeps one end flush (LibcSetEndFlush_nid_no_patch) and runs it from
those paths. Its first registration chains a SIGABRT handler in front of
the previous one, so every abort() and std::terminate in the process is
covered, on Linux as well; with the default disposition the handler
restores it and raises again, so raise(SIGABRT) still ends the process.
Guest abort() and _Exit, and ReportCrash for the first fatal exception,
run the flush directly. AsyncLog registers a bounded flush (FlushFor, 2 s)
that polls two counters and takes no lock, so a dying process cannot hang
on a blocked stream or on the queue lock; after its first timeout it
returns at once. Flush counts queued and finished entries instead of
watching the queue and the writer flag, so it waits for the lines queued
before the call and not for a moment in which no thread is logging.

agc_async_log_fatal runs the test executable as a child that queues lines
behind a held stream and ends in abort(), std::terminate(), raise(SIGABRT)
(POSIX) or an access violation (Windows), and once more with the stream
never released. The lines of the first four must arrive in order, the last
child must end after the bound, and every child has a watchdog.
agc_async_log gains the bounded flush case.
2026-10-15 20:42:16 +02:00
AlxcBTW 99ada24cc5 test(agc): Flush waits for a held stream and a full queue blocks the caller
Flush must not return while the logger still waits for a stream that
another thread holds (the regression reported on the pull request: it gave
up after two seconds), and a full queue must block its caller instead of
dropping a line. AsyncLog::Capacity becomes public so the test sizes its
load from it.
2026-10-15 20:42:16 +02:00
AlxcBTW 4e26472603 fix(agc): Flush waits until the logger has written every queued line 2026-10-15 20:42:16 +02:00
AlxcBTW ad85ed13ac perf(agc): format and write steady-state log lines off the queue worker
Texture creation logged one stdout line per texture and per mip through
WriteLogLine, which formatted with the mingw printf and flushed every
line on the queue worker (about 786k lines in a 25 minute cave run).

AsyncLog keeps a bounded queue and a logger thread. AGC_LOG_DEFERRED
captures numeric arguments on the caller and formats them on the logger
thread; WriteLogLine hands finished lines to a per-module sink in
libc/LogMacros.hpp that AgcDriver installs, so all AgcDriver stdout
lines keep their order and are written one flush per batch. A full queue
blocks the caller, so no line is dropped. Flush runs on driver failure,
shutdown and at exit. APS5_LOG_SYNC=1 restores the synchronous path.

Identical "deferred write-back failed" notes are printed three times per
10 s and then counted into one "repeated N more times" line. A
"[log] 10 s" line reports lines, bytes, caller time and logger time
(APS5_LOG_STATS=0 hides it).
2026-10-15 20:42:16 +02:00
javierUDP 6f100d3f61 test(relinker): execute the AMD64-only conversion stubs on macOS
The execution part of the AMD64-only converter tests was compiled for
Linux x86-64 only, so the SSE4A, SHA-1, SHA-256, CLZERO and reciprocal
stubs were never run on a macOS x86-64 build, unlike the ANDN lowering
tests. Rosetta maps no memory below 4 GiB, so the CLZERO case that needs
a 32-bit address is left out when that mapping is unavailable.
2026-10-15 15:40:26 -03:00
Mehran 09f574989e fix(agc): record a multisampled target's commands on its own device 2026-10-15 21:37:57 +03:00
Codex ced0305455 fix(libkernel): return EINVAL for invalid mutex priority attributes 2026-10-15 21:34:35 +03:00
Adrià 44df216321 Merge pull request #5834 from xXPBSXx/fix/agc-register-default-owner-v2
fix(libSceAgcDriver): return 0 from sceAgcDriverRegisterDefaultOwner
2026-10-15 20:34:25 +02:00
Adrià e6134fd0d9 Merge pull request #5827 from hamb3r/perf/precise-wait-spin-tail
perf(libc): add sub-tick spin tail to PreciseSleepUs and PreciseSleepUntil
2026-10-15 20:34:20 +02:00
Adrià 048e61b897 Merge pull request #5815 from EagleBearerYS/fix/agc-space-owner-overlap
fix(agc): bind a read-only V# over the cached address space through the region that holds it
2026-10-15 20:34:16 +02:00
Adrià 15a60e1455 Merge pull request #5762 from AlexOfTheForest/fix/rosetta-legacy-compare
fix(relinker): move legacy CMPSS and CMPSD out of line for Rosetta
2026-10-15 20:34:12 +02:00
Adrià dee15e2ec6 Merge pull request #5810 from mohammad-alosta/fix/libSceNgs2-listener-transform
fix(libSceNgs2): support listener transforms in sceNgs2GeomCalcListener
2026-10-15 20:34:07 +02:00
MrMha 4c64d39af5 fix: escape phase names in trace interval tables 2026-10-15 22:33:01 +04:00
Adrià c503db8d87 Merge pull request #5800 from fdfawef324/codex/frame-dump-io-best-effort
fix(agc): disable optional BMP dumps after host I/O failures
2026-10-15 20:32:15 +02:00
Anthony 2b567cda34 fix(libc): count wide collate string elements 2026-10-15 15:30:40 -03:00
ArjenS-LA 725ad5649c feat(libc): implement getopt_long_only 2026-10-15 11:27:50 -07:00
ArjenS-LA af691b717a feat(libc): implement overlap-safe bcopy 2026-10-15 11:27:49 -07:00
Sam c8bedff055 test(agc): check that lazy registration defers preparation
The lazy mode of agc_driver_prepared_shaders only checked dispatch output and failure reporting, which eager preparation also produces. Read the registered snapshot through Driver::RegisteredShaders: registration leaves it deferred with no prepared artifact, and the first dispatch prepares it.
2026-10-15 19:26:59 +01:00
Sam 96070188b9 perf(agc): allow shader preparation on first use
APS5_LAZY_SHADER_PREPARE=1 keeps registration validation and decoding but skips queueing the preparation. Draws and dispatches prepare a deferred snapshot on first use and cache it; explicit ABI resolution still prepares its stages. Titles that register thousands of shaders at boot no longer hold every prepared shader in memory before the first frame.

Cover lazy dispatch, metadata and failure cases in both asynchronous and synchronous modes.
2026-10-15 19:26:20 +01:00
MrMha 0be11ff1a3 fix: keep release-note alias tests compatible with Python 3.9 2026-10-15 22:20:53 +04:00
Adrià b7cedd900d Merge pull request #5803 from YossiYad/fix/videodec2-avc-parameter-sets
fix(libSceVideodec2): hold an AVC unit of parameter sets for the next slice
2026-10-15 20:18:10 +02:00
JJenkx 4c2b12439f fix(audio-propagation): preserve existing destination mixes 2026-10-15 14:17:17 -04:00
ee6aba54 d6fe6551b2 fix(agc-driver): keep storage images with pending results out of the memory release
Storing a storage image's pending results needs a staging buffer, and under memory pressure that buffer comes from the heap whose allocation just failed. The release turned to dirty images once the clean ones did not cover the request, so with the device and shared heaps full it failed on a 4 MiB write-back buffer at every call (PPSA26344 on Windows). StorageTexture::Flush clears the pending state before it stores, so each failed store also dropped that image's results. The release now takes only sampled entries and storage images without pending results, and its line reports how many images with pending results it kept.
2026-10-15 20:13:28 +02:00
AlxcBTW c0588d2747 fix(agc): write copied buffers back before reporting an unaligned BDA access
WriteBackBuffers threw the fault before guestMemory.WriteBack(), so a
dispatch that recorded an unaligned BDA access lost the stores of its
other invocations, although the shader only skips that access. The
write-back now happens first and the report follows. A fault of any
other kind still fails the command before anything is published.
2026-10-15 20:06:02 +02:00
AlxcBTW 0f0197c16d fix(agc): rate-limit the deferred report of an unaligned BDA access
A shader that records an unaligned BDA access on every dispatch formatted
and printed one line per completion. CheckFault now throws
BdaUnalignedAccess for that fault, and the recorder prints the first 8
deferred reports of it whole, then every 1024th with the count. Every
other deferred failure is still printed each time.
2026-10-15 20:02:38 +02:00
Get-fix 8c34587598 fix(relinker): search libc.prx for libkernel-only Windows executables
AnyPS5 exports some libkernel functions, such as __error, from
libc.prx, which libkernel.prx links. On Linux they resolve through that
dependency. On Windows, the import stubs search only the listed
modules, and libc.prx was listed only when libSceLibcInternal.prx was
needed. A PS4 homebrew that needs libkernel.prx but no C library (the
OpenOrbis graphics sample) failed with "unresolved ELF import
9BcDykPmo1I". libc.prx is now also listed when libkernel.prx is needed.
PS5 executables need libSceLibcInternal.prx and convert unchanged.
2026-10-15 21:02:31 +03:00
Yunus Shaikh f036140f3a Merge branch 'perf/agc-host-import-aligned-blocks' into perf/agc-host-import-blocks 2026-10-15 10:57:55 -07:00
Yunus Shaikh 57ceb9e370 fix(agc): keep the guest's sample order where pixel (0,0)'s locations stand in for a 2x2 grid
Village's 2x checkerboard puts its two samples at x = +4/16 and -4/16
and swaps their indices on odd rows. On a device without a 2x2 sample
location grid every pixel takes pixel (0,0)'s locations, so the odd
rows hold the console's sample 1 in sample 0 and the reverse: a pass
that reads the samples by index, as checkerboard reconstruction does,
exchanges the two half-pixels of every odd row, and SampleID, sample
masks and exported coverage name the wrong samples there.

Such a pattern holds one set of positions in every pixel, so drawing
with pixel (0,0)'s locations is exact up to the order of each pixel's
samples. The draw now keeps the guest's order: the pixel shader reads
SampleID, applies the sample mask and exports coverage through each
pixel's order, and every render pass drawing with the stand-in puts the
samples of its multisampled attachments in the stand-in's order before
it and back in the guest's after it. Color targets do that through a
storage view of their texels as unsigned integers, depth through a copy
and a per-sample pass writing FragDepth, and stencil through
VK_EXT_shader_stencil_export or one pass per bit.

It needs shaderStorageImageMultisample with a storage view of the color
format, sampleRateShading, and a depth format FragDepth writes back
exactly (16-bit or 32-bit float); otherwise, and for patterns whose
pixels hold different positions, the stand-in alone is used, and the
log line says why. Devices with the grid are unchanged.

Recompile requests carry the order as serialization version 32 (#6470
takes 31), and the shader cache format becomes 40 (open pull requests
take 37 and 39).
2026-10-15 17:53:11 +00:00
RickandClaude Opus 5.5 6c5686d7ea feat(libSceImeDialog): take the dialog's text from the host keyboard
sceImeDialogInit wrote "Slayer" into an empty text buffer and the
dialog finished on the second status poll, so a title never got text
from the user: ProsperoRadio's search typed "Slayer" by itself and
found no station.

The dialog now runs until the user answers on the host keyboard, the
way #4756 made sceImeOpen's panel-less IME take it. While no IME panel
is open, libSceIme hands the game window's text and editing keys to
a sink that the dialog registers. Typing edits the text up to
maxTextLength without splitting a surrogate pair, Enter writes it to
the title's buffer and finishes with end status 0, and Escape finishes
with 1. Abort still finishes with 2. A second Init reports busy, and a
null parameter or buffer or a maximum length outside 1 to 2048 is
refused, as in shadPS4.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-10-15 19:52:28 +02:00
winstrexandClaude Opus 5.5 f81fb317dd perf(agc): match the dword pattern-fill kernel with its two compares in either order
MatchDwordPatternFill took the 69-word pattern-fill kernel only word for
word. Hades (PPSA03355) runs the same kernel with words 27 to 29 in the
other order: the SDWA v_cmp that writes s12 (0x7d8c02f9 0x06068c02)
comes before the v_cmp that writes vcc_lo (0x7d860609). Neither compare
reads what the other writes, so both orders compute the same fill.
The matcher now takes either order; every other word and every
user-data and packet condition is unchanged.

The test runs both orders through the matcher and through Submit, flips
each word of the swapped kernel, refuses the other orders of those three
words, and is registered a second time with
APS5_NO_FILL_HLE=1 so the translated kernel must give the same bytes.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 14:40:16 -03:00
Yunus Shaikh b8a33ab7ff test(agc): register the write-back block test apart from the split write-back test
Its registration and its command-line option followed the split write-back test's, where another open pull request adds its own. They now follow the copied-direct ordering and CMASK tests. No test changes.
2026-10-15 10:36:21 -07:00
Ondra97 1fee29b6ad fix(libSceNet): inherit nonblocking mode on accepted sockets 2026-10-15 19:29:41 +02:00
Yunus Shaikh 3ba5574dc4 Merge upstream main into perf/shader-image-table-reuse-v3-pr 2026-10-15 10:29:25 -07:00
Alex ColliniandClaude Opus 5.5 349420af7f docs(agc): record the measured effect of dropping entries with released textures
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 19:28:43 +02:00
Zinebyte 5c378ece37 fix(relinker): preserve weak imports in macOS guest modules 2026-10-15 13:25:46 -04:00
Adrià 03c4cb5e78 Merge pull request #5791 from Ondra97/codex/fix-draw-mesh-index-cache
fix(agc): validate mesh index descriptors on cached draws
2026-10-15 19:25:11 +02:00
Adrià 3bb409b603 Merge pull request #5784 from gguerra26/fix/macos-m1-andn
fix(relinker): lower ANDN in Rosetta conversion
2026-10-15 19:25:06 +02:00
notaxeltvandCursor 511db2e8ff feat(libc): export locale::classic for the C locale
Absent PPSA34015 import; return a stable facade over the classic _Locimp.

Co-authored-by: Cursor <[email protected]>
2026-10-15 18:57:39 +02:00
Alex ColliniandClaude Opus 5.5 49919d7f32 fix(agc): drop resource-cache entries that hold released sampled textures
A resource-cache entry keeps every sampled texture of its descriptor sets alive. The sampled texture cache passes over textures something else holds and, past its ceiling, drops them anyway; textures it makes without caching are never in it. Entries holding either kept them alive with no budget counting them, bounded only by the 1,024-entry and 65,536-element counts, until device memory ran out.

The texture cache now marks such textures released. ResourceCache::Insert refuses descriptor sets holding one and hands the entries that hold one back to the caller, like RemoveImage does for evicted storage images.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 18:56:30 +02:00
milescovielloandClaude Opus 5.5 92f170c673 fix(agc): treat a view past a depth surface's first level as memory
A depth surface is one level: the driver rejects draws that render a
depth mip. A sampled or storage view at the surface's address and extent
that starts at a later level, or a storage access to a later level, does
not touch that level, so it is not the depth plane. DepthSurfaceTexture
and DepthSurfaceStorage still sent such views to the surface, which
rejected the level. Forspoken (PPSA03984) builds a depth pyramid from its
1984x1116 D32 depth surface with a compute shader that samples one level
of a five-level R32F view and stores the next, and stopped there.

Both now leave such views to the texture and storage caches, as they
already do for a view of another extent or format.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 16:55:31 +00:00
milescovielloandClaude Opus 5.5 4cdd2f4834 fix(agc): accept a copy's sample selection on a draw that copies nothing
DB_RENDER_CONTROL.COPY_CENTROID and COPY_SAMPLE select the sample that
DEPTH_COPY or STENCIL_COPY copies. Forspoken (PPSA03984) draws with
DB_RENDER_CONTROL 0xc0, DEPTH_COMPRESS_DISABLE and COPY_CENTROID with
neither copy bit set, and stopped at 43 s because both
DepthMaintenanceRejection and decodeDepth took the selection for a copy.

Accept the selection fields when no copy is enabled; draws that copy are
still rejected.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 16:54:42 +00:00
Adrià fa9365ca74 Merge pull request #5781 from moong15/fix/agc-sample-stencil-as-unorm
fix(agc): sample a depth surface's stencil plane through an R8_UNORM view
2026-10-15 18:50:41 +02:00
Adrià 2cefed5499 Merge pull request #5778 from meh7an/fix/agc-buffer-range-limit-by-mapped-memory
fix(agc): bind a V# past the range limit by the memory behind it
2026-10-15 18:50:36 +02:00
Adrià e2bcee655d Merge pull request #5776 from simonbronk/fix/convert-keycode-state-bit
fix(libSceConvertKeycode): ignore the state bit 0x4000000 RE Engine titles pass
2026-10-15 18:50:01 +02:00
billybobpicklioandClaude Opus 5.5 9800f3ab92 fix(agc): keep each set's image table writes in its own draw snapshot set
The vertex and fragment image tables both sit at ImageTableBinding, in
sets 0 and 1. PrepareDrawBindings matched the recorded writes to their
bindings by binding number alone, so the set 0 table also took the
fragment table's writes: they went into the snapshot's set 0, past its
variable descriptor count and into the next set in the pool, and the
snapshot's set 1 table was left unwritten.

Match a write by its original set as well. The recorder test device now
enables the descriptor indexing features image tables need.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 12:49:59 -04:00
Yunus Shaikh 98c72e9f83 perf(agc): take the host import budget from the device's memory budget
Imports were held to a configured budget only. With APS5_HOST_IMPORT_MIB
at 6864 on a 15.4 GB PC, Village's imports reached the NVIDIA driver's
pinning ceiling of about 6.56 GiB, and from there every import was tried
and failed at vkAllocateMemory, 992 times.

Where the device enables VK_EXT_memory_budget, the budget is now also at
most the host heap's reported budget less its other usage and an eighth,
in 64 MiB steps, read at most once a second. A vkAllocateMemory failure
within an eighth of the budget, or the third in a row, lowers the budget
to the live imports, so later imports are refused or evict instead of
failing; an isolated failure further below only marks its range failed,
as before. A remembered refusal stays remembered while the budget does
not grow.
2026-10-15 09:49:04 -07:00
Yunus Shaikh 7f7d4064c8 refactor(agc): place the image table reuse's includes and shared resolution declaration apart from neighbouring edits
Moves a few include lines and the ResolveImageTablesShared declaration by a line or two, so they no longer share an insertion point with other open pull requests. No behaviour change.
2026-10-15 09:45:11 -07:00
Yunus Shaikh 4fc7af779a test(agc): register the image table reuse tests in one block
The snapshot reuse test joined the shared Windows PATH list and the vouch tests sat after the foreach, both lines that other open pull requests also change. All three now register together, with their own Windows PATH setting.
2026-10-15 09:45:11 -07:00