AnyPS5/core/libs/prx/libSceAgc
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
..
Acb style: strip explanatory comments per CONVENTIONS.md 2026-09-29 04:20:09 +03:00
Cb style: drop the branch's code comments per CONVENTIONS.md 2026-09-29 21:25:29 +03:00
Command Merge branch 'boykopovar:main' into main 2026-09-30 05:05:49 -04:00
DcbDraw style: drop the branch's code comments per CONVENTIONS.md 2026-09-29 21:25:29 +03:00
DcbFlow style: drop the branch's code comments per CONVENTIONS.md 2026-09-29 21:25:29 +03:00
DcbState Update Registers.cpp 2026-09-30 04:55:24 -04:00
Misc fix(agc): fuse geometry shader halves into one self-contained program 2026-10-01 08:45:51 +13:00
Patch Merge branch 'boykopovar:main' into main 2026-09-30 05:05:49 -04:00
Predication refactor(libSceAgc): add subdirs + new separated src 2026-09-13 15:06:31 +03:00
Shader fix(agc): preserve strict shader linkage failures 2026-09-25 07:22:06 +10:00
tests fix(agc): fuse geometry shader halves into one self-contained program 2026-10-01 08:45:51 +13:00
CMakeLists.txt fix(agc): fuse geometry shader halves into one self-contained program 2026-10-01 08:45:51 +13:00
Unimplemented.cpp fix(agc): EOP PatchData takes (cmd, data); -KRzWekV120 sets the index size 2026-09-29 21:22:16 +03:00