Commit Graph

6 Commits

Author SHA1 Message Date
boykopovar 2767da6a8a fix(tests): check Vulkan availability before shader registration 2026-10-08 19:09:13 +03:00
Adrià ac951f8d09
Merge pull request #1215 from polysius/fix/agc-versioned-nid-names
refactor(libSceAgc): name exports after the versioned SDK names their NIDs hash to
2026-10-08 11:05:42 +02:00
ploysius f7424ea95d refactor(libSceAgc): name three more exports after their versioned NIDs
OpenAGC's include/agc_nids.h names three more of the raw-NID exports, and
each name hashes to its NID:

  gQkqkLttcpw  sceAgcAcb_gQkqkLttcpw               -> sceAgcAcbAtomicGds_0900
  dolOmWH+huQ  sceAgcUnknownGetFusedShaderSize     -> sceAgcGetFusedShaderSize_0080
  V++UgBtQhn0  sceAgcGetDataPacketPayloadAddressUnk -> sceAgcGetDataPacketPayloadAddress_0090

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 14:02:51 -04:00
ploysius 39191f905d refactor(libSceAgc): name exports after the versioned SDK names their NIDs hash to
Eight libSceAgc exports were published under a raw NID with a made-up
name. Each NID is the hash of a versioned SDK name (checked with
tools/nid_names.py compute_nid), so the functions now carry that name and
are exported from it directly:

  23LRUSvYu1M  sceAgcUnknownInitState          -> sceAgcInit_0090
  -KRzWekV120  sceAgcUnknown__MKRzWekV120      -> sceAgcDcbSetIndexSize_0600
  Ikfdt-rIqCE  sceAgcUnknown_Ikfdt_MrIqCE      -> sceAgcJumpPatchSetTarget_0300
  7Wa3aeJgeVU  sceAgcUnknown_7Wa3aeJgeVU       -> sceAgcBranchPatchSetThenTarget_0300
  rP5xLdOf26k  sceAgcUnknown_rP5xLdOf26k       -> sceAgcBranchPatchSetElseTarget_0300
  fd5Bp5tGTgo  sceAgcUnknownFuseShaderHalves   -> sceAgcFuseShaderHalves_0200
  qj7QZpgr9Uw  sceAgcDcbContextStateAnotherOp  -> sceAgcDcbContextStateOp_0100
  k0E7vkgqAuE  sceAgcCreateInterpolantMappingVsPs -> sceAgcUpdateInterpolantMapping_0100

The exported NIDs are unchanged; the extra exports under the hashes of the
made-up names are gone. Behaviour is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 13:55:45 -04:00
TideOPL 1311bf6567 fix(libSceAgc): accept s_swappc_b64 null, s[6:7] as a front half's terminator
sceAgcUnknownGetFusedShaderSize and sceAgcUnknownFuseShaderHalves
require a front half to end with s_setpc_b64 s[6:7] (0xbe802006), the
jump to the back half, before its s_code_end padding. PPSA16064
(Minecraft Dungeons II, Unreal Engine) has front halves that end with
0xbefd2106 instead, and the size query threw "front half does not end
with s_setpc_b64 s[6:7]".

0xbefd2106 is SOP1 S_SWAPPC_B64 (opcode 0x21) with SSRC0 s[6:7] and
SDST 125, the NULL register (RDNA2 ISA, SOP1 and the scalar operand
table): it jumps to s[6:7] and discards the return address, the same
transfer as s_setpc_b64 s[6:7]. Fusion drops this instruction and pads
to the back half with s_nop either way, so both forms are accepted. Any
other last instruction still throws.

agc_shader_fusion runs the full fusion check on a front half ending
with the s_swappc_b64 form; on main it fails with the title's error.
2026-10-07 14:08:13 +01:00
Dean Galvin 258e4d526d fix(agc): fuse geometry shader halves into one self-contained program
sceAgcUnknownFuseShaderHalves (fd4700b9) fuses both kinds of halves at
the register level: the back half's registers with the front half's
program address in PGM_LO_ES (PGM_LO_LS for hull halves). For geometry
halves the driver then compiles that front half as the draw's whole
program (type 4, Stage::Mesh) and skips the back (Role::GeometryBack);
nothing links the two. The front ends in s_setpc_b64 s[6:7] and has no
s_endpgm, so the decode runs on into the s_code_end padding and the
program trailer. In PPSA21564 the geometry shader draws were skipped
with "unsupported SOPP opcode 31" (s_code_end) and "unsupported scalar
source operand code 115 at program counter 64".

Geometry halves are now fused into one Gs program: the front half's code
up to its final s_setpc_b64 s[6:7] (its length comes from the program
trailer), s_nop padding to the next 256 bytes, then the whole back half,
so the front falls through into the back. Its SH registers are the back
half's, with PGM_LO/HI_GS pointing at the copied back code, the ES
program address at the fused code, RSRC1 taking the larger VGPR and SGPR
counts of the two halves, RSRC2 taking the front half's user-SGPR count
(the SPI loads the front layout; the back reloads its own from memory
through s[0:1]), and the front's other SH registers except its checksum
appended. Context registers are merged the same way. Inputs come from
the front, outputs, specials and user data from the back; the scratch
size is the larger of the two.

Everything the fused Shader points to, including a copy of the header
itself, is written into the caller's memory after the code, and the
header is registered with the driver as a self-contained shader. Titles
pass memory without honouring the reported alignment, so the program is
placed at the first 256-byte boundary inside it, and the size query
returns the total plus 255 bytes of padding (alignment reported as log2
8). Halves with embedded constant buffers, a front half without a
trailer or final s_setpc_b64, a front half that needs RSRC2 state the
back half does not enable, and geometry halves without fused memory
throw.

Hull halves keep the register-level fusion, which the tessellation
path's separate local and hull programs fit. The half-type and stage
checks stay shared.

The driver now loads s[0:1] of a Gs program from its user-data address
registers whenever they are set, not only for GsFront programs, since
the back half of a fused program reloads its user data from there; a
program without those registers keeps zero there (from SamG-Coder's
8345fbc1).
2026-10-01 08:45:51 +13:00