Skip to content

fix(agc): reclaim idle device buffers up to the storage cache's current cap - #10551

Open
JJenkx wants to merge 1 commit into
boykopovar:mainfrom
JJenkx:perf/agc-storage-reclaim-ceiling
Open

JJenkx wants to merge 1 commit into
boykopovar:mainfrom
JJenkx:perf/agc-storage-reclaim-ceiling

Conversation

@JJenkx

@JJenkx JJenkx commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

What

#8672 reclaims idle device-tier buffers from the buffer pool when the storage image cache needs more room than its budget gives. The amount is capped at a ceiling: the most the cache may hold. Its debt entry describes this as "the cache's shortfall below its existing ceiling". In storageBudget the ceiling is computed as max(512 MiB, min(TextureCacheBudget, budget / 4)), which is a copy of the storage cache's cap before #10044.

#10044 raised that cap to min(heap / 2, budget / 2) in StorageTextureBudget, but the copy in storageBudget was not updated. On main the two now disagree. When the cache's shortfall lies between a quarter and half of the budget, idle pooled buffers are no longer reclaimed for it, although StorageTextureBudget would let the cache grow into the room they free. Example: an 8 GB GPU with a 6 GiB budget. The cap is 3 GiB, but reclaim stops at 1.5 GiB.

This PR moves the cap into one function, StorageTextureCeiling, used by both StorageTextureBudget and the reclaim ceiling. It returns max(512 MiB, min(heap / 2, budget / 2)), or TextureCacheBudget without VK_EXT_memory_budget. StorageTextureBudget returns the same values as before: min(max(512 MiB, cap), max(512 MiB, free)) equals max(512 MiB, min(cap, free)). The only behavior change is the reclaim ceiling.

Tested

  • storageTextureBudgetTests adds checks for the ceiling: a quarter of the heap without VK_EXT_memory_budget, half of a 6 GiB budget, half of the heap for a 40 GiB budget, and the 512 MiB floor. A sweep over budgets (1-24 GiB) and usage checks that the storage budget never exceeds the ceiling, and that an idle heap reaches it.

  • Focused Vulkan gate. Machine: Linux 7.2.9, RX 6650 XT, RADV (Mesa 26.2.4). Command: ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation VK_LOADER_DEBUG=layer ctest -V -j1 -R '^(agc_driver_graphics|agc_buffer_pool.*|agc_driver_sampled_cache_budget_.*)$'.

    arm head result validation layer inserted VUIDs
    main aeeaefad98 6/6 2 tests 0
    this change with the ceiling forced back to a quarter of the budget cc90fbcb7c + one-line edit 5/6: agc_driver_graphics fails with "a 10 GiB budget on the 16 GiB heap does not limit the storage image cache to half of the budget" 2 tests 0
    this change cc90fbcb7c 6/6 2 tests 0

    The head was then rebased on 5d3ab7791d without conflict. None of the four files it touches differ between aeeaefad98 and 5d3ab7791d.

  • Logs: https://github.com/JJenkx/AnyPS5/releases/tag/storage-reclaim-ceiling-evidence

  • This PR makes no performance claim. A title measurement that exercises the changed reclaim condition remains outstanding; the independent Windows report below did not reach it.

  • Related measurement, from a diagnostic and not this change. On the same GPU at its real reported budget (about 6 GiB), shrinking the pool's device and image tiers by override raised the storage cache budget in Echoes from 0.5-0.9 GiB to 1.6-2.2 GiB. That suggests idle pool retention competes with the storage cache there. The throughput effect was within run-to-run spread.

Independent Windows/NVIDIA coverage reported by @Rajkamalcode: exact head 0d6a6f96eeee90b4998deaadae50ef5e3cf01a53 merged onto main 5ed5427ba as 469b28f11, Ryzen 5 5600X / 16 GB RAM, RTX 3070 8 GB, driver 32.0.16.1088, Windows 11 22635. Their focused graphics executable passed, including the StorageTextureCeiling cases. Validation-layer use was not reported for that Windows run; the local layered Linux comparison above remains scoped separately.

Their two 360-second Squirrel with a Gun (PPSA22102, 01.000.000) runs used the same pad schedule/cache/settings and had no fatal/OOM, with 39–41 presents per 10 seconds after load in both arms. The sampled storage cache stayed below its budget and both runs reported zero device-pool evictions, so the changed reclaim branch was not exercised. Pool retention and images-phase differences from that single pair do not establish a benefit. This is attributed independent coverage, not a locally reproduced run or performance evidence.

Checklist

🤖 Generated with Claude Code

…nt cap

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added the agc libSceAgc* label Oct 24, 2026
@github-actions

github-actions Bot commented Oct 24, 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 10194 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp L626-630

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 4040 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 5441 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 5925 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6192 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 6194 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6202 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 6223 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 6235 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6280 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6412 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 6481 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6498 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 6548 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6808 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 7002 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 7256 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 7410 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 7642 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 7689 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 7844 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 8246 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 8998 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 9020 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9335 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9356 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9387 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9400 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 9489 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9592 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 9674 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 9675 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9700 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9748 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9897 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 10049 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 10064 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 10193 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 10435 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 10442 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp

@MarcZX10 MarcZX10 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.

Reviewed the ceiling calculation and its use in both cache budgeting and idle-buffer reclamation. The shared StorageTextureCeiling preserves the former StorageTextureBudget cap/floor behavior while removing the stale quarter-budget reclaim limit; the added sweep checks the invariant across heap budgets and usage levels. The contributor reports the focused Vulkan suite passing 6/6 with validation enabled on RADV, including a one-line mutation that makes the expected half-budget case fail. I did not rerun the GPU test locally.

@Rajkamalcode

Copy link
Copy Markdown
Contributor

Independent Windows/NVIDIA check of the reclaim-ceiling fix at head 0d6a6f96, merged into current main 5ed5427ba (469b28f11). I do not have a performance claim for this title; this is a no-regression and coverage check.

Measured

Environment: Ryzen 5 5600X, 16 GB RAM, RTX 3070 8 GB, driver 32.0.16.1088, Windows 11 22635. Squirrel with a Gun PPSA22102, content 01.000.000, stock ini 0156186E, VSync on, guest 3840x2160 presented at 727x409. Both arms: 360 s, same pad schedule, same shader cache, no texture-cache override.

5ed5427ba control 0d6a6f96 merged on 5ed
driver SHA-256 BD92C0DB4A5C8853F5F4A44816F15ED2A8CF9B32EF6E872D6B5C96251D4A4AF1 9CB80316D70E56C8C51B1A90E5BBB2F5DE5D3E322E10227B34B430BA567F0759
storage images created (final) 381 375
images phase (final) 2,141 ms 3,101 ms
resource builds (final) 158,012 142,228
presents after load (per 10 s) 39-41 39-41
storage image cache budget (final sample) 3,257 MiB 3,384 MiB
cached storage images (final sample) 2,837 MiB 2,935 MiB
idle device pool retained (final) 438 MiB of 906 353 MiB of 906
fatal/OOM none none

Focused test on this machine: agc_driver_graphics_tests.exe with ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 passed in 8.79 s, including the new StorageTextureCeiling cases.

Logs: swag-run55-err.log (control), swag-run56-err.log (head), test-agc-driver-graphics-pr10551-on-5ed.log.

Analysis (AI-assisted)

The title did not reach the condition this PR changes in either arm. The storage cache stayed below the reported storage budget in the sampled windows, and the buffer pool reported 0 device evictions in both runs. The lower device retention in the head run (353 vs 438 MiB) is not attributable to the change from one pair. The images-phase and build differences are also within the large run-to-run spread this title shows; I am not treating them as an effect.

So: no observable SWAG benefit, and no regression in this check. The fix is not exercised by this title under normal memory pressure. The Echoes of the End pair remains the better place for a throughput result, or a controlled lower-budget diagnostic would be needed if you want the reclaim branch itself exercised.

AI-assisted report. Measured data and interpretation are separated above.

@JJenkx

JJenkx commented Oct 24, 2026

Copy link
Copy Markdown
Contributor Author

Recorded your exact-head Windows/NVIDIA report in Tested with its limits: no fatal/OOM in the reported pair, but the title stayed below its storage budget and never exercised the changed reclaim branch. The observed pool/timing differences are not a performance result, and I have not treated unreported Windows validation-layer coverage as a clean validation run. The stale queued-pair wording is replaced with the specific outstanding measurement. The existing layered Linux gate and deterministic ceiling/negative-control checks remain separate.

This branch has not been deployed

No deployments
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.

4 participants