Skip to content

fix(agc): bind a V# past the range limit by the memory behind it - #5778

Merged
adriadam10 merged 1 commit into
boykopovar:mainfrom
meh7an:fix/agc-buffer-range-limit-by-mapped-memory
Oct 15, 2026
Merged

adriadam10 merged 1 commit into
boykopovar:mainfrom
meh7an:fix/agc-buffer-range-limit-by-mapped-memory

Conversation

@meh7an

@meh7an meh7an commented Oct 14, 2026

Copy link
Copy Markdown
Contributor

What

A buffer V# whose size (num_records * stride) is past maxStorageBufferRange stopped the draw with shader buffer exceeds descriptor range limit, and on current main a failed draw ends the title. Titles leave such words in descriptor slots their shaders do not reach on the path taken. Following the review of #3202, ShaderResources::addGuestBuffer now binds such a V# by the guest memory behind it:

  • the readable registered allocation holding its base ends before the limit: bound up to that allocation's end;
  • no registered allocation holds its base: the empty placeholder buffer, as for a null V#;
  • the allocation reaches the limit: it still throws.

A V# inside the limit is unchanged. The console's behaviour for an access past the bound range is not known; it is recorded under Unknown function info in docs/dev/debt/libSceAgcDriver.md.

Prince of Persia: The Lost Crown (PPSA10528) binds c8010002 2c6bec20 c0053c00 04000013 while it loads a save: base 0xec20c8010002, above the user address space, about 33 TB.

Tested

Windows 11 Pro 10.0.26300, WinLibs GCC 15.2.0, Release, this branch on main 872f523.

  • agc_driver_graphics passes. The new oversizedDescriptorTests checks the three cases: an oversized V# 8 KiB before the end of a 64 KiB registered block is bound as those 8 KiB with their bytes; one at the block's start (64 KiB, past the mock 16 KiB limit) still throws; one over unregistered memory binds the placeholder. The two existing oversized cases over unregistered test memory are now accepted. Nothing in the test is Windows-only.
  • PPSA10528 1.4.1: without the change, loading a save aborted with shader buffer exceeds descriptor range limit. With it, the save loads and the first level renders. That run was on main ea53213 with this change plus local versions of fix(libkernel): keep host standard streams open on guest close #3295 and fix(shader): ignore unused descriptor fields for scalar buffer loads #5049, which the title needs to get that far.
  • Linux: not built or run.

Checklist

@github-actions

github-actions Bot commented Oct 14, 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
PR 5926 docs/dev/debt/libSceAgcDriver.md L21

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 1395 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 1896 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 4040 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 4448 docs/dev/debt/libSceAgcDriver.md
PR 4650 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 5499 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 5500 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 5761 docs/dev/debt/libSceAgcDriver.md
PR 5867 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 5881 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 5884 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 5925 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6177 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 6188 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6208 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 6222 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6235 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp

@xXPBSXx

xXPBSXx commented Oct 14, 2026

Copy link
Copy Markdown
Contributor

Kena: Bridge of Spirits (PPSA01746) stops on the throw this PR changes, with a V# of this kind. A local print in front of the Require(byteSize <= maxStorageBufferRange ...) in addGuestBuffer (not part of any PR; #5761's head 25cc5e6d2, fragment shader, binding 63, element 1 of 2, read only) gave words 00000000 00fff000 06f00000 00000000 byteSize 29679943680 limit 4294967295 stride 255 records 116391936 base f00000000000 (PPSA01746_rX/run_170224.err line 119, what(): AGC graphics: shader buffer exceeds descriptor range limit at line 122; the same words in run_171822.err line 116).

By the code: that base (0xf000_0000_0000) is not in the registered allocations, so RegisteredReadableEnd (GuestBufferMemory.cpp:2365) returns 0, the new branch sets byteSize = 0, and the slot gets the empty placeholder buffer instead of the throw. I did not run Kena with this PR, so I do not know whether the title then gets past this draw; it stopped at other places in other runs on the same head (buffer descriptor uses an unsupported type at ResourceMaterializer.cpp:590, and Vulkan result -4).

AI-assisted (Claude Code).

@xXPBSXx

xXPBSXx commented Oct 14, 2026

Copy link
Copy Markdown
Contributor

Tested on head e9c98900e (the current head of this pull request on GitHub, same SHA).

Kena: Bridge of Spirits (PPSA01746) gets past the shader buffer exceeds descriptor range limit throw that this change targets (one run).

  • Tree: main 278765a07 + this head (clean merge, tree 65dc50edc), no other changes. In the run (PPSA01746_rK5/run_200250.err, 805 lines, 240 s limit) there is no line with exceeds descriptor range (0 of 805). The run ends at line 121 with a different error: what(): AGC graphics: guest sampler descriptor uses unnormalized coordinates with anisotropic filtering, which is not implemented (line 119 [videoout] presentation failed: …, line 122 FATAL: abort()); that is a sampler gap, not related to this pull request.
  • For comparison, earlier runs of the title on other heads stopped at that throw: the log quoted in this thread (Test build: storage-image write-back fixes combined (do not merge) #5761's head, PPSA01746_rX/run_170224.err line 122, what(): AGC graphics: shader buffer exceeds descriptor range limit). I did not run main 278765a07 without this pull request, so the comparison is with those earlier runs, not with the same main.

Test conditions

  • Windows 10 (19045), MinGW-w64 GCC 15.2.0, Release. ninja -C build -j4 relinker plus all 126 core/libs/libs/*.prx of the merged tree, finished 20:01:54 local time (libSceAgcDriver.prx 20:01:45, relinker.exe 20:01:54).
  • Relink: relink_title_trace.ps1 -Id PPSA01746 -Repo <that tree> = relinker.exe --windows --registry --trace-imports from the converted inputs of the earlier PPSA01746_rX run (no -ModuleDir). Run: run_title.ps1 -Seconds 240, APS5_TRACE_CALLS=all.

Limits

One title, one run. Whether the draw behind the old throw is rendered correctly, I did not look at. This pull request's own tests were not run.

AI-assisted (Claude Code).

@xXPBSXx

xXPBSXx commented Oct 15, 2026

Copy link
Copy Markdown
Contributor

Teardown (PPSA15246) stops on the same throw class as Kena here, and with this PR it moves on to the next check instead of passing.

Without this PR (session B, main d92a8dad390af1807cc91622b924252141816a5a, PPSA15246_rR/run_110418.err lines 23-27): [gpu] driver failure: compute shader 0x1409cd300: AGC graphics: shader buffer exceeds descriptor range limit (the check in ShaderResources::addGuestBuffer), then FATAL: abort() (SIGABRT).

With this PR (head e9c98900e7c6c466381a3d99ed8d558b6d9f053f) on main e49ec591dc93c9e4dfaad8b6dbc0b995dd7830a0 (merge tree 76ee4db26da038be8c6ff1864f164ca44a9cf492), same title executable (PPSA15246_rR/app.exe, relinked 2026-10-15 09:54:01, hardlinked as PPSA15246_rY5/app.exe), same key plan as B (run_menu.log), 240 s requested: the addGuestBuffer throw is gone, and the same shader stops one check later, at line 31 and 33 of PPSA15246_rY5/run_122959.err (60 lines):

[videoout] presentation failed: compute shader 0x1409cd300: AGC graphics: guest buffer view exceeds descriptor range limit

(line 33 repeats it as what()).
That text comes from GuestBufferMemory::Descriptor (GuestBufferMemory.cpp:4061 on that main: Require(range <= context.limits.maxStorageBufferRange, ...)), which runs on the view that addGuestBuffer now hands out. So for this title the PR does not remove the stop; it only passes its own check. I did not print the V# or the sizes, so I do not know why the view is still past the limit; one possibility, not checked, is that the bound size ends within the view adjustment of the limit (ViewBytes adds the alignment adjustment to the size).

The window title shows the run was at FPS: 59.94 (804) before it stalled (FPS: 0.27 (842) to the end; send_keys_td5778.log).

Tested. Windows 10 (19045), MinGW-w64 GCC 15.2, Release, NVIDIA GeForce RTX 4080 SUPER. ninja -j 8 libs exit 0 (script times 12:19:10 to 12:28:13), run_title.ps1, one game at a time, script times 12:29:20 to 12:32:35 (includes the wait for the run mutex), one run, no local changes. Relinker commit and command for the executable are not recorded in my notes (made by session B). Not tested: Linux, other GPUs, a picture.

AI-assisted (Claude Code).

@adriadam10

Copy link
Copy Markdown
Collaborator

Checked on Linux (RADV): agc_driver_graphics passes with the change and fails without it, the rest of the libSceAgcDriver ctest scope is green apart from agc_driver_tessellation (RADV segfault, also on main). Both partial-allocation and unregistered cases are pinned, and the allocation-reaching-the-limit case still throws. Merging once the full Build is green.

@alfalfa-star

Copy link
Copy Markdown
Contributor

Title evidence on main after this PR: Kena: Bridge of Spirits (PPSA01802).

On main aa19278 (2026-10-14) Kena stopped before its first scene with AGC graphics: shader buffer exceeds descriptor range limit (a read-only V# with an unmapped base, see #5428). On plain main ce991f1 (includes this PR, no other changes, relinked with that build's relinker), one 150 s run:

  • It shows the Ember Lab logos, then the loading screen, then renders the 3D forest scene and keeps presenting it until the time limit (exit by timeout, no throw, no crash, no GPU reset).
  • The picture has a blown-out white glare over the middle of the scene and stretched vertical streaks in the upper half. No UI is visible in the dumped frames; no pad input was given, so nothing past this scene was tested.
  • No throws and no skipped draws or dispatches in the log; the only unsupported lines are 6 of Shader … has unsupported registered shader type 8; it is not prepared at registration.

Setup: Linux (Arch, kernel 7.2.9), GCC, Release, RX 9070 XT (RADV, Mesa 26.2.4). Diagnostics only: APS5_TRACE_SKIPS=1 APS5_DUMP_FRAMES=40 APS5_DUMP_FRAMES_EVERY=100.

AI-assisted (Claude Code).

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

Labels

agc libSceAgc* docs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants