Skip to content

perf(agc): reclaim idle device buffers under storage cache pressure - #8672

Merged
adriadam10 merged 4 commits into
boykopovar:mainfrom
eliasbruno124-dev:fix/cold-device-storage-pressure-20261020
Oct 23, 2026
Merged

adriadam10 merged 4 commits into
boykopovar:mainfrom
eliasbruno124-dev:fix/cold-device-storage-pressure-20261020

Conversation

@eliasbruno124-dev

@eliasbruno124-dev eliasbruno124-dev commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

What

The storage-image cache can repeatedly evict surfaces while the device-buffer pool retains allocations the title has stopped using. GTA III reproduces this below the reported heap budget, where over-budget trimming does not apply.

On storage admission pressure, reclaim independently allocated device buffers unused during a complete one-second observation interval, oldest first and bounded by the admission shortfall. Reread the driver's budget after an actual release; the existing storage-budget formula, reserve, caps and forced-budget override remain in charge. Active buffers, host tiers, slabs, retained image allocations and recently reused buffers are protected. No fixed small pool cap is introduced.

Reclamation requires one device-local heap because retained buffers do not record their heap. The one-second retention choice and unmeasured effects on intermittent reuse are documented in technical debt.

Scope/order agreed with #4472 and #7833: cold-buffer release first; those branches rebase around it. This does not implement #6194's budget growth or #7833's in-flight image retention.

Tested

Current rebase validation

Head b996e31d8c11956df72031e42d286e4682ebe1fe is rebased linearly onto 777bdbb4f80bcc03e870dfda0d292c0c6410fd6a, including the updated #8527 review correction (equivalent patches to its a0ecec3d3 head). The header conflict retains upstream AgcDriver::Mutex and the idle-clock fields. The reclaim policy and retained-image exclusion are unchanged.

On the Windows/NVIDIA system below, complete runtimes were built for that main and this head. The same 26 focused tests passed on both with ANYPS5_REQUIRE_VULKAN=1, ANYPS5_NO_SHADER_CACHE=1, real Khronos synchronization validation and ctest -V -j1 --timeout 30. Neither run skipped a case or missed the layer. Main nevertheless logged 26 synchronization errors in four tests: agc_import_settle_first_use, agc_import_settle_earlier_import, agc_storage_split_writeback and agc_driver_storage_write_back_overhang. This head logged none. These ordering corrections come from #8527, not the cold-buffer policy. Longest cases: 14.4429s on main and 12.9777s on this head.

The three additional #8527 cases (write_order, write_order_other_family and wait_failure) also passed on this head without skips or validation errors. Conventions and whitespace checks pass. Pre-push main 8eb8e3920 was inspected and merges cleanly; it was not the tested runtime. Linux and AMD/Intel were not tested locally.

The earlier mixed-pool regression fails without the retained-image exclusion and passes with it; image reuse, an image-only pool, repeated empty scans and exact cleanup remain covered. The title measurements below remain evidence for their explicitly named earlier commits. No new gameplay or performance measurement is claimed for this rebase.

Original title measurements

Windows 10.0.26300, i5-11400H, 32 GiB RAM, NVIDIA RTX 3060 Laptop GPU (6 GiB), driver 617.42. Original GTA III PPSA03527/01.003.000, 3840x2160, stationary first-mission spawn at Callahan Bridge with Claude, Kuruma, HUD and radar.

Pinned main 434e965d4620c48e315b25fb869a2d84b39cfb2d plus the unchanged #8527 dependency gives baseline 9552b5e2ccbb297dccd3aba7d8df631bfa9094de; candidate a6c415f7ad63de979e16e39c898c0846ab34465c adds only this policy. Both use the same warmed cache/private-save seed and automatic navigation, default pools, complete runtimes and 61 verified loaded PRXs. Original metadata remained unchanged. No storage error occurred.

APS5_TRACE_FRAMES=4440:10 captures ten presents per side. Startup-only image exports ended at present 4410; navigation ended before that. No readbacks or input during capture, no additional TRACE/PROFILE options, no redirected game logs. Both traces are complete with no dropped events. The short window is corroborated by longer profiled diagnostics below; it is not a claim of steady gameplay or a general FPS gain.

Metric Baseline Candidate
Frame p50 587.394 ms 374.071 ms
Frame p90/p99/max 705.173 ms 400.796 ms
GPU busy per present 298.705 ms 293.601 ms
Capture duration / presents 5988.938 ms / 10 3739.319 ms / 10

Median frame time fell 36.3%; p90 fell 43.2%. The scene remains slow (about 1.67 vs 2.67 presents/s across these short captures). Driver.Packet.memory_wait fell from 517.818 to 166.197 ms/frame, inclusive; overlapping phases must not be added. GPU work remains substantial.

Earlier paired 98.9/113.6-second diagnostic windows used profiling/readbacks: median logical storage-cache eviction writeback 10272.9 MiB/interval -> 0, retained device pool 586 ->298 MiB. Candidate released 348.875 MiB before and 111.5 MiB within the window; neither side acquired new device-pool allocations between the window's first/last counter rows. These are mechanism observations, not additional clean FPS measurements.

Both pinned runtimes pass the same 28 focused native cases using ctest -V, ANYPS5_REQUIRE_VULKAN=1, ANYPS5_NO_SHADER_CACHE=1, and the real VK_LAYER_KHRONOS_validation with synchronization validation. No missing-layer warning, VUID error or skipped case; longest cases 14.8167s baseline / 13.9844s candidate. Candidate regressions cover bounded release, repeated 384 MiB reuse, active/host/slab protection, allocation failure while collecting releases, backwards time, unsupported heaps and avoiding repeated empty scans. Conventions pass. Linux and AMD/Intel remain untested locally.

Both complete trace_digest.py outputs, including the raw aps5-summary.jsonl records, follow. The archive contains both raw traces, summary files and digests: gta3-cold-buffer-traces.zip

Baseline: complete trace digest and summary

frames 4440:10 from present 4440: 10 presents, frame p50 587.4 / p90 705.2 / p99 705.2 / max 705.2 ms, GPU busy 298.7 ms per present
NVIDIA GeForce RTX 3060 Laptop GPU, NVIDIA 617.42, Windows 10.0.26300, 3840x2160, commit 9552b5e, dropped: no

{"commit":"9552b5e2ccbb","dirty":false,"env":{"APS5_DUMP_FRAMES":"147","APS5_DUMP_FRAMES_EVERY":"30","APS5_DUMP_SCALE":"4","APS5_LAZY_SHADER_PREPARE":"1","APS5_NO_PAD_INPUT":"1","APS5_PAD_INPUT_FILE":"<path>","APS5_PIPELINE_JOURNAL_THREADS":"2","APS5_TRACE_FRAMES":"4440:10"},"gpu":"NVIDIA GeForce RTX 3060 Laptop GPU","driver":"NVIDIA 617.42","os":"Windows 10.0.26300","cpu":"11th Gen Intel(R) Core(TM) i5-11400H @ 2.70GHz","cpu_threads":12,"memory_mib":32509,"title_id":"PPSA03527","title":"Grand Theft Auto III \u00e2\u0080\u0093 The Definitive Edition","content_version":"01.003.000","resolution":"3840x2160","window":{"spec":"frames 4440:10","first_present":4440,"ms":5988.938},"presents":10,"frame_ms":{"p50":587.394,"p90":705.173,"p99":705.173,"max":705.173},"gpu_busy_ms_per_present":298.705,"worker_busy_pct":{"queue worker 0x0":99.262,"queue worker 0x20":89.756},"top_phases_ms_per_frame":{"Driver.Packet":1129.534,"Driver.Packet.memory_wait":517.818,"Graphics.Draw":321.549,"Graphics.Draw.draw_and_resource_release":302.126,"Driver.Packet.device_lock":249.122,"Driver.Packet.dispatch":216.385,"Resources.Complete":212.253,"Driver.Dispatch":204.801},"trace_dropped":false,"trace":"aps5-trace-9552b5e2ccbb-22520.json.gz"}

Slowest frames (largest slices inside each, inclusive)

  • present 4449: 705.2 ms at 5284 ms: Driver.Packet (queue worker 0x0) 681.5, Driver.Packet (queue worker 0x20) 405.2, Graphics.Draw (draw committer) 388.0, Driver.Packet.memory_wait (queue worker 0x20) 387.0
  • present 4448: 648.7 ms at 4635 ms: Driver.Packet (queue worker 0x20) 646.1, Driver.Packet (queue worker 0x0) 626.7, Driver.Packet.memory_wait (queue worker 0x20) 626.6, batch (gpu) 382.2
  • present 4442: 636.9 ms at 1150 ms: Driver.Packet (queue worker 0x20) 634.2, Driver.Packet (queue worker 0x0) 619.7, Driver.Packet.memory_wait (queue worker 0x20) 599.1, Graphics.Draw (draw committer) 342.5
  • present 4447: 633.6 ms at 4001 ms: Driver.Packet (queue worker 0x20) 630.3, Driver.Packet (queue worker 0x0) 616.5, Driver.Packet.memory_wait (queue worker 0x20) 613.3, Graphics.Draw (draw committer) 317.9
  • present 4440: 587.4 ms at 0 ms: Driver.Packet (queue worker 0x0) 571.0, batch (gpu) 305.9, Graphics.Draw (draw committer) 288.8, Driver.Packet (queue worker 0x20) 271.6

Threads (ms per frame)

thread busy wait untraced in slices < 20 us largest
queue worker 0x0 577.6 (96 %) 4.6 (1 %) 16.7 69.8 Driver.Packet 581.1, Driver.EndSubmission 1.1
draw committer 344.9 (58 %) 21.5 (4 %) 232.4 13.4 Graphics.Draw 318.6, Recorder.Sync 30.2
presenter 1.9 (0 %) 0.2 (0 %) 596.8 0.1 VideoOut.Flip 2.0, Driver.Present 0.1
queue worker 0x20 14.3 (2 %) 523.2 (87 %) 61.3 0.1 Driver.Packet 536.1, Driver.EndSubmission 1.4
gpu 315.4 (53 %) 0.0 (0 %) 283.5 0.0 batch 315.4

Largest slices (ms per frame, inclusive, all threads): Driver.Packet 1117.2, Driver.Packet.memory_wait 517.8, Graphics.Draw 319.0, batch 315.4, Graphics.Draw.draw_and_resource_release 297.2, Driver.Packet.device_lock 245.2, Driver.Packet.dispatch 216.3, Resources.Complete 212.1, Driver.Dispatch 204.7, Vulkan.Dispatch 158.2

Longest waits

  • Driver.Packet.memory_wait (queue worker 0x20) 670.4 ms at 4341 ms, present 4447
  • Driver.Packet.memory_wait (queue worker 0x20) 637.4 ms at 5033 ms, present 4448
  • Driver.Packet.memory_wait (queue worker 0x20) 568.1 ms at 327 ms, present 4440
  • Driver.Packet.memory_wait (queue worker 0x20) 559.7 ms at 3761 ms, present 4446
  • Driver.Packet.memory_wait (queue worker 0x20) 552.5 ms at 3197 ms, present 4445
  • Driver.Packet.memory_wait (queue worker 0x20) 536.3 ms at 1548 ms, present 4442
  • Driver.Packet.memory_wait (queue worker 0x20) 535.9 ms at 2646 ms, present 4444
  • Driver.Packet.memory_wait (queue worker 0x20) 513.9 ms at 2097 ms, present 4443
  • Driver.Packet.memory_wait (queue worker 0x20) 322.0 ms at 907 ms, present 4441
  • Driver.Packet.memory_wait (queue worker 0x20) 281.4 ms at 1241 ms, present 4442

Largest GPU batches (GPU ranges inside, and the CPU slices that recorded each, inclusive)

  • batch 902: 47.5 ms at 4242 ms, present 4447: GPU no ranges; recorded by Graphics.Draw (draw committer) 3.8, Graphics.Draw.draw_and_resource_release (draw committer) 2.6, Graphics.Draw.validate (draw committer) 0.5, Resources.Complete (draw committer) 0.3
  • batch 780: 45.3 ms at 3670 ms, present 4446: GPU no ranges; recorded by Graphics.Draw (draw committer) 3.5, Graphics.Draw.draw_and_resource_release (draw committer) 2.4, Resources.Complete (draw committer) 0.4, Graphics.Draw.validate (draw committer) 0.3
  • batch 539: 44.4 ms at 2565 ms, present 4444: GPU no ranges; recorded by Graphics.Draw (draw committer) 3.6, Graphics.Draw.draw_and_resource_release (draw committer) 2.5, Graphics.Draw.validate (draw committer) 0.4, Resources.Complete (draw committer) 0.3
  • batch 49: 43.7 ms at 240 ms, present 4440: GPU no ranges; recorded by Graphics.Draw (draw committer) 4.1, Graphics.Draw.draw_and_resource_release (draw committer) 2.7, Graphics.Draw.validate (draw committer) 0.7, Resources.Complete (draw committer) 0.3
  • batch 168: 42.8 ms at 816 ms, present 4441: GPU no ranges; recorded by Graphics.Draw (draw committer) 4.2, Graphics.Draw.draw_and_resource_release (draw committer) 2.8, Graphics.Draw.validate (draw committer) 0.7, Resources.Complete (draw committer) 0.4
Candidate: complete trace digest and summary

frames 4440:10 from present 4440: 10 presents, frame p50 374.1 / p90 400.8 / p99 400.8 / max 400.8 ms, GPU busy 293.6 ms per present
NVIDIA GeForce RTX 3060 Laptop GPU, NVIDIA 617.42, Windows 10.0.26300, 3840x2160, commit a6c415f, dropped: no

{"commit":"a6c415f7ad63","dirty":false,"env":{"APS5_DUMP_FRAMES":"147","APS5_DUMP_FRAMES_EVERY":"30","APS5_DUMP_SCALE":"4","APS5_LAZY_SHADER_PREPARE":"1","APS5_NO_PAD_INPUT":"1","APS5_PAD_INPUT_FILE":"<path>","APS5_PIPELINE_JOURNAL_THREADS":"2","APS5_TRACE_FRAMES":"4440:10"},"gpu":"NVIDIA GeForce RTX 3060 Laptop GPU","driver":"NVIDIA 617.42","os":"Windows 10.0.26300","cpu":"11th Gen Intel(R) Core(TM) i5-11400H @ 2.70GHz","cpu_threads":12,"memory_mib":32509,"title_id":"PPSA03527","title":"Grand Theft Auto III \u00e2\u0080\u0093 The Definitive Edition","content_version":"01.003.000","resolution":"3840x2160","window":{"spec":"frames 4440:10","first_present":4440,"ms":3739.319},"presents":10,"frame_ms":{"p50":374.071,"p90":400.796,"p99":400.796,"max":400.796},"gpu_busy_ms_per_present":293.601,"worker_busy_pct":{"queue worker 0x0":98.964,"queue worker 0x20":94.925},"top_phases_ms_per_frame":{"Driver.Packet":723.913,"Driver.Packet.dispatch":263.692,"Recorder.Sync":201.478,"Driver.Packet.device_lock":193.149,"Driver.Packet.memory_wait":166.197,"Graphics.Draw":85.945,"Driver.Packet.draw":76.704,"Driver.Draw":75.787},"trace_dropped":false,"trace":"aps5-trace-a6c415f7ad63-32836.json.gz"}

Slowest frames (largest slices inside each, inclusive)

  • present 4447: 400.8 ms at 2590 ms: Driver.Packet (queue worker 0x20) 400.5, Driver.Packet (queue worker 0x0) 382.4, batch (gpu) 348.8, Recorder.Sync (draw committer) 216.5
  • present 4445: 385.4 ms at 1823 ms: Driver.Packet (queue worker 0x20) 385.0, Driver.Packet (queue worker 0x0) 366.1, batch (gpu) 333.4, Recorder.Sync (draw committer) 203.0
  • present 4446: 381.8 ms at 2209 ms: Driver.Packet (queue worker 0x20) 381.5, Driver.Packet (queue worker 0x0) 363.3, batch (gpu) 328.9, Recorder.Sync (draw committer) 197.3

Threads (ms per frame)

thread busy wait untraced in slices < 20 us largest
queue worker 0x0 356.1 (95 %) 0.1 (0 %) 17.7 78.6 Driver.Packet 355.4, Driver.EndSubmission 0.9
draw committer 286.5 (77 %) 1.1 (0 %) 86.3 18.0 Recorder.Sync 199.2, Graphics.Draw 81.4
presenter 1.2 (0 %) 0.7 (0 %) 372.1 0.1 VideoOut.Flip 1.7, Driver.Present 0.1
queue worker 0x20 180.2 (48 %) 174.7 (47 %) 18.9 0.1 Driver.Packet 354.7, Driver.EndSubmission 0.2
gpu 324.8 (87 %) 0.0 (0 %) 49.1 0.0 batch 324.8

Largest slices (ms per frame, inclusive, all threads): Driver.Packet 710.1, batch 324.8, Driver.Packet.dispatch 263.6, Recorder.Sync 201.5, Driver.Packet.device_lock 189.2, Driver.Packet.memory_wait 166.1

Longest waits

  • Driver.Packet.memory_wait (queue worker 0x20) 199.5 ms at 2149 ms, present 4445
  • Driver.Packet.memory_wait (queue worker 0x20) 194.4 ms at 2535 ms, present 4446
  • Driver.Packet.memory_wait (queue worker 0x20) 183.3 ms at 1405 ms, present 4443
  • Driver.Packet.memory_wait (queue worker 0x20) 181.9 ms at 2937 ms, present 4447
  • Driver.Packet.memory_wait (queue worker 0x20) 181.7 ms at 1770 ms, present 4444
  • Driver.Packet.memory_wait (queue worker 0x20) 181.6 ms at 681 ms, present 4441

Largest GPU batches (GPU ranges inside, and the CPU slices that recorded each, inclusive)

  • batch 499: 71.1 ms at 2060 ms, present 4445: GPU no ranges; recorded by Graphics.Draw (draw committer) 4.0, Graphics.Draw.draw_and_resource_release (draw committer) 2.0, Graphics.Draw.validate (draw committer) 1.4, Recorder.Submit (draw committer) 0.1
  • batch 688: 67.6 ms at 2852 ms, present 4447: GPU no ranges; recorded by Graphics.Draw (draw committer) 3.4, Graphics.Draw.draw_and_resource_release (draw committer) 2.1, Graphics.Draw.validate (draw committer) 0.6, Recorder.Submit (draw committer) 0.1
  • batch 595: 65.8 ms at 2452 ms, present 4446: GPU no ranges; recorded by Graphics.Draw (draw committer) 3.8, Graphics.Draw.draw_and_resource_release (draw committer) 2.2, Graphics.Draw.validate (draw committer) 0.8, Recorder.Submit (draw committer) 0.1

Fresh pre-publication main 50e0624d7a902d1083368fafee4a019a10296e1e is checked separately for conflicts and changed inputs; it is not the commit measured above.

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 under Silent stubs in their library's technical debt file
  • 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: fix(agc): order deferred import settles with main-queue accesses #8527
  • Fixes: none
  • Unblocks: none
  • GPUs tested: NVIDIA RTX 3060 Laptop GPU, driver 617.42, Windows 10.0.26300
  • AI-assisted: yes

@github-actions github-actions Bot added perf Performance change perf numbers missing perf pull request without a before and after summary line labels Oct 20, 2026
@github-actions

Copy link
Copy Markdown

This pull request is labeled perf, so it needs the summary line of a capture on main and one with the change, from the same title, scene and machine, as the Performance report form asks. Please paste both aps5-summary.jsonl lines, attach the two traces and add the output of tools/trace_digest.py.

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

I reviewed the reclaim policy and its call site. Take advances the pool clock, so entries reused during the one-second observation window are newer than reclaimBefore; active allocations are absent from the free tier, and slab allocations are explicitly excluded. The operation removes pool bookkeeping under the mutex and destroys Vulkan allocations after releasing it. The one-device-local-heap guard matches the implementation's lack of per-allocation heap tracking, and the budget is reread only after an actual release.

The PR description reports focused Vulkan validation with synchronization validation and paired traces for the same Windows/NVIDIA scene, while clearly limiting the performance claim to that scene. Hosted platform jobs are skipped, so this approval relies on the author's detailed run report rather than an independent build or GPU run here.

@github-actions

github-actions Bot commented Oct 20, 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 8419 docs/dev/debt/libSceAgcDriver.md L106
PR 10194 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp L11, L617-624
core/libs/prx/libSceAgcDriver/tests/BufferPool.cpp L1015

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 2434 docs/dev/debt/libSceAgcDriver.md
PR 4448 docs/dev/debt/libSceAgcDriver.md
PR 4472 core/libs/prx/libSceAgcDriver/Graphics/include/BufferPool.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/BufferPool.cpp
core/libs/prx/libSceAgcDriver/tests/BufferPool.cpp
PR 5058 docs/dev/debt/libSceAgcDriver.md
PR 5925 docs/dev/debt/libSceAgcDriver.md
PR 6186 docs/dev/debt/libSceAgcDriver.md
PR 6192 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 6194 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6202 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 6223 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6273 docs/dev/debt/libSceAgcDriver.md
PR 6280 docs/dev/debt/libSceAgcDriver.md
PR 6300 docs/dev/debt/libSceAgcDriver.md
PR 6412 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6481 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6548 docs/dev/debt/libSceAgcDriver.md
PR 6549 docs/dev/debt/libSceAgcDriver.md
PR 6808 docs/dev/debt/libSceAgcDriver.md
PR 6867 docs/dev/debt/libSceAgcDriver.md
PR 6970 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 6977 docs/dev/debt/libSceAgcDriver.md
PR 7256 docs/dev/debt/libSceAgcDriver.md
PR 7307 docs/dev/debt/libSceAgcDriver.md
PR 7449 docs/dev/debt/libSceAgcDriver.md
PR 7484 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 7604 docs/dev/debt/libSceAgcDriver.md
PR 7618 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7642 core/libs/prx/libSceAgcDriver/Graphics/include/BufferPool.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/BufferPool.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7689 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 7833 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 7844 docs/dev/debt/libSceAgcDriver.md
PR 7893 docs/dev/debt/libSceAgcDriver.md
PR 7910 docs/dev/debt/libSceAgcDriver.md
PR 8014 docs/dev/debt/libSceAgcDriver.md
PR 8223 docs/dev/debt/libSceAgcDriver.md
PR 8319 docs/dev/debt/libSceAgcDriver.md
PR 8365 docs/dev/debt/libSceAgcDriver.md
PR 8426 docs/dev/debt/libSceAgcDriver.md
PR 8542 docs/dev/debt/libSceAgcDriver.md
PR 8592 docs/dev/debt/libSceAgcDriver.md
PR 8998 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 9020 docs/dev/debt/libSceAgcDriver.md
PR 9335 docs/dev/debt/libSceAgcDriver.md
PR 9356 docs/dev/debt/libSceAgcDriver.md
PR 9387 docs/dev/debt/libSceAgcDriver.md
PR 9393 docs/dev/debt/libSceAgcDriver.md
PR 9400 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 9431 docs/dev/debt/libSceAgcDriver.md
PR 9432 docs/dev/debt/libSceAgcDriver.md
PR 9508 core/libs/prx/libSceAgcDriver/Graphics/include/BufferPool.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/BufferPool.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9592 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9672 docs/dev/debt/libSceAgcDriver.md
PR 9673 docs/dev/debt/libSceAgcDriver.md
PR 9674 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9675 docs/dev/debt/libSceAgcDriver.md
PR 9676 docs/dev/debt/libSceAgcDriver.md
PR 9700 docs/dev/debt/libSceAgcDriver.md
PR 9748 docs/dev/debt/libSceAgcDriver.md
PR 9842 docs/dev/debt/libSceAgcDriver.md
PR 9891 docs/dev/debt/libSceAgcDriver.md
PR 9892 docs/dev/debt/libSceAgcDriver.md
PR 9893 docs/dev/debt/libSceAgcDriver.md
PR 9895 docs/dev/debt/libSceAgcDriver.md
PR 9897 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 9898 docs/dev/debt/libSceAgcDriver.md
PR 9904 docs/dev/debt/libSceAgcDriver.md
PR 9905 docs/dev/debt/libSceAgcDriver.md
PR 9906 docs/dev/debt/libSceAgcDriver.md
PR 9941 docs/dev/debt/libSceAgcDriver.md
PR 10000 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 10049 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
docs/dev/debt/libSceAgcDriver.md
PR 10064 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
docs/dev/debt/libSceAgcDriver.md
PR 10193 core/libs/prx/libSceAgcDriver/Graphics/include/BufferPool.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/BufferPool.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
docs/dev/debt/libSceAgcDriver.md

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 20, 2026
@eliasbruno124-dev
eliasbruno124-dev force-pushed the fix/cold-device-storage-pressure-20261020 branch from a6c415f to 74b001a Compare October 20, 2026 21:35
@eliasbruno124-dev

Copy link
Copy Markdown
Contributor Author

Rebased to 74b001a9cc after #7870. Retained images now share the free tier, so idle buffer reclamation explicitly excludes them. The new mixed-pool regression fails without that exclusion and passes with it, including image reuse and exact cleanup.

Both complete Windows/NVIDIA runtimes pass the same 28 focused tests with cache disabled and Khronos synchronization validation: no VUID errors or skipped cases. Conventions pass. The description now distinguishes these checks from the earlier title timing evidence.

Prepared with AI assistance.

@JJenkx

JJenkx commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Second title, on AMD/Linux: neutral on Code Violet (PPSA26528). The reclaim path runs, but there is little idle pool to reclaim on this title.

Setup

  • Linux 7.2.9, Ryzen 9 7950X, RX 6650 XT 8 GiB, RADV (Mesa 26.2.4); PPSA26528 01.000.028, difficulty/start menu.
  • This is integration-relative, because plain main does not render this title on RADV (Code Violet (PPSA26528) #6256). Both sides are main a6dcea9 + feat(libSceAgcDriver): import scattered direct memory as a dma-buf run list and probe its coherence #4449 (local descriptor guard) + fix(agc): keep the write-back ready barrier while hole copies are pending #8908: control 4e68e5f738, and control + this PR (head 74b001a) 3e042365f3. The PR's source merged cleanly. The only conflict was the device-option list in tests/Recorder.cpp, where both sides add an option; I kept both.
  • One persistent runtime for every run, with no per-run restore of shader-cache or save seeds (corrected; see my follow-up below). The AnyPS5 shader cache (warm from earlier runs) had two files written at the start of the first control run and none after. The Mesa cache and the title's save state were not reset or checked. 240 s runs with Cross at 100, 140 and 170 s, APS5_TRACE_SECONDS=200:30. Every trace reports dirty false and dropped false.
  • Run order: control, PR, PR, control. The first PR run segfaulted 6 s into startup (the title's occasional startup crash, seen on both sides before), so I replaced it with one more PR run.
Run presents frame p50 / p90 ms GPU busy ms/present Resources.Complete ms/frame Driver.Packet.memory_wait ms/frame
control 10 3927.9 / 4861.6 886.1 2507.2 1532.8
PR 11 2657.1 / 4227.5 779.3 2205.6 1416.6
control 11 2357.1 / 4341.6 912.2 2222.6 1425.9
PR (replacement) 12 3460.8 / 4420.9 733.5 2182.8 1427.2

Why neutral. This title's storage-image cache churns, with 38–40% of lookups missing. Nearly all misses are budget evictions of surfaces cached before. The per-frame storage set (a 16320x16320 surface plus several 3840x2160 targets) does not fit a storage budget of 0.5–1.7 GiB; details are on #6256. A separate PR run with APS5_PROFILE_DRAW=1 shows the reclaim firing 4 times in 240 s, releasing 10–53 MB each time, and the storage miss rate unchanged at about 39%. Here the idle device-buffer pool is small next to the storage shortfall, so the PR's mechanism has little to work with. That is a different situation from GTA III's, where retained idle buffers were the pressure.

No regression: the control and PR ranges overlap on every column.

AI-assisted: yes (Claude Code); results above were run on this machine.

@JJenkx

JJenkx commented Oct 22, 2026

Copy link
Copy Markdown
Contributor

Correction to my Code Violet comment above: its setup said the runs used "identical shader-cache and save seeds". That was wrong. I have edited the comment.

  • The Code Violet batch ran every arm in one persistent runtime and did not restore shader-cache or save seeds before each run. (My Lodoss harness does restore them; I carried that wording over.)
  • What I can show: the AnyPS5 shader cache, warm from earlier runs, had two files written at the start of the first control run and none after.
  • Not reset or checked: the Mesa shader cache and the title's save state.

The measured numbers are unchanged. The Resources.Complete figures are from tools/trace_digest.py's largest-slices line, which differs by a few ms per frame from a per-frame reduction of the same traces.

AI-assisted: yes (Claude Code); results above were run on this machine.

@JJenkx

JJenkx commented Oct 23, 2026

Copy link
Copy Markdown
Contributor

Protocol note on my measurement above (comment 6337457417): it does not meet the performance-report protocol's "do not redirect the log" rule. The game's stdout and stderr were redirected to game.log by the run wrapper. The results stay as diagnostic observations, but I am withdrawing any claim of measured speed impact or direction from them until a terminal-attached rerun. The counts, logs and traces themselves are unaffected.

AI-assisted: yes (Claude Code)

@eliasbruno124-dev
eliasbruno124-dev force-pushed the fix/cold-device-storage-pressure-20261020 branch from 74b001a to b996e31 Compare October 23, 2026 12:13
@eliasbruno124-dev

Copy link
Copy Markdown
Contributor Author

Rebased linearly onto 777bdbb4f as b996e31d8, including #8527's updated review correction. The header conflict preserves upstream AgcDriver::Mutex; the cold-buffer policy and retained-image exclusion are unchanged.

Both complete Windows/RTX 3060 Laptop 617.42 runtimes passed the same 26 focused tests with cache disabled and real Khronos synchronization validation. Main logged 26 synchronization errors in four cases despite passing CTest; this head logged none. That difference belongs to the included #8527 ordering fix. Its three additional ordering/failure-path tests also pass without skips or validation errors. Conventions pass, and inspected pre-push main 8eb8e3920 merges cleanly.

The description records the exact tested commits. Historical GTA III timings retain their original commits; this rebase adds no new FPS claim. JJenkx's Code Violet observations remain diagnostic only, as corrected above.

Prepared with AI assistance.

@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 23, 2026
@harry-z-kang

Copy link
Copy Markdown
Contributor

@eliasbruno124-dev Draft #10194 adds opt-in allocation accounting for #10041. The overlap audit flags your storage-budget refresh/reclaim calculation and the adjacent test insertion in BufferPool.cpp.

I propose keeping your existing merge order and rebasing accounting after yours lands. The resolution should preserve your cold-buffer reclaim and image exclusion, report the fresh budget after reclaim, and keep both sets of tests. Your PR does not need to wait for #10194. Does that order work for you? If accounting lands first, I can help integrate the reporting hook here.

The current accounting branch builds independently and changes no cache policy; validation results are in #10194. AI-assisted: yes.

@eliasbruno124-dev

Copy link
Copy Markdown
Contributor Author

@harry-z-kang agreed: keep #8527 -> #8672, then rebase #10194's accounting on the resulting code. #8672 does not gain a dependency on #10194.

I inspected the accounting changes at 3bd56fff7: the reporting hook currently uses the budget snapshot taken before this PR's reclaim/re-query path. The later integration should report the refreshed snapshot and selected budget, retain cold-buffer reclamation and the image exclusion, and preserve both test additions. The combined accounting/reclaim path still needs validation; I have not run it. No code or test result changes in this reply.

Prepared with AI assistance.

@JJenkx

JJenkx commented Oct 23, 2026

Copy link
Copy Markdown
Contributor

An interaction between #8672 and #10044, from reading both diffs. It is not measured.

#8672's storageBudget(context, required) bounds the reclaim target with its own ceiling, min(TextureCacheBudget, heapBudget / 4). That is the quarter cap StorageTextureBudget used before #10044. #10044 raises the cap inside StorageTextureBudget to min(heap size / 2, heapBudget / 2) but does not touch #8672's separate ceiling. With both merged:

  • When the reserve formula already allows more than a quarter, needed = min(required, ceiling) is at or below cached.budget, so ReclaimIdleDevice never runs.
  • Reclaim can then only help a storage budget that is still below a quarter of the reported budget.

On Echoes of the End (8 GB GPU), the formula gives about 1.6-2.9 GiB of storage depending on the budget, so the quarter ceiling (about 1.6-1.75 GiB) would usually keep #8672 from reclaiming when #10044 is present.

Whichever PR lands second could derive the ceiling from the same cap expression as StorageTextureBudget, for example a small shared helper, so the two cannot disagree. I am measuring #8672 on its own on Echoes (fresh integration tree without #10044, reported budget pinned to 6900 MiB) and will post the result on #8672.

@adriadam10 adriadam10 self-assigned this Oct 23, 2026
@adriadam10
adriadam10 merged commit 9477025 into boykopovar:main Oct 23, 2026
12 checks passed
@adriadam10

Copy link
Copy Markdown
Collaborator

Checked the reclaim policy against the diff: only complete-idle-interval, independently allocated device buffers are released, oldest first and bounded by the shortfall; active, host, slab, retained-image and recently reused buffers are excluded; Vulkan frees happen outside the pool mutex; the budget is re-read only after an actual release. Tests cover bounded release, allocation failure during collection, backwards time, unsupported heap layouts, mixed image/buffer pools and a reused working set. Technical debt line and memory bound (retained pool 586 -> 298 MiB) are documented; #8527 is already in main. Not verified here: Linux/AMD/Intel timing; merged.

@JJenkx

JJenkx commented Oct 24, 2026

Copy link
Copy Markdown
Contributor

A neutral observation on Echoes of the End (PPSA25636), as promised above. It is a single pair, not evidence for or against this PR.

Setup

Over the last 300 s (in play)

A (without) B (with)
presents 180 196
storage evictions per 10 s, mean ~1,730 ~1,920
storage cache budget, median 1725 MiB (the quarter cap) 1502 MiB
device heap usage at the end 5546 MiB 6191 MiB
device buffer pool retained 406 MiB (of 558) 734 MiB (of 776)

0 crashes in either arm.

Reading

  • Early in B the storage budget reached the quarter cap sooner, which is consistent with the reclaim releasing idle buffers under pressure.
  • Late in B the device pool held more (734 MiB) than in A, device use was higher, and the storage budget was lower. The present difference (+9 %) is within run-to-run spread on this machine.
  • I have not found why the pool's limit (558 vs 776 MiB) differs between the arms. It may come from the fix(agc): order deferred import settles with main-queue accesses #8527 commits.
  • With one pair and no traces, I am not drawing a conclusion. Happy to rerun with traces if a specific scenario would help.

LeandroLP23 added a commit to LeandroLP23/AnyPS5 that referenced this pull request Oct 25, 2026
ReclaimIdleDevice (boykopovar#8672) scans deviceTier for the oldest idle slots, and
the host-placed device buffers this change retains live there too. An
older host-placed slot could satisfy the requested byte count, so the
reclaim freed host memory, reported it as released device memory and left
the idle device-local slots in place. The scan now skips hostPlaced
allocations.

IdleReclaimSkipsHostPlaced retains an older host-placed and a younger
device-local slot and checks that the reclaim frees and counts only the
device-local one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agc libSceAgc* build docs perf numbers missing perf pull request without a before and after summary line perf Performance change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants