Skip to content

perf(agc): keep adjacent ranges one import serves as one region of the cached address space - #4428

Merged
adriadam10 merged 1 commit into
boykopovar:mainfrom
hypermoist:perf/address-space-import-runs
Oct 13, 2026
Merged

adriadam10 merged 1 commit into
boykopovar:mainfrom
hypermoist:perf/address-space-import-runs

Conversation

@hypermoist

Copy link
Copy Markdown
Contributor

What

GuestBufferMemory::AcquireRegistered publishes a cached address space with one region per registered range, while one host import can serve a whole run of adjacent ranges (importRun). A V# that crosses the boundary between two such ranges is then not inside any one region, so the build dissolves the shared space into its own regions: on Killing Floor 3 (PPSA08427) that is about 10k regions copied, sorted and looked up, 700-1,300 times per 10 s at the title screen.

When the space is published, adjacent ranges served by the same import (same import, contiguous, same writability, no mirror, not sparse, inside the import) are kept as one region. A V# across them is inside that region and is bound in place from the import, the same binding a V# inside one range already gets.

Tested

Linux (CachyOS, kernel 7.2.9), RTX 3060 (NVIDIA 615.78.08), GCC 16.2.1, Release.

  • agc_driver_graphics gets a case (spaceImportRunTests in tests/BdaResources.cpp): two adjacent 64 KiB read-only ranges one import serves, and a V# across their boundary. On current main it fails (a V# across one import's ranges dissolved the cached address space); with this change the second build is a space hit and nothing dissolves.
  • Killing Floor 3 (PPSA08427, 02.011.000), on our fork with the same settings before and after: dissolved builds went from 694-1,260 to 0 per 10 s, the title screen from 15-25 to 34-36 presents per 10 s and the main menu from 17-21 to 31-35. The title does not run on main alone: it stops before its first frame at clip distances, layer, viewport or auxiliary vertex exports is unsupported (register 0x207 = 0x0040000f) (feat(agc): vertex clip and cull distances #423).

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

https://claude.ai/code/session_01Uzy15wqYTt6iWyxYXEzUWo

@hypermoist
hypermoist marked this pull request as ready for review October 12, 2026 11:03
@github-actions github-actions Bot added agc libSceAgc* needs rebase Conflicts with main, rebase needed labels Oct 12, 2026
@AlxcBTW

AlxcBTW commented Oct 12, 2026

Copy link
Copy Markdown
Contributor

@hypermoist I tested this on Sword of the Sea (PPSA25344) in the opening cutscene. In this scene, partial overlaps used to dissolve the cached address space in about a third of all address-based builds. With this PR the dissolves are gone.

Setup. Windows 11, RTX 5070 Laptop (616.92). Two 900 s in-scene rows, each a lab branch of main plus local patches for this title. The before-row has no #4428. The after-row has this PR cherry-picked unchanged, but it also carries other local changes: dispatch template relocation, a draw-path change and several experiments. So only the [address] dissolve counters below are attributable to this PR. One of those changes is a local overlay that also targets partial overlaps. It printed "0 overlays used" in every window of the after-row, so the counters come from this PR, not from it. No FPS claims.

[address], per 10 s, last 20 windows before (no #4428) after (with #4428)
address-based builds 1016 1894
space hits 1015 1893
dissolved: overlap 365 (max 429) 0 (max 0)
dissolved: overlap, whole row 25584 over 77 windows 0 over 72 windows

For context only: the before-row spent 132 s of 247 s of dispatch resource time in "resources: A locked (bda)", the locked stage A of address-based builds, which includes the dissolve and re-merge. The after-row spent 2 s of 78 s there (cumulative [dispatch] phase totals, APS5_PROFILE_DRAW=1). The other changes in the after-row also shrink resource time, so that ratio is not this PR's alone.

AI-assisted: yes (Claude Code)

@blawesom

Copy link
Copy Markdown
Contributor

Rebase handoff — rebased onto current main, authorship unchanged.

One test-file conflict with main's newer BDA tests: both sides add independent test functions at the same spot — kept main's failedImportRemapTests and this PR's spaceImportRunTests, with both called.

Verified on Linux (CachyOS, kernel 7.2.9, GCC 16.2.1, Ninja, Release, BUILD_TESTING=ON, AMD RX 9070 XT / RADV):

  • builds; tools/check_conventions.py --base origin/main passes
  • full suite: 952/952 passed

To pick it up:

git fetch https://github.com/blawesom/AnyPS5 rebase/4428
git checkout <your branch>
git merge --ff-only FETCH_HEAD

Head is fd7ce3ff2.

…e cached address space

A V# spanning two registered ranges dissolved the shared space into the
build's own regions (about 10k regions copied, sorted and looked up per
build in Killing Floor 3), although the import covering the run binds it
in place.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uzy15wqYTt6iWyxYXEzUWo
@hypermoist
hypermoist force-pushed the perf/address-space-import-runs branch from e42cfad to 6bf9ab8 Compare October 13, 2026 06:03
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 13, 2026
@github-actions

github-actions Bot commented Oct 13, 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
#4448 core/libs/prx/libSceAgcDriver/tests/BdaResources.cpp L177, L1204-1205
#4979 core/libs/prx/libSceAgcDriver/tests/BdaResources.cpp L1204

@TideOPL

TideOPL commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

Tested on Minecraft Dungeons II (PPSA16064) gameplay at the Squid Coast spawn: Windows 11, RTX 5070, trace window 25-40 s after the HUD (#4526 trace, APS5_TRACE_SECONDS=25:15). Base: main + #4367 #4515 #4517 + #3816 + #425 + #3763 + local patches MCD2 needs.

On MCD2 this removes a run-to-run bimodality. In about half the runs, about 4 address-based dispatches per frame dissolved the cached space ([address] dissolved: overlap, about 320 per 10 s): a V# crosses the boundary of two adjacent registered ranges that one joined import (#4517) serves. Each dissolved build then sorts and merges about 1,200 regions (sort ~630 us + merge ~730 us + bindings ~650 us). With this PR (together with #4248) there are no dissolves in any run.

Together with #4248, #4012 and #4603, interleaved, 3 runs each: p50 118.6 / 130.6 / 129.1 ms -> 110.9 / 110.8 / 111.9 ms, p99 127-141 -> 121-127 ms.

Not run: Linux, AMD, the PR's own tests.

AI-assisted (Claude Code).

@adriadam10

Copy link
Copy Markdown
Collaborator

Checked the region merge in AcquireRegistered (same import, contiguous, same writability, no mirror, not sparse, inside the import; order preserved), the new spaceImportRunTests case (fails without the change, passes with it) and the libSceAgcDriver ctest scope on RADV; also confirmed by @AlxcBTW and @TideOPL on real titles. Merging once the full build is green.

@adriadam10
adriadam10 merged commit 759c665 into boykopovar:main Oct 13, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agc libSceAgc*

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants