Skip to content

feat(agc): implement packet and range predication and the predication sizes - #582

Merged
oneandonlydean merged 4 commits into
boykopovar:mainfrom
CnRJay:feat/agc-predication
Oct 6, 2026
Merged

oneandonlydean merged 4 commits into
boykopovar:mainfrom
CnRJay:feat/agc-predication

Conversation

@CnRJay

@CnRJay CnRJay commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

What

Five libSceAgc exports threw NotImplemented.

  • sceAgcSetPacketPredication(packet, predication) sets (1) or clears (0) the PM4 predicate bit (bit 0) of a type-3 packet header and leaves the payload alone. A null packet, a non-type-3 header or a value above 1 throws.
  • sceAgcSetRangePredication(start, end, predication) does the same for every type-3 packet in [start, end). It skips type-2 filler dwords. A range that ends inside a packet or holds another packet type throws.
  • sceAgcDcbSetZPassPredicationEnableGetSize, sceAgcDcbSetPredicationDisableGetSize and sceAgcDcbSetBoolPredicationEnableGetSize return 16 bytes.
    • Their builders are inline in the SDK and not exported. Z-pass, boolean and disable are all PM4 SET_PREDICATION operations, so the size is that of the packet sceAgcDcbSetPredication writes.
    • This is derived, not observed, so it is recorded under Unknown function info in TechnicalDebt.

The executor still rejects predicated packets ("PM4 header flags ... are not implemented") and SET_PREDICATION itself ("GPU query predication is not implemented"). A title that predicates commands still stops at execution with a clear error, rather than running them unconditionally.

Tested

Windows 11, MinGW GCC 15.2.0 r7. New agc_predication_tests:

  • Sizes: the three size queries against the bytes sceAgcDcbSetPredication writes.
  • Single packet: setting and clearing the bit on a packet, and rejecting bad arguments without modifying anything.
  • Range: a range with a filler dword between packets, where payloads and fillers stay untouched. Also an exclusive end, an empty range, a range ending mid-packet, a reversed range, an invalid value and a non-type-2/3 packet.

Full ctest: 217/218 pass. agc_shader_memory fails without this change too; #574 fixes it.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed in TechnicalDebt
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • AI-assisted: yes

🤖 Generated with Claude Code

… sizes

sceAgcSetPacketPredication sets or clears the predicate bit of a type-3
packet header, and sceAgcSetRangePredication does so for every type-3
packet between two addresses, skipping type-2 fillers. The z-pass, bool
and disable predication size queries return the size of the
SET_PREDICATION packet sceAgcDcbSetPredication writes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@oneandonlydean

Copy link
Copy Markdown
Collaborator

Thanks. The five NIDs recompute to these names, the predicate bit and the size from the count field are right for a type-3 header, and it matches BryKytyPS5's AgcSetPacketPredication/AgcSetRangePredication, except that you throw for an invalid value or a reversed range, which is fine. The 16-byte sizes with the TechnicalDebt line look good to me too.

One gap in the range walk: the one-dword pad 0xffff1000 (a type-3 NOP with count 0x3fff, which the CP treats as a single dword; main's Commands.cpp test calls it the empty payload marker). Here it's read as a 16385-dword packet. In a short range that throws, but in a range longer than that it silently skips the next 16384 dwords, and those packets keep their old predicate bit. BryKytyPS5 treats (header & 0x3fffff00) == 0x3fff1000 as one dword. Could you do the same (or throw on it), with a test row next to the type-2 filler?

agc_predication_tests passes here and fails on main's code ("sceAgcDcbSetZPassPredicationEnableGetSize not implemented"). It conflicts with #338, #407, #545 and #550 in TechnicalDebt.md (neighbouring lines), so whichever lands later needs a one-line rebase. PPSA21564 doesn't import any of these functions. The CI run still needs workflow approval.

@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

Progress report (7de111f → 73a751a)

📈 System libraries: 80.85% (+0.15%, +5 implemented functions)

✅ 5 implemented
Library Name
libSceAgc sceAgcDcbSetBoolPredicationEnableGetSize
libSceAgc sceAgcDcbSetPredicationDisableGetSize
libSceAgc sceAgcDcbSetZPassPredicationEnableGetSize
libSceAgc sceAgcSetPacketPredication
libSceAgc sceAgcSetRangePredication

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 5, 2026
@oneandonlydean

Copy link
Copy Markdown
Collaborator

One more thing for when you push the pad change: #338 and #613 have landed since, and both add lines at the end of "Unknown function info" in docs/dev/TechnicalDebt.md, where this PR adds its predication sizes line. Could you rebase onto main at the same time, keeping main's lines and adding yours after them?

CnRJay and others added 2 commits October 5, 2026 14:48
0xffff1000 is a type-3 NOP whose count field is 0x3fff, which the command
processor reads as a single dword. sceAgcSetRangePredication read it as a
16385-dword packet and skipped the packets after it, or threw in a short
range. It is now stepped over like a type-2 filler.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 5, 2026
@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 5, 2026
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 5, 2026
@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.

Pull request Conflicting files (lines on main) Same exports Same new files
#778 docs/dev/TechnicalDebt.md L122

@oneandonlydean
oneandonlydean merged commit b8a98c9 into boykopovar:main Oct 6, 2026
3 checks passed
@oneandonlydean

Copy link
Copy Markdown
Collaborator

Thanks for the pad change and the rebase. d4f7dda steps over 0xffff10xx as one dword, like a type-2 filler, and leaves it unpredicated. The test now puts the pad between two packets and checks that both still get the bit and that the pad is unchanged, which throws on the previous head. That matches the one-dword size #772 uses for sceAgcGetPacketSize.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants