Skip to content

fix(libSceAgcDriver): zero the overhanging record of a vertex fetch - #5926

Merged
oneandonlydean merged 2 commits into
boykopovar:mainfrom
xXPBSXx:fix/agc-vertex-fetch-overhang
Oct 19, 2026
Merged

oneandonlydean merged 2 commits into
boykopovar:mainfrom
xXPBSXx:fix/agc-vertex-fetch-overhang

Conversation

@xXPBSXx

@xXPBSXx xXPBSXx commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

What

The Mound: Omen of Cthulhu (PPSA26223) sometimes aborts in the video-out thread while it prepares a draw:

[VBDBG] addr=0x1378f00650 bytes=0x9f9bc stride=44 records=14858 valid=0x9f9b8 indirect=0
[unreadable] guest memory is not readable at 0x1378fa0000 (range 0x1378f00650+0x9f9b8) from +0xc6ad4
what():  AGC driver: guest memory is not readable at 0x1378fa0000 (range 0x1378f00650+0x9f9b8)

(PPSA26223_rM2/run_175628.err lines 4201-4206; the [VBDBG] line is a local debug print, not part of this change.) The vertex descriptor says 14858 records of 44 bytes, 0x9f9b8 bytes, starting at offset 0x650 of a mapping that the title made with map direct 0000001378f00000+0xa0000 (same file, line 3895). The mapping holds 0x9f9b0 bytes from that address: 14857 whole records and 36 of the 44 bytes of the last one. CopyZeroPaddedDrawInput asks for the whole 0x9f9b8 bytes and the draw fails 8 bytes past the mapping.

This pull request copies only the readable bytes of such a fetch and reads the rest as zeros, when the part past the readable memory is less than one stride. A longer overhang, and a fetch without a stride, still fail as before.

  • Rule: the same as the documented "Strided buffer overhang" rule in docs/dev/debt/libSceAgcDriver.md (a descriptor that ends less than one stride past the readable allocation is bound only up to the allocation's end, assuming the extra bytes are the rounded-up num_records of the last record). It is taken from there and from fix(agc): bound a strided buffer's rounded-up last record by its allocation #2912, not measured on hardware; whether the console reads the missing 8 bytes of the last record, and whether this draw uses that record, is not known. The debt entry says so.
  • Frequency: the abort was seen in 3 runs of the title (PPSA26223_rL/run_155033.err on main e736e5bdb, PPSA26223_rM1/run_160909.err, and the run above) and not in 16 other runs of the title that I made (on three different builds of main), so it depends on something in the run that I could not identify. The first two hits name the same range shape (0x650 + 0x9f9b8, 8 bytes over a 0xa0000 boundary); only the third has the stride and record count.
  • With this change I did not get a deterministic title run that shows the draw passing, because the abort does not reproduce on demand.

Tested

Windows 10 (19045), MinGW-w64 GCC 15.2.0, Release, on main fa9365ca7 + this commit (head 3666457f0):

  • agc_driver_graphics (new case vertexOverhangTests: a reserved block with one committed and one PAGE_NOACCESS page; a fetch of stride 44 that overhangs the committed page by 8 bytes is copied with its last 8 bytes zero; an overhang of one stride, and a fetch without a stride, fail with "is not readable") passes. With the clamp removed in Draw.cpp (same signature, so the test still builds; the unchanged main Draw.cpp does not compile against the new call) it fails with "guest memory is not readable".
  • python tools/check_conventions.py --base upstream/main with this title and body passes.
  • Title evidence run (before the change): main 979ad7b6a with a local fprintf in Draw.cpp that prints the fetch when it is unreadable; ninja -C build -j4 relinker plus all 126 core/libs/libs/*.prx, libSceAgcDriver.prx 17:01:45 local time; relink_title_trace.ps1 (relinker.exe --windows --registry --trace-imports), run_title.ps1 -Seconds 120, APS5_TRACE_MEMORY=1, APS5_TRACE_UNREADABLE=1. In the earlier hit PPSA26223_rM1/run_160909.err (offsets +0xc4cd4 and +0x120186 of that build, resolved with nm on its libSceAgcDriver.prx) the caller is AgcDriver::Graphics::CopyZeroPaddedDrawInput; the [VBDBG] line above is printed from the same code path.
  • Not tested: Linux (the test has a mmap branch that I did not build), a console, other titles.

Overlap: #5778 (open) also deals with V# ranges, but in ShaderResources::addGuestBuffer for a size past maxStorageBufferRange; this change is in the staging copy CopyZeroPaddedDrawInput for a record that overhangs readable memory by less than one stride. merge-tree of both heads conflicts only in docs/dev/debt/libSceAgcDriver.md. Whether #5778 changes the Mound case was not 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 in TechnicalDebt (docs/dev/debt/libSceAgcDriver.md)
  • No notes, investigation .md files or images added to the repository
  • New third-party code is a submodule built from source (none added)
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Unblocks: PPSA26223 (The Mound: Omen of Cthulhu) at this draw; no bring-up discussion known to me
  • GPUs tested: n/a (CPU-side copy; the title runs used an NVIDIA GeForce RTX 4080 SUPER, Windows 10)
  • AI-assisted: yes

AI-assisted (Claude Code).

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.

Pull request Shared files not compared
PR 1191 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 1368 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 1395 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 2434 docs/dev/debt/libSceAgcDriver.md
PR 4040 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 4072 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 4448 docs/dev/debt/libSceAgcDriver.md
PR 4650 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 5058 docs/dev/debt/libSceAgcDriver.md
PR 5372 docs/dev/debt/libSceAgcDriver.md
PR 5431 core/libs/prx/libSceAgcDriver/Graphics/include/Draw.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 5441 core/libs/prx/libSceAgcDriver/Graphics/include/Draw.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 5499 core/libs/prx/libSceAgcDriver/Graphics/include/Draw.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 5500 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 5609 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 5925 core/libs/prx/libSceAgcDriver/Graphics/include/Draw.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6188 core/libs/prx/libSceAgcDriver/Graphics/include/Draw.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6194 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6202 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 6223 docs/dev/debt/libSceAgcDriver.md
PR 6235 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6273 docs/dev/debt/libSceAgcDriver.md
PR 6280 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6292 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 6300 docs/dev/debt/libSceAgcDriver.md
PR 6412 docs/dev/debt/libSceAgcDriver.md
PR 6457 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6479 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6481 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6498 docs/dev/debt/libSceAgcDriver.md
PR 6523 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6529 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6535 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6539 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 6543 docs/dev/debt/libSceAgcDriver.md
PR 6548 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6549 docs/dev/debt/libSceAgcDriver.md
PR 6563 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6567 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6571 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6606 core/libs/prx/libSceAgcDriver/Graphics/include/Draw.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 6615 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 6636 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6639 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6646 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6647 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6683 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6718 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 6727 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6730 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6762 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6763 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 6786 docs/dev/debt/libSceAgcDriver.md
PR 6808 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6820 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 6867 docs/dev/debt/libSceAgcDriver.md
PR 6868 docs/dev/debt/libSceAgcDriver.md
PR 6941 docs/dev/debt/libSceAgcDriver.md
PR 6946 core/libs/prx/libSceAgcDriver/Graphics/include/Draw.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6947 core/libs/prx/libSceAgcDriver/Graphics/include/Draw.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6958 docs/dev/debt/libSceAgcDriver.md
PR 6966 docs/dev/debt/libSceAgcDriver.md
PR 6970 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6972 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6977 docs/dev/debt/libSceAgcDriver.md
PR 7008 docs/dev/debt/libSceAgcDriver.md
PR 7085 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7254 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7256 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7258 docs/dev/debt/libSceAgcDriver.md
PR 7332 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7340 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 7369 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 7390 docs/dev/debt/libSceAgcDriver.md
PR 7432 docs/dev/debt/libSceAgcDriver.md
PR 7505 docs/dev/debt/libSceAgcDriver.md
PR 7604 docs/dev/debt/libSceAgcDriver.md
PR 7642 core/libs/prx/libSceAgcDriver/Graphics/include/Draw.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7650 docs/dev/debt/libSceAgcDriver.md

@github-actions github-actions Bot added docs agc libSceAgc* labels Oct 14, 2026
This was referenced Oct 15, 2026
@xXPBSXx

xXPBSXx commented Oct 15, 2026

Copy link
Copy Markdown
Contributor Author

@adriadam10 a short request for review of this PR. It had a merge conflict in docs/dev/debt/libSceAgcDriver.md (the new entry from #5778 and mine; I kept both), so I rebased it onto main fa9365ca7; head is now 3666457f0, MERGEABLE / CLEAN, the Conventions and Eligibility checks are green. agc_driver_graphics (including vertexOverhangTests) passes with the change and fails without it on that base (guest memory is not readable at 0x1a921b70000). The description names the title (The Mound: Omen of Cthulhu, PPSA26223) and the log line. The needs rebase label is still on it from before.

AI-assisted (Claude Code).

@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 15, 2026

@jotitadev jotitadev left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A Linux run, since the description says the mmap branch of the test was not built.

Machine: Ubuntu 26.04 (kernel 7.0.0-38, 4 KiB pages), i7-8700, GCC 15.2, Release, BUILD_TESTING=ON; NVIDIA GeForce RTX 3070, driver 595.99.02. Head 3666457f0 merged onto main 5d9dcc42d, no conflicts.

GPUs tested: NVIDIA GeForce RTX 3070 (595.99.02), Linux

  • The mmap/mprotect branch of vertexOverhangTests builds with no warnings from the changed files, and agc_driver_graphics passes 3/3.
  • Fault check on Linux: with the clamp line in CopyZeroPaddedDrawInput taken out (if (validBytes - prefix < stride) readable = prefix;, same signature so the test still builds), agc_driver_graphics fails 3/3 with AGC driver: guest memory is not readable at 0x...5e000 (range 0x...4e650+0xf9b8), the 8 bytes past the readable page. With the line restored, it passes. So GuestMemory::Accessible/CommittedRanges see the PROT_NONE half of the block on Linux as well, and the test guards the fix there.
  • ctest -R "^agc" -E "agc_display_buffer_dcc|agc_driver_flip|agc_driver_lds_atomics64" -j1 --timeout 60: 591/593 pass, the same result as unchanged main on this machine (agc_driver_stencil_ref_export skipped, agc_driver_store_over_untracked fails as on main, #6385).

Written with AI assistance (Claude Code). I ran the tests above on my machine.

@adriadam10 adriadam10 self-assigned this Oct 16, 2026
@adriadam10

Copy link
Copy Markdown
Collaborator

Re-checked on Linux (RADV) with the PR merged onto current main: agc_driver_graphics (incl. vertexOverhangTests) passes, the rest of the libSceAgcDriver scope is green apart from agc_driver_tessellation (segfault, also on main). Without the change the test doesn't build (new signature); @jotitadev confirmed the test fails on Linux when the clamp line is removed. The clamp is limited to a stride-bearing fetch with less than one stride of overhang, and the debt entry records that it isn't measured on hardware. Merging once the full Build is green.

@oneandonlydean oneandonlydean self-assigned this Oct 18, 2026
@oneandonlydean

Copy link
Copy Markdown
Collaborator

The fix reads right. Could the debt entry drop the title (PPSA26223; it's in the PR body), per the no-titles-in-docs rule?

@github-actions github-actions Bot added the unblocks title Names a title ID on the Unblocks line label Oct 18, 2026
xXPBSXx and others added 2 commits October 19, 2026 03:47
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@xXPBSXx
xXPBSXx force-pushed the fix/agc-vertex-fetch-overhang branch from 3666457 to 55b197d Compare October 19, 2026 01:48
@xXPBSXx

xXPBSXx commented Oct 19, 2026

Copy link
Copy Markdown
Contributor Author

Author address of the first commit corrected (it carried a local test address, so GitHub did not attribute it to my account); no code change: the tree of both commits is identical before and after (a37b45a2d).

The second commit drops the title from the debt entry, as asked: the entry now describes the observed case (a fetch of 14858 records of 44 bytes that ends 8 bytes past the end of the 0xa0000-byte mapping holding it) without naming the game; the title stays in the PR body.

AI-assisted (Claude Code).

@oneandonlydean
oneandonlydean merged commit fa0ac6d into boykopovar:main Oct 19, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agc libSceAgc* docs unblocks title Names a title ID on the Unblocks line

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants