Skip to content

perf(agc): stage read and written buffer elements a dispatch sweeps - #2681

Merged
oneandonlydean merged 2 commits into
boykopovar:mainfrom
oneandonlydean:up2/swept-buffer-staging
Oct 10, 2026
Merged

oneandonlydean merged 2 commits into
boykopovar:mainfrom
oneandonlydean:up2/swept-buffer-staging

Conversation

@oneandonlydean

Copy link
Copy Markdown
Collaborator

What

A written V# element bound in place in a host import makes every load a PCIe round trip. In one title's particle update, a kernel loads and stores a 10 MiB pool (2048x64 threads over 131072 records of 80 bytes). That is above the 2 MiB written window, so it stayed in place and took about 4.8 ms of GPU per frame.

Two commits:

  1. feat(shader): DescriptorBinding gains bufferRead next to bufferWritten and bufferAtomic, filled from the resource tracker's existing per-buffer read flag. It is kept in the shader disk cache, which bumps the format to 24. No key or ABI change.
  2. perf(agc): an element is now staged in device-local memory up to 16 MiB when all of these hold:
    • the shader also reads it;
    • it is written by a direct dispatch;
    • the dispatch's threads times the V# stride cover at least half of it.

The coverage test keeps a kernel that updates about 12k records of a 16 MiB pool in place: staging all of it would cost about 1.3 ms of copies for a 0.08 ms kernel. Write-only elements, indirect dispatches and raw (stride 0) buffers keep the 2 MiB window.

Tested

  • Linux (CachyOS, x86-64, GCC, RTX 4090), Release with BUILD_TESTING=ON: ctest -R "agc|shader" passes 320/321. The one failure, agc_driver_dcc_keys_first_write, fails the same way on current main.
  • agc_shader_disk_cache_tests: bufferRead survives the disk cache round trip and the binding plan.
  • agc_driver_recorder_tests, new readWrittenStagingTests, run on its own on the RTX 4090 (the full binary stops earlier on main with a 60 s lease wait, unrelated):
    • a read and written 4 MiB element is staged;
    • the same element written only stays in place;
    • a dispatch touching 16 KiB of it, or of unknown size, keeps it in place;
    • copy-backs leave the guest bytes unchanged.
  • Astro Bot (PPSA21564), measured on our fork, which carries the same change: the particle update 0x500779a00 went from about 4.8 ms of GPU per frame to 0.06 ms plus about 0.9 ms of copies.

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 (Claude Code)

DescriptorBinding gains bufferRead next to bufferWritten and bufferAtomic,
filled from the resource tracker's per-buffer read flag and kept in the
shader disk cache (format 24).
A written V# element bound in place in a host import makes every load a
PCIe round trip. A particle update that loads and stores a 10 MiB pool
(2048x64 threads over 131072 records of 80 bytes), above the 2 MiB written
window, took about 4.8 ms of GPU per frame.

An element the shader also reads (DescriptorBinding::bufferRead), written by
a direct dispatch whose threads times the V# stride cover at least half of
it, now takes device-local staging up to 16 MiB: that dispatch drops to
about 0.06 ms plus 0.9 ms of bulk copies. The coverage test keeps a kernel
that updates about 12k records of a 16 MiB pool in place, where staging all
of it would cost 1.3 ms of copies for a 0.08 ms kernel. Write-only
elements, indirect dispatches and raw (stride 0) buffers keep the 2 MiB
window.
@github-actions

github-actions Bot commented Oct 10, 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
#757 core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp L44
core/shader/recompiler/ShaderDiskCache.cpp L68-70
core/shader/recompiler/ShaderDiskCache.hpp L15
#758 core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp L44
core/shader/recompiler/ShaderDiskCache.cpp L68-70
core/shader/recompiler/ShaderDiskCache.hpp L15
#822 core/shader/recompiler/ShaderDiskCache.hpp L15

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

Labels

agc libSceAgc* shader core/shader

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant