Commit Graph
14017 Commits
Author SHA1 Message Date
fma-rc d6f67d1be2 fix(agc): keep fused geometry programs out of the caller's memory
sceAgcFuseShaderHalves copied both halves' code, the fused header and its
tables into the caller's memory and registered the program at that
address. PPSA02100 fuses different halves into the same memory a few
calls apart, while draws that use the earlier result are still queued.
The registry keeps one program per code address, so those draws were
compiled from the later program: its code read a user-data word the
bound layout does not have, and the device reported "BDA access failed"
for the mesh stage.

The PS5 5.02 module writes only the back half's register list into that
memory (sceAgcGetFusedShaderSize reports eight bytes per register,
alignment 4) and leaves the code where the halves are.

The fused code, header and tables now live in memory libSceAgc owns, one
program per distinct pair of halves, registered once. The caller's
memory receives the fused register list and the size query reports that
list. A second fusion of the same halves returns the same program; halves
whose contents changed get a new one.

The driver looked a header up by comparing its fields with the
registered header, including the register list's address. A header whose
register list is a copy elsewhere with the same contents now matches
too, which is what the title passes after a fusion.
2026-10-14 02:08:21 +02:00
Kikoarl 3ebad9045e perf(agc): expand draw recipes to support depth targets 2026-10-14 02:00:40 +02:00
alosta a0bd257a09 feat(libc): implement swprintf_s
Add the missing wide secure formatting exports required by PPSA15552
(Dead Cells), whose load failed with `undefined symbol: Im55VJ-Bekc`:
swprintf_s and its va_list counterpart follow C11 Annex K.3.9.1.4
(the complete output, including the terminator, must fit), while
vsnwprintf_s is the va_list counterpart of snwprintf_s (K.3.9.1.3,
truncation with full length). The export names produce NIDs
Im55VJ-Bekc, oDoV9tyHTbA and 8SKVXgeK1wY respectively. Document
the new functions in docs/dev/debt/libc.md.
2026-10-14 00:59:50 +01:00
NikoandClaude Opus 5.5 4ba4ede2a9 fix(relinker): name missing and non-PE modules in Windows dependency diagnostics
When a relinked executable fails to load a staged module, the dependency
diagnostics routine maps the same path as an image resource to walk its
imports. If that mapping failed it printed only "FAIL: dependency
diagnostics Windows API failed". The log then did not say whether the
staged module itself (libs\libSceRegMgr.prx in #4720) was absent or was
not a Windows image, and a module reached through another module's
imports was not named at all.

The register routine now reads GetLastError when LoadLibraryExW fails.
ERROR_FILE_NOT_FOUND and ERROR_PATH_NOT_FOUND print "dependency module
not found", ERROR_BAD_EXE_FORMAT prints "dependency module is not a
Windows PE image"; both name the module path, its importer and the
chain from the executable, like the existing missing-module report.
Other errors keep the generic message. An API set contract that
LoadLibraryExA reports as ERROR_MOD_NOT_FOUND now gets the
missing-module report too.

Refs #4720

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 01:51:23 +02:00
David-cmrg 75c25e16f0 fix(tests): use position-independent unwind data in the C++ error fixture 2026-10-14 01:49:52 +02:00
JJenkx 2d14128a29 Merge remote-tracking branch 'origin/main' into fix/pad-command-file-access 2026-10-13 19:49:22 -04:00
JJenkx 665136f53e Merge remote-tracking branch 'origin/main' into feat/libc-isfinitel 2026-10-13 19:49:22 -04:00
JJenkx 859d815c5e Merge remote-tracking branch 'origin/main' into fix/guest-declared-host-import-registry 2026-10-13 19:49:22 -04:00
JJenkx e3a321ea11 Merge remote-tracking branch 'origin/main' into fix/ngs2-render-capacity 2026-10-13 19:49:21 -04:00
JJenkx 84e1dbf153 Merge remote-tracking branch 'origin/main' into feat/vp9-picture-info 2026-10-13 19:49:21 -04:00
JJenkx 957051602c Merge remote-tracking branch 'origin/main' into fix/audio-output-conversion-state 2026-10-13 19:49:21 -04:00
JJenkx 563743267d Merge remote-tracking branch 'origin/main' into fix/linux-guest-finalizer-arguments 2026-10-13 19:49:21 -04:00
JJenkx 73840e4f43 Merge remote-tracking branch 'origin/main' into feat/private-mutex-sharing 2026-10-13 19:49:21 -04:00
JJenkx 71d9fe4691 Merge remote-tracking branch 'origin/main' into feat/videoout-buffer-labels 2026-10-13 19:49:20 -04:00
MidnightApora 945b97094c fix(agc): accept 2D-array image loads and stores on 3D T#s
A 2D-array image_load or image_store bound to a 3D T# addresses the slice as z. Add a 3D runtime mode for these accesses and drop loads and stores whose slice is past the volume depth.
2026-10-13 18:44:22 -05:00
milescovielloandClaude Opus 5.5 cd1757e036 test(shader): check that a queried and sampled table T# is one image
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 23:42:15 +00:00
AlxcBTWandClaude Opus 5.5 7e00edae23 perf(agc): compare key components only when APS5_TRACE_RESOURCE_KEY_MISSES is set
The per-miss component comparison allocates and walks the whole key, and
it ran under APS5_PROFILE_DRAW as well, where it cost queue time on every
resource-content miss. It now runs only with the trace variable, which is
also the only one that prints its [keymiss] lines.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 01:36:25 +02:00
SamandClaude Opus 5.5 af2b869281 fix(shader): share delete access when reading cache entries on Windows
WriteFileAtomically renames its handle over the published entry and
closes it afterwards. A std::ifstream reader opened in that window fails
with ERROR_SHARING_VIOLATION, and the cache reports the entry as gone.
Read through one CreateFileW handle that shares read, write and delete.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 00:35:54 +01:00
Dean d1670009fb Merge pull request #5429 from Dripl1x/perf/windows-mutex-wake
perf(libkernel): wake guest mutex waiters on release on Windows
2026-10-14 12:31:24 +13:00
milescovielloandClaude Opus 5.5 e015772307 fix(shader): plan a table T# that several image operations share
TryMakeTableImage planned a T# read from a bindless image table only when
its eight scalar reads had no user other than that one GetImageResource.
Descriptor-phi splitting gives each image operation its own copy of the
T# over the same reads, so a table entry that is both queried and sampled
was refused, and GetHandle then rejected the scalar reads.

Accept reads whose every user is a GetImageResource built from exactly
those eight reads; each copy is planned as the same table.

Crimson Desert (PPSA25286) stops on such a shader at start-up:
image_get_resinfo and image_sample_lz on one s_buffer_load_dwordx8 T#.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 23:28:50 +00:00
Evgeniy KazarinandClaude Opus 5.5 99eaf73102 perf(libkernel): wake guest mutex waiters on release on Windows
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 02:18:33 +03:00
mariuszkreft 58120ca418 fix(relinker): place the Linux extra PT_LOAD past the last guest page
ComputeExtraBlockVaddr kept the ELF congruence p_vaddr == p_offset (mod 0x1000)
and bumped the result by one page only when it fell below the highest guest
load end as a byte address. When that end is not page aligned and the extra
block's file offset remainder reaches it, the extra RWX PT_LOAD landed in the
same 4 KiB page that holds the tail of the highest guest segment. The kernel
maps each PT_LOAD page by page with MAP_FIXED in program-header order, so the
extra block's file page replaced the guest's .data tail and zero-filled .bss
there.

Round the highest kept PT_LOAD end up to the page before adding the offset
remainder, which is the placement GuestModuleWriter::WriteLinux already uses
for the guest module. Only the overlapping case changes; an end that is page
aligned or a remainder below it yields the same address as before.

The extra PT_LOAD now also spans to the end of its own page in p_memsz, so the
page it takes over is fully covered, and its vaddr is derived in WriteLayout
instead of being taken from the request. The header block load carries the
same flags as before.
2026-10-14 01:17:49 +02:00
JJenkx 3873c15152 Merge commit '7a0c838ca485d59561518f118afc690baa5eb557' into fix/pad-command-file-access 2026-10-13 19:16:03 -04:00
JJenkx 40a9849f3a Merge commit '7a0c838ca485d59561518f118afc690baa5eb557' into feat/libc-isfinitel 2026-10-13 19:16:03 -04:00
JJenkx a6666689a2 Merge commit '7a0c838ca485d59561518f118afc690baa5eb557' into fix/guest-declared-host-import-registry 2026-10-13 19:16:03 -04:00
JJenkx 5c9bcc08b2 Merge commit '7a0c838ca485d59561518f118afc690baa5eb557' into feat/vp9-picture-info 2026-10-13 19:16:02 -04:00
JJenkx 945ef466f9 Merge commit '7a0c838ca485d59561518f118afc690baa5eb557' into fix/linux-guest-finalizer-arguments 2026-10-13 19:16:02 -04:00
JJenkx 4230dca6c8 Merge commit '7a0c838ca485d59561518f118afc690baa5eb557' into feat/private-mutex-sharing 2026-10-13 19:16:02 -04:00
JJenkx 633f5e9927 Merge commit '7a0c838ca485d59561518f118afc690baa5eb557' into fix/ngs2-render-capacity 2026-10-13 19:16:01 -04:00
JJenkx 12fddc7337 Merge commit '7a0c838ca485d59561518f118afc690baa5eb557' into fix/audio-output-conversion-state 2026-10-13 19:16:01 -04:00
JJenkx efb0b6401e Merge commit '7a0c838ca485d59561518f118afc690baa5eb557' into feat/videoout-buffer-labels 2026-10-13 19:16:01 -04:00
Adelmo Junior 12851ef037 docs: document flexible memory budget behavior 2026-10-13 20:13:14 -03:00
Adelmo Junior 72211b70fe fix(kernel): honor the declared flexible memory budget
Read the optional aligned budget from param.json and apply it consistently to configured, available and mapped flexible memory. Add parser and allocation regression coverage.
2026-10-13 20:13:14 -03:00
Dean 7a0c838ca4 Merge pull request #4875 from nikowolf123/perf/libc-write-watch-capacity
perf(libc): size each write-watch query to the region it covers
2026-10-14 12:12:10 +13:00
NikoandClaude Opus 5.5 07d4b36c50 test(recompiler): cover slow shared merge splitting and its growth budget
Structurize the 20-block graph whose merge splitting adds one forwarder
per round until its round budget runs out, and a 12-block loop whose
2000-word latch is too large to clone, so merge splitting keeps adding
junctions. Both must give structured branches, every original block once
and the same executions as the input.

Give the loop an unsupported exit, which keeps the reach-flag fallback
out, and require Structurize to report the growth budget refusal instead
of the round budget refusal it reached before after 676 blocks.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 01:00:21 +02:00
NikoandClaude Opus 5.5 2c53270b94 perf(recompiler): iterate structurizer fixpoints in post-order and bound shared merge splitting growth
The structurizer's attempts could spend more than 10 s on a graph of 20
blocks before they accepted or refused it; in a title that stalls shader
preparation. Nearly all of that time went to recomputing dominators and
post-dominator fixpoints while merge splitting grew the graph to
hundreds or thousands of blocks.

Dominators, post-dominators and the fixpoints in mergeBesideReturns,
iterationSelectionMerge and joinWithinIteration now sweep the blocks in
reverse post-order (dominators) or post-order (the others) instead of in
id order. Splitting appends its new blocks at the end, so id order needed
a sweep for almost every new block. Each fixpoint starts from the full
set and its equations are monotone, so every sweep order reaches the
same greatest fixed point and the result does not change.

Shared merge splitting also refuses an attempt once the graph has more
than 16 times its block count at the start of splitting (at least 64
blocks). Without it, splits that route through a new junction each round
grew some graphs past 4,000 blocks before the round budget ran out. A
refused attempt goes to the next attempt or to the reach-flag fallback,
as it does after the round budget.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 01:00:21 +02:00
JJenkx 78f661e6e6 Merge commit '30f961266ade83b41d5c9de7dec1393e7fcecfb7' into fix/pad-command-file-access 2026-10-13 18:59:59 -04:00
JJenkx aa16bfc632 Merge commit '30f961266ade83b41d5c9de7dec1393e7fcecfb7' into feat/libc-isfinitel 2026-10-13 18:59:59 -04:00
JJenkx 2f7b33521f Merge commit '30f961266ade83b41d5c9de7dec1393e7fcecfb7' into fix/guest-declared-host-import-registry 2026-10-13 18:59:59 -04:00
JJenkx 9bd29e4767 Merge commit '30f961266ade83b41d5c9de7dec1393e7fcecfb7' into feat/private-mutex-sharing 2026-10-13 18:59:59 -04:00
JJenkx 374f2cc6f1 Merge commit '30f961266ade83b41d5c9de7dec1393e7fcecfb7' into feat/vp9-picture-info 2026-10-13 18:59:58 -04:00
JJenkx 57a97f61c5 Merge commit '30f961266ade83b41d5c9de7dec1393e7fcecfb7' into fix/linux-guest-finalizer-arguments 2026-10-13 18:59:58 -04:00
JJenkx aaa34abc67 Merge commit '30f961266ade83b41d5c9de7dec1393e7fcecfb7' into fix/ngs2-render-capacity 2026-10-13 18:59:57 -04:00
JJenkx b9beb1fb1a Merge commit '30f961266ade83b41d5c9de7dec1393e7fcecfb7' into fix/audio-output-conversion-state 2026-10-13 18:59:57 -04:00
JJenkx fbe4f35e01 Merge commit '30f961266ade83b41d5c9de7dec1393e7fcecfb7' into feat/videoout-buffer-labels 2026-10-13 18:59:57 -04:00
NikoandClaude Opus 5.5 22c0c51730 test(recompiler): cover refused control flow and the forced structurizer fallback
Structurize eight graphs the ladder refuses on main (a duplicate merge, a
region that wraps around to its dominator, the merge-splitting budget, a
conditional without a structured merge, an irreducible entry and three
loops that never exit) and the #2642 two-latch loop, which the ladder
accepts. Each must give structured branches, every original block exactly
once and the same executions as the input for every branch decision.

Register agc_structurizer_forced_fallback and
agc_shader_control_flow_forced_fallback, which run the in-tree graphs and
RDNA programs, through Recompile and SPIR-V validation, with
APS5_FORCE_STRUCTURIZER_FALLBACK=1. Under that switch the split-kind
checks become checks that no block is cloned and a route variable is
used, and the nested-selection check names blocks by their original
instructions instead of their position.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 00:59:50 +02:00
NikoandClaude Opus 5.5 1c958de097 feat(recompiler): structurize refused control flow with reach flags
When every attempt of the structurizer ladder refuses a graph, the title
aborts. Rebuild such a graph from a hierarchical decomposition into
strongly connected components instead: each original block keeps one copy
and runs behind a guard on its own reach flag, and each component becomes
a loop with a single latch that repeats it while a back edge set its again
flag. Every edge sets the reach flag of its target, so exactly one flag
names the next original block and the blocks run in the input's order for
every branch decision. Irreducible and non-terminating graphs are handled
the same way, and no block is cloned.

The ladder runs first and its output is unchanged. The fallback only runs
when both attempt series refuse; if it cannot structure the graph, the
ladder's error is reported as before. Blocks that start the top-level
order unconditionally run unguarded, so the entry block's results reach
later blocks without a stale path. APS5_FORCE_STRUCTURIZER_FALLBACK=1
uses the construction for every supported graph, for tests.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 00:59:50 +02:00
AlxcBTWandClaude Opus 5.5 6ffc99bedb perf(agc): take the memory-value dword fill kernel as a buffer fill
The 9-word kernel #3816 matches stores one dword per thread, loaded with
s_buffer_load_dword through the descriptor in user[4..7]. Run as a
compute dispatch, its stores are pending writes of unknown value, so a
later read of DCC keys in that range waits for the GPU.

fillBuffer now takes it as a uniform buffer fill when all of these hold:
- the output descriptor's format is 32_UINT, 32_SINT or 32_FLOAT (20-22),
  so buffer_store_format_x stores the loaded dword unchanged;
- the value descriptor covers the loaded dword: num_records times the
  stride (num_records alone when the stride is 0) is at least 4 bytes,
  the range the recompiler gives a scalar buffer load;
- exactly 8 user SGPRs and group id X enabled, so the group id is s8;
- a direct, non-partial dispatch, 64x1x1 threads, one group in Y and Z,
  and a 16-byte aligned range of whole 16-byte units.

The value is read when the fill is recorded, after the labels queued
before it, as the pattern-fill kernel's source is. When the value is one
byte repeated and that byte is a DCC key code, the fill goes into the GPU
key-store memo whatever ClassifyFill reports: the memo answers a key
read only while this fill is still the newest pending write over the
keys, and a fill over a color target's keys is not a storage image's
keys fill.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 00:44:41 +02:00
David 773e7f218c docs(debt): describe the byte the Windows flock locks 2026-10-13 22:29:33 +00:00
David b962be8536 test(libc): read and write through another descriptor while a flock is held 2026-10-13 22:29:20 +00:00