Skip to content

fix(agc): resolve indexed indirect draws on a queue that never set INDEX_BUFFER_SIZE - #7679

Closed
spiff637 wants to merge 4 commits into
boykopovar:mainfrom
spiff637:fix/agc-unset-index-limit
Closed

spiff637 wants to merge 4 commits into
boykopovar:mainfrom
spiff637:fix/agc-unset-index-limit

Conversation

@spiff637

Copy link
Copy Markdown
Contributor

What

An indexed indirect draw (DRAW_INDEX_INDIRECT 0x25, DRAW_INDEX_INDIRECT_MULTI 0x38) on a queue that has not received INDEX_BUFFER_SIZE (0x13) or INDEX_ATTRIBUTES_INDIRECT (0x91) since its last reset threw INDEX_BUFFER_SIZE has not been set.

Marvel's Spider-Man 2 (PPSA08338) never emits either packet. Probing every 0x13 and every suspend-point queue reset over a whole run found none, so no written size is being lost. Per draw it writes VGT_INDEX_TYPE (uconfig 0x243 = 0x400, 16-bit indices) and INDEX_BASE, then issues DRAW_INDEX_INDIRECT_MULTI. It stopped about 110–194 s in, on both a 2026-10-13 base (84b0d2f24) and current main.

The change:

  • QueueState::indexBufferSize becomes std::optional<std::uint32_t>. A size written by 0x13 or by a 0x91 record behaves as before. An explicit 0 still throws, now as INDEX_BUFFER_SIZE is zero.
  • When the size was never written, resolveIndirectDraw marks the draw indexLimitKnown = false and keeps the base and alignment checks.
  • ClassifyIndirectDraw sends such a draw to the CPU record path (new path IndexLimitUnknown, profiler name "index limit unknown"). The mesh GPU-side case goes there too, so the GPU path's whole-range check and copy is never reached without a limit.
  • On the record path, each record's firstIndex/indexCount range skips the clamp against the declared limit. Instead it must not overflow, and it goes through fix(agc): resolve sparse indirect index ranges per record #6606's per-record readability check. Reads stay bounded by min(count at countAddress, packet count) records; nothing beyond a record's own range is read.
  • What still throws: an unreadable active record, address overflow, a null or misaligned base, an explicit size of 0, and the existing type checks.
  • The assumption is recorded in docs/dev/debt/libSceAgcDriver.md. The console's initial INDEX_BUFFER_SIZE, and whether the DRAW_INDEX_2/DRAW_INDEX_OFFSET_2 MAX_SIZE sets it, are not measured.

The branch is #6606's head (925f9a84b) merged with main (0d1c299a9), plus one commit. Until #6606 is merged, the diff also shows its commits.

Tested

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 under Silent stubs in their library's technical debt file
  • 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: fix(agc): resolve sparse indirect index ranges per record #6606
  • Fixes: none
  • Unblocks: PPSA08338 (no Game bring-up discussion yet)
  • GPUs tested: NVIDIA GeForce RTX 3080, driver 617.42, Windows 11 Enterprise 10.0.26200
  • AI-assisted: yes

🤖 Generated with Claude Code

https://claude.ai/code/session_01HAtTu2pw6GTkMNwsjBDatU

Kovalev Vladislav and others added 4 commits October 16, 2026 04:27
…DEX_BUFFER_SIZE

A queue that has received neither INDEX_BUFFER_SIZE nor
INDEX_ATTRIBUTES_INDIRECT since its last reset has no index limit.
Such a draw takes the CPU record path and reads each record's index
range as written, refusing a range that overflows or is not readable.
An explicit INDEX_BUFFER_SIZE of 0 still throws.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HAtTu2pw6GTkMNwsjBDatU
@github-actions

Copy link
Copy Markdown

Thank you for your contribution! Authors with no pull requests merged into main can have 1 open pull request at a time, authors with at least 1 merged can have 20, and from 20 merged there is no limit. This PR has been automatically closed and labeled "open PR limit" because that limit was reached. This is not a judgment of the quality of your changes: reopen it once one of your open pull requests is merged or closed.

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

Labels

open PR limit Closed over the open PR limit: 1 without merged PRs, 20 with at least 1, none from 20 unblocks title Names a title ID on the Unblocks line

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant