Commit Graph
194 Commits
Author SHA1 Message Date
Adrià 2da2284def Merge pull request #6270 from YossiYad/fix/agc-register-defaults-pairs
fix(libSceAgc): return the console's register-defaults table and type pairs
2026-10-18 23:14:29 +02:00
Adrià 09acc80f7e Merge pull request #6145 from MarcZX10/codex/fix-agc-atomic-gds-size
fix(libSceAgc): reserve complete atomic GDS packets
2026-10-18 19:28:01 +02:00
Dean 16c607a937 Merge pull request #6925 from LeandroLP23/fix/agc-shader-helpers-shutdown
test(agc): shut libc down before agc_shader_helpers returns
2026-10-17 17:29:05 +13:00
Adrià f1dded21fe Merge pull request #6004 from XairRrR/fix/agc-empty-register-list
fix(agc): write nothing for an empty register list
2026-10-17 03:10:51 +02:00
LeandroLP23andClaude Opus 5.5 050f10053c test(agc): shut libc down before agc_shader_helpers returns
On Windows, agc_shader_helpers returned from main with the driver's
threads still running. ExitProcess ends them first, then the DLLs'
static destructors run and wait on what those threads left locked:
the async log's queue mutex in Driver::stop, DeviceUseGate's condition
variable in ~Driver, and condition variables in libkernel's statics.
The test hung after printing its result in about one ctest run of
three on a Radeon 860M (#6791).

Like the other driver tests, it now runs LibcRunShutdown_nid_postfix
before returning, which stops the driver while its threads are alive.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 20:56:41 +02:00
Adrià ab88420409 Merge pull request #5845 from pushkarreddyy/feat/libSceAgc-default-cx-state-flat
feat(libSceAgc): implement sceAgcGetDefaultCxStateFlat
2026-10-15 23:00:59 +02:00
Adrià 8b99f0177c Merge pull request #5848 from wachi35676/refactor/libSceAgc-name-interpolant-mapping-10000
refactor(agc): name dbOlWdppb4o and vieBRwlh1Lw the _10000 interpolant mappings
2026-10-15 23:00:46 +02:00
Adrià Franch 6ebab0e73b test(libSceAgc): declare the invalid-argument constant, restore the register defaults version checks 2026-10-15 15:36:49 +02:00
pushkarreddyy fd90df41b6 feat(libSceAgc): implement sceAgcGetDefaultCxStateFlat 2026-10-15 15:36:43 +02:00
Yossi Yadgar 52e288ef43 test(libSceAgc): find the MRT0 colour-target defaults the way a title does
Reads the root at its byte offsets, walks the type table as key and
bank-index pairs and checks that the MRT0 key leads to the sixteen
colour-target registers: block 78 of the table sceAgcGetRegisterDefaults
returns, block 73 of version 10, and a valid block in every version from
4. Fails on the compact entries and on the version 0 legacy table.
2026-10-15 11:04:32 +03:00
Yossi Yadgar dce1573ea0 fix(libSceAgc): return the newest public register defaults from sceAgcGetRegisterDefaults
The legacy call takes no version and answered with the version 0 table.
On a console it returns the running system software's table: 128 keyed
entries over 79 context blocks on 10.x and 137 over 84 on 12.02 and 13.x,
as ps5-vulkan measured and relies on. Version 0 holds 150 entries and its
MRT0 block starts at 0x318 followed by 0x319, so PPSA99011 refused it
even with the types fixed. Return the version 13 table, which is the
137-entry one.
2026-10-15 11:03:41 +03:00
Yossi Yadgar f7750c7769 fix(libSceAgc): hand out register-default types as key and bank-index pairs
The defaults root exposed the compact 12-byte type entries, whose second
word also packs each block's register count and stride above bit 10.
Titles read the type table as 8-byte {key, index << 2 | bank} pairs, so
PS5 FSR4 Showcase (PPSA99011) found the MRT0 key at index 529482 and
refused to build its compose pass. Build the pairs once per table and
check that every index lies inside its bank.
2026-10-15 11:03:12 +03:00
XairRrR f991052cfd test(agc): an empty register list into a null buffer still throws
AI-assisted: yes
2026-10-15 02:54:50 +02:00
MarcZX100 7918cfc49a fix(libSceAgc): reserve complete atomic GDS packets 2026-10-14 23:21:34 +00:00
Dean 95945006ec Merge pull request #4629 from mugurc/fix/libcxx-portability
fix(libs): build with libc++
2026-10-15 10:46:05 +13:00
XairRrR cf914b5102 fix(agc): write nothing for an empty register list
sceAgcCbSetShRegistersDirect and the other register list writers threw on
a count of 0 although the matching size functions report 0 words for it.
PPSA05684 calls the writer with an empty list at its main menu and
terminated. An empty list now writes no packet and returns the cursor,
as its size says; a null buffer still throws.

AI-assisted: yes
2026-10-14 20:50:00 +02:00
Adrià 456ce66bb0 Merge pull request #5163 from mazen320/fix/agc-init-fallback-out-of-range
fix(agc): return 0 for out-of-range sceAgcInit without table lookup
2026-10-14 20:35:43 +02:00
Adrià 0b1304896d Merge pull request #5023 from fdfawef324/fix/agc-shader-prep-wait
fix(agc): settle registration preparations before a preparation scope locks
2026-10-14 19:53:34 +02:00
Muhammad Wasif Ali WasifandClaude Opus 5.5 a0fc988a53 refactor(agc): name dbOlWdppb4o and vieBRwlh1Lw the _10000 interpolant mappings
The names hash to the NIDs dbOlWdppb4o and vieBRwlh1Lw that the exports
carried as sceAgcUnknownCreateInterpolantMapping and
sceAgcUnknown_vieBRwlh1Lw.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 18:44:16 +05:00
Maz eb1b9eca96 fix(agc): return 0 for out-of-range sceAgcInit without table lookup
Pointer-shaped calls match the #4808 console probe (success, no writes); selecting table 13 for those values was unsupported.
2026-10-14 11:38:52 +04:00
mazen 4832bd825c fix(agc): clamp sceAgcInit versions above 13 inline 2026-10-14 11:30:49 +04:00
mazen 9d412df7b5 fix(agc): fall back out-of-range sceAgcInit versions to table 13
Pointer-shaped NID kW3GLb7QfPg calls from public homebrew succeed on console; returning an error left those titles failing init after #4835.
2026-10-14 11:30:49 +04:00
Dean 107190d11d Merge pull request #5573 from fma-rc/fix/agc-fuse-halves-scratch
fix(agc): keep fused geometry programs out of the caller's memory
2026-10-14 19:25:23 +13:00
fdfawef324andClaude Opus 5.5 11ef8e6c83 fix(agc): settle registration preparations before a preparation scope locks
sceAgcCreateInterpolantMapping resolved the pixel shader's ABI, which takes
the process-wide shader preparation lock until the scope ends, and then
waited under that lock for the vertex shader's background registration
preparation. sceAgcCreatePrimState and sceAgcLinkShaders could wait the same
way. Every other shader registration and ABI resolution queued behind that
one compile: on PPSA07411 the lock was held 8 to 10 s of every 10 s, almost
all of it waiting for registration preparations, while its loader threads
waited 13 to 45 s per 10 s to take it.

A preparation scope now names the shaders it resolves and waits for their
registration preparations before it can take the lock.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 22:39:26 -04:00
pushkarreddyy fbf619ef0d feat(libSceAgc): ignore address argument on non-sample-dump events in sceAgcDcbEventWrite 2026-10-14 07:37:02 +05:30
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
David 352d04e8dc feat(libSceAgc): implement sceAgcSetAmmSemaphoreMemory and sceAgcGetSemaphoreLabel
sceAgcSetAmmSemaphoreMemory(memory, sizeInBytes) registers the AMM semaphore memory once and zeroes the first 8 bytes of each 32-byte label; sceAgcGetSemaphoreLabel(index, label) writes memory + 32 * index for an index inside the registered memory.

Unblocks New Joe & Mac Caveman Ninja (PPSA02801) which imports both symbols. Matches OpenAGC and sharpemu agreements on signatures, 16 KiB alignment, 32-byte stride, and zeroed label counters.
2026-10-13 15:01:43 +02:00
Dean 501f4f5aa7 Merge pull request #4835 from MarcZX100/fix/agc-init-version-error-4808
fix(agc): return error for unsupported init versions
2026-10-13 22:00:27 +13:00
MarcZX100 cbd615bb42 fix(agc): return error for unsupported init versions 2026-10-12 23:15:39 +00:00
winstrexandClaude Opus 5.5 cb6866653c feat(libSceAgc): implement sceAgcGetGsPrimPayload
Report the 8-byte GS primitive payload when the shader's context registers
set SPI_SHADER_IDX_FORMAT.IDX0_EXPORT_FORMAT to SPI_SHADER_2COMP, and 0
otherwise. The search runs over every context register, so an earlier
SPI_SHADER_IDX_FORMAT entry with another format does not end it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 19:46:20 -03:00
fdfawef324andClaude Opus 5.5 f8257a112b feat(agc): return null from the workload builders for unregistered streams
sceAgcDcbSetWorkloadStreamInactive and the three ACB workload builders
(sceAgcAcbSetWorkloadsActive, sceAgcAcbSetWorkloadComplete,
sceAgcAcbSetWorkloadStreamInactive) threw for every call, and
sceAgcDcbSetWorkloadsActive read the workload ids before it checked the
stream.

The prosper console oracle (mattias800/prosper df074498,
prosper/tests/data/console_oracle/agcbuild.golden.tsv lines 48-56 and
196-204) measured all six calls on a PS5 with three argument patterns
and no workload stream registered: each returned null and wrote nothing.
Pattern b passes stream 1 with the workload ids at address 2, so the
console checks the stream before it reads the ids; here that call read
address 2 and crashed.

The four builders now return null for a null command buffer or a stream
that is not registered, and still throw for a registered stream: the
packet a registered stream gets is not measured, KytyPS5 has no body for
them, and its IT_NOP layout for the DCB calls differs from the
SET_UCONFIG_REG, WRITE_DATA and SET_WORKLOAD sequence OpenAGC
(3c7e8072, src/agc_workload_packet.c) derives from the driver. The
signatures are OpenAGC's DCB ones (src/game_compat.c), which says the
ACB calls use the same driver builders. sceAgcDcbSetWorkloadsActive now
checks the stream before the ids, as OpenAGC does. Recorded in
docs/dev/debt/libSceAgc.md.

agc_commands gains testWorkloadStreams: the three measured patterns for
all six calls (null, buffer untouched), an exhausted and a null buffer,
and a registered stream that throws without touching the buffer. On
upstream/main it fails with "sceAgcDcbSetWorkloadStreamInactive not
implemented", and the DCB active pattern b alone segfaults reading
0x2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 15:22:21 -04:00
mugurc facc03ae90 fix(libs): build with libc++
Apple clang ships libc++, which differs from libstdc++ where the sources
relied on it:

- std::atomic<std::shared_ptr<T>> is not provided. AtomicSharedPtr is that
  type where the library has it and a mutex-guarded pointer with the same
  member functions elsewhere; the AGC driver uses it.
- std::atomic_ref<const T> is not provided; the page span reads go through
  a non-const reference.
- std::filesystem::file_time_type::clock::to_sys is not provided;
  std::chrono::file_clock::to_sys is.
- std::max and std::min do not deduce across the integer types of the
  guest range arithmetic, which is spelled with an explicit type.
- <string> and <initializer_list> are included where the sources and tests
  use them.
2026-10-12 19:57:33 +03:00
Dean 2dfde65fa1 Merge pull request #3789 from xXPBSXx/fix/agc-workload-nop-packets
fix(libSceAgc): emit NOP packets for the DCB workload calls
2026-10-13 00:44:27 +13:00
Utku Halis 661f8e1e7c feat(libSceAgc): implement sceAgcAcbWaitUntilSafeForRendering 2026-10-12 08:26:47 +03:00
xXPBSXxandClaude Sonnet 5.5 2a7b38ab75 fix(libSceAgc): write the KytyPS5 workload packets and return null for unregistered streams
sceAgcDcbSetWorkloadsActive writes an 18-dword IT_NOP packet (stream id, 64-bit workload mask) and sceAgcDcbSetWorkloadComplete a 12-dword one (stream id, workload id, 64-bit clear mask), following KytyPS5. Both return null for a null buffer, an unregistered or out-of-range stream, a workload id above 63, and for active a duplicate id or a count of 0 or above 63. sceAgcDriverRegisterWorkloadStream and sceAgcDriverUnregisterWorkloadStream now record the stream ids the DCB calls check.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 01:37:56 +02:00
xXPBSXxandClaude Sonnet 5.5 45fcf734ab fix(libSceAgc): emit NOP packets for the DCB workload calls
sceAgcDcbSetWorkloadsActive and sceAgcDcbSetWorkloadComplete threw. They now write a plain two-dword NOP and keep no workload state.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 01:36:51 +02:00
Adrià 6dbc0ea66a Merge pull request #3829 from YossiYad/carry/agc-vieBRwlh1Lw
feat(libSceAgc): implement the vieBRwlh1Lw interpolant mapping update
2026-10-12 00:39:58 +02:00
Adrià e8169f49b3 Merge pull request #3756 from Lorkydey/feat/agc-acb-atomic-gds
feat(libSceAgc): build versioned ACB atomic GDS commands
2026-10-12 00:28:45 +02:00
Adrià 0b7b479a04 Merge pull request #3576 from parl0v/refactor/agc-dcb-atomic-gds-0900
refactor(agc): name zARR5aCmkoY sceAgcDcbAtomicGds_0900
2026-10-11 23:36:55 +02:00
DavidandClaude Fable 5.1 f4424b5f1e feat(libSceAgc): implement the vieBRwlh1Lw interpolant mapping update
Hollow Knight Silksong (PPSA12544) imports libSceAgc NID vieBRwlh1Lw
(#699). Its name is unknown: it is not in aerolib, and the
sceAgcUpdateInterpolantMapping label other projects give it hashes to
SbuY2jN+axQ.

OpenAGC (src/game_compat.c at 3c7e807, sceAgcUnknownVieBRwlh1Lw) reads
it from FW 11.60 as the dbOlWdppb4o transform with the same (regs, gs,
ps) arguments, without the identity tail: it writes one register per
pixel shader input, none for a pixel shader without inputs, and rejects
a null pixel shader. It now shares the dbOlWdppb4o path and throws for
the rejected arguments.

For is_f16 1 and 3 inputs whose default_value and default_value_hi
differ, OpenAGC takes DEFAULT_VAL from default_value_hi, while KytyPS5,
sharpemu and dbOlWdppb4o here take it from default_value; these inputs
throw. On every other input the dbOlWdppb4o values equal OpenAGC's.

agc_interpolant_mapping runs the dbOlWdppb4o vectors and OpenAGC's
enhanced-mapping vectors through it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-11 20:16:47 +03:00
Lorkydey 43783f725c feat(libSceAgc): build versioned ACB atomic GDS commands 2026-10-11 18:28:46 +02:00
Josip Parlov 265c982eaa refactor(agc): name zARR5aCmkoY sceAgcDcbAtomicGds_0900 2026-10-11 15:33:55 +02:00
MarcZX100 afcaf91019 test(agc): cover hand-built VGPR register offset 2026-10-11 13:32:20 +00:00
David 88cd5bbde5 fix(libSceAgc): accept a hand-built GE_USER_VGPR register offset in sceAgcCreatePrimState
EVO Player (PPSA99039), Jelly5 (PPSA99505), Emby5 (PPSA99515) and
Nuvio PS5 (PPSA99997) stop on main 0f863c10 with

  what():  sceAgcCreatePrimState: invalid user configuration register offsets

All four build their shader headers by hand (EVO-PLAYER-PS5
evo_agc_shader_header.c, ported from ps5-xash3d-halflife) and store the
ge_user_vgpr_en special at 0x25c (GE_USER_VGPR1, value 0) instead of
0x262 (GE_USER_VGPR_EN), as analysed in #3457. They run on the console.

OpenAGC's reconstruction of the FW 5.50 sceAgcCreatePrimState
(src/game_compat.c at 3c7e8072) copies the four special register pairs
verbatim without checking their offsets; KytyPS5's offset checks
(src/libs/agc.cpp at 16a7fe68) are EXIT_NOT_IMPLEMENTED guards. The
special is now copied at the offset the header stores, not moved to
0x262; the driver reads neither register. GE_CNTL, VGT_SHADER_STAGES_EN
and a used VGT_GS_OUT_PRIM_TYPE are still required at their own
offsets because the driver reads them there, and the error now names
the special and the offset found.

With the change all four titles get past sceAgcCreatePrimState and stop
in the shader recompiler (GetImageResource dword 3 is not a valid
runtime value), as #3457 reported for EVO Player.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
(cherry picked from commit aeaa5080d9595305aa73e74d966f989c88b79839)
2026-10-11 13:19:03 +00:00
MarcZX100 a9575dc70b fix(agc): normalize disabled user VGPR special offset 2026-10-11 12:49:38 +00:00
DavidandClaude Fable 5.1 9bec190733 feat(libSceAgc): implement sceAgcDebugRaiseException
sceAgcDebugRaiseException (NID T6xuVw0KUJo) now logs the exception id
with APS5_LOG_OUT and returns 0, as libkernel's
sceKernelDebugRaiseException does.

Palworld PPSA23126 (#2598) and 007 First Light PPSA11386 (#2523) import
it; neither is shown calling it.

OpenAGC 3c7e8072 (src/game_compat.c) returns 0 and says the function is
a no-op on retail hardware; the ud2 trap it describes for development
hardware is not reproduced. KytyPS5 6f0cddd4 (src/libs/agc.cpp) takes a
uint32 exception_id, logs it and returns 0. OpenAGC declares no
arguments, but a body that only traps reads none, so the uint32 is kept
and the conflict is recorded in TechnicalDebt. The aerolib name is from
zecoxao/sce_symbols 2883963a; ps5-payload-dev/sdk f5d40f02 has only an
untyped stub.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-11 07:47:33 -03:00
MathiasDevelopes 46d8c587c6 fix(agc): mask clear-state command to four bits 2026-10-11 12:11:03 +02:00
husari.orozco 6ad5c61f1a build: route system dependency include paths and pin the shader cache to package versions 2026-10-11 10:18:23 +02:00
Cesar RodriguezandClaude Opus 5.5 8d96b44917 fix(libSceAgc): accept a null base in sceAgcDcbSetBaseIndirectArgs
The builder threw on a null indirect base, while the PM4 executor accepts
SET_BASE with address 0 (it only requires the alignment and address bits) and
an indirect draw that later reads the base is checked there. Titles clear the
base with 0, as with sceAgcDcbSetIndexBuffer, which already accepts 0 to
unbind. A non-null base is still checked for 8-byte alignment.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 20:05:51 -07:00
Adrià 9402d32fc2 Merge pull request #2993 from CnRJay/fix/agc-indirect-getsize-count
fix(agc): ignore the count passed to the indirect register GetSize functions
2026-10-11 01:48:56 +02:00