Skip to content

perf(agc): refuse a staging shadow that would take the last eighth of the device-local budget - #14815

Merged
oneandonlydean merged 2 commits into
boykopovar:mainfrom
hugodearaujo:perf/agc-staging-shadow-headroom
Nov 3, 2026
Merged

oneandonlydean merged 2 commits into
boykopovar:mainfrom
hugodearaujo:perf/agc-staging-shadow-headroom

Conversation

@hugodearaujo

@hugodearaujo hugodearaujo commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor

What

A staged buffer region (a written element, a swept range up to 256 MiB on a discrete GPU, an atomic element) gets a device-local shadow from stagingBuffer (GuestBufferMemory.cpp). Each shadow is its own VkDeviceMemory, it lives as long as the cached build that holds it, and its allocation never looks at the device-local budget: BufferMemoryType only checks the budget for host-coherent buffers, so a device-local shadow is allocated until the driver refuses it. The other big device-local consumers adapt to the budget (the storage image cache keeps budget / 8 free in its reserve, the sampled texture cache has its own budget), so when a title fills the heap it is the shadows that keep growing into that last eighth and past the budget.

  • Context::DeviceLocalHeadroom(type, bytes) (new): whether an allocation of bytes from memory type type still ends at or below seven eighths of the budget VK_EXT_memory_budget reports for that type's heap. A type on a heap without VK_MEMORY_HEAP_DEVICE_LOCAL_BIT, an unknown type, a device without the extension and a heap without a reported budget all answer yes, so those cases behave as before.
  • Buffer::WithinDeviceLocalHeadroom(context, bytes, usage) (new) makes a device-local Buffer through the normal constructor path. A buffer the pool already retains (BufferPool::Take) is reused as before, without the check, since it adds nothing to the heap. Only on a pool miss, after BufferMemoryType(requirements.memoryTypeBits, ...) has picked the memory type, is the new allocation checked against the heap of that type; without headroom the VkBuffer just created is destroyed and the function returns nullptr.
  • stagingBuffer makes its shadows through it. A refused shadow is treated exactly like a shadow the device cannot provide: nullptr, counted in stagingRefused (the [buffers] staging line of APS5_PROFILE_DRAW), and the region takes the path it takes without staging (Region::unstaged: in place when aligned, otherwise the host copy). The first four refusals print one [buffers] staging shadow of N bytes refused: ... line each.
  • Nothing else changes: shadows already made stay, reuse of a build keeps its shadow, and with room in the budget every shadow is made as before.
  • docs/dev/debt/libSceAgcDriver.md gets a "Staging shadow headroom" entry: the eighth comes from one title on one GPU, budget readings are estimates, and the check reserves nothing against concurrent allocations.

Why (PRAGMATA, PPSA02530)

On an RX 9070 XT (16 GiB, RADV, Linux), the title is stopped by device memory every time the player walks from the "Basic Movement" tutorial save into the forklift room: the device-local heap reaches 15.3 to 16.1 GiB, and free GTT drops next (1.3 GiB of VRAM and 3.0 GiB of GTT free at the stop; our local guard stops the process there, before the desktop compositor starts failing command submission, which an earlier run on this machine caused). With APS5_TRACE_MEMORY_BUDGET=1 (#10194) plus a local diagnostic that names generic Buffer allocations by their caller, the device-local heap at the stop was:

category (heap 1, MiB, active + retained in the pool) at the stop
storage images (storage image cache) 5612 + 8
staging shadows (stagingBuffer < GuestBufferMemory::UploadPrepare) 4415 + 1282
sampled textures 2032 + 227
device buffers 165 + 486
unit shadows, depth targets and copies, mirrors, presentation ~700
heap usage / budget 15353 / 15953

Between the lobby and the forklift room the shadows grew by 1.3 GiB active (3132 -> 4415 MiB) while the storage cache stayed at its budget, and the heap went from 13.3 to 15.3 GiB.

Same build (main 8f55414 + the PRs PRAGMATA needs to reach gameplay + #14367 + #10194, plus that diagnostic), same save, same scripted route (Continue, then the left stick held forward), one run each, with the first version of this change (a37af8b):

run staging shadows at the forklift room device-local usage there (process fdinfo VRAM) result
base 4415 + 1282 MiB 15294 MiB stopped on entering the forklift room (581 s)
base, APS5_NO_WRITTEN_SHADOW=1 ~0 11.9-12.0 GiB walks through the forklift room, still running 500 s later; frame rate lower (2-4 presents per 10 s against 4-6)
base + this change 1593 + 1113 MiB (42248 shadows refused over the run) 13.4-13.6 GiB (peak 13591 MiB) walks through the forklift room and runs to the 1200 s limit; frame rate as base (4-6 presents per 10 s)

The storage image cache takes part of the room the shadows leave (5.6 -> 6.4-6.8 GiB), which is its budget doing its job.

Performance

Captured as the Performance report form describes: PRAGMATA (PPSA02530), the "Basic Movement" save, Continue, then the left stick held forward by script; window APS5_TRACE_SECONDS=410:20, which falls in the Delphi lobby on the way to door A2 (screenshots match between the arms), before the point where the base is stopped on entering the forklift room. No other APS5_TRACE_* or APS5_PROFILE_* switch (the summary lines show only APS5_TRACE_SECONDS and the input file of our runner, which also captures the log to a file); warm shader and pipeline caches (the same cache copied into both run directories); RX 9070 XT, 3840x2160, same session. PRAGMATA does not reach gameplay on main alone, so the base is our test stack: main 8f55414 + the PRs PRAGMATA needs to reach gameplay + #14367 + #10194 (commit a9b16f94d161 in the lines), and the change is that stack + a37af8b and b491e43 cherry-picked (e5b4c1a76648). Two pairs, in the order base, change, change, base:

capture commit presents frame p50 / p90 / max (ms) GPU busy per present (ms) staging refusals before the window closed
1, base a9b16f94d161 13 1596 / 1765 / 1914 273.1 (no gate)
2, change e5b4c1a76648 10 2109 / 2828 / 2828 314.3 none yet (first one after the window)
3, change e5b4c1a76648 13 1613 / 1918 / 1923 270.9 yes (from before the window)
4, base a9b16f94d161 12 1761 / 2023 / 2110 296.6 (no gate)

The run-to-run spread is larger than any difference between the arms: capture 2 ran no refused shadow inside its window, so it ran the same code as the base there, and is still the slowest; capture 3, with the gate refusing shadows, is within the two base captures. In every capture the largest phase after Driver.Packet is Driver.Packet.memory_wait.

{"commit":"a9b16f94d161","dirty":null,"env":{"APS5_PAD_INPUT_FILE":"<path>","APS5_TRACE_SECONDS":"410:20"},"gpu":"AMD Radeon RX 9070 XT (RADV GFX1201)","driver":"radv Mesa 26.2.6-arch1.1","os":"Linux 7.2.11-arch1-1","cpu":"AMD Ryzen 7 9800X3D 8-Core Processor","cpu_threads":8,"memory_mib":31192,"title_id":"PPSA02530","title":"PRAGMATA","content_version":"01.200.000","resolution":"3840x2160","window":{"spec":"seconds 410:20","first_present":2289,"ms":21384.855},"presents":13,"frame_ms":{"p50":1596.384,"p90":1765.323,"p99":1914.261,"max":1914.261},"gpu_busy_ms_per_present":273.070,"worker_busy_pct":{"queue worker 0x38":92.947,"queue worker 0x20":69.872,"queue worker 0x0":99.465,"queue worker 0x28":96.512},"top_phases_ms_per_frame":{"Driver.Packet":5900.144,"Driver.Packet.memory_wait":3544.659,"Driver.Packet.dispatch":1335.178,"Driver.Dispatch":1239.117,"Resources.Complete":925.882,"Driver.Packet.draw":924.118,"Driver.Draw":923.648,"Graphics.Draw":753.789},"trace_dropped":false,"trace":"aps5-trace-a9b16f94d161-2684461.json.gz"}
{"commit":"e5b4c1a76648","dirty":null,"env":{"APS5_PAD_INPUT_FILE":"<path>","APS5_TRACE_SECONDS":"410:20"},"gpu":"AMD Radeon RX 9070 XT (RADV GFX1201)","driver":"radv Mesa 26.2.6-arch1.1","os":"Linux 7.2.11-arch1-1","cpu":"AMD Ryzen 7 9800X3D 8-Core Processor","cpu_threads":8,"memory_mib":31192,"title_id":"PPSA02530","title":"PRAGMATA","content_version":"01.200.000","resolution":"3840x2160","window":{"spec":"seconds 410:20","first_present":2425,"ms":20649.170},"presents":10,"frame_ms":{"p50":2109.147,"p90":2828.118,"p99":2828.118,"max":2828.118},"gpu_busy_ms_per_present":314.273,"worker_busy_pct":{"queue worker 0x38":95.928,"queue worker 0x20":78.151,"queue worker 0x0":99.634,"queue worker 0x28":97.109},"top_phases_ms_per_frame":{"Driver.Packet":7655.591,"Driver.Packet.memory_wait":4592.974,"Driver.Packet.dispatch":1973.793,"Driver.Dispatch":1893.469,"Resources.Complete":1217.791,"Vulkan.Dispatch":969.457,"Driver.Packet.draw":965.215,"Driver.Draw":964.749},"trace_dropped":false,"trace":"aps5-trace-e5b4c1a76648-2745028.json.gz"}
{"commit":"e5b4c1a76648","dirty":null,"env":{"APS5_PAD_INPUT_FILE":"<path>","APS5_TRACE_SECONDS":"410:20"},"gpu":"AMD Radeon RX 9070 XT (RADV GFX1201)","driver":"radv Mesa 26.2.6-arch1.1","os":"Linux 7.2.11-arch1-1","cpu":"AMD Ryzen 7 9800X3D 8-Core Processor","cpu_threads":8,"memory_mib":31192,"title_id":"PPSA02530","title":"PRAGMATA","content_version":"01.200.000","resolution":"3840x2160","window":{"spec":"seconds 410:20","first_present":2292,"ms":21376.039},"presents":13,"frame_ms":{"p50":1612.930,"p90":1918.206,"p99":1923.364,"max":1923.364},"gpu_busy_ms_per_present":270.926,"worker_busy_pct":{"queue worker 0x38":94.585,"queue worker 0x20":72.484,"queue worker 0x0":99.506,"queue worker 0x28":96.598},"top_phases_ms_per_frame":{"Driver.Packet":5969.986,"Driver.Packet.memory_wait":3613.671,"Driver.Packet.dispatch":1393.410,"Driver.Dispatch":1261.634,"Resources.Complete":907.912,"Driver.Packet.draw":850.179,"Driver.Draw":849.714,"Graphics.Draw":738.702},"trace_dropped":false,"trace":"aps5-trace-e5b4c1a76648-2978920.json.gz"}
{"commit":"a9b16f94d161","dirty":null,"env":{"APS5_PAD_INPUT_FILE":"<path>","APS5_TRACE_SECONDS":"410:20"},"gpu":"AMD Radeon RX 9070 XT (RADV GFX1201)","driver":"radv Mesa 26.2.6-arch1.1","os":"Linux 7.2.11-arch1-1","cpu":"AMD Ryzen 7 9800X3D 8-Core Processor","cpu_threads":8,"memory_mib":31192,"title_id":"PPSA02530","title":"PRAGMATA","content_version":"01.200.000","resolution":"3840x2160","window":{"spec":"seconds 410:20","first_present":2270,"ms":21051.273},"presents":12,"frame_ms":{"p50":1760.807,"p90":2023.421,"p99":2109.706,"max":2109.706},"gpu_busy_ms_per_present":296.581,"worker_busy_pct":{"queue worker 0x20":74.765,"queue worker 0x38":92.637,"queue worker 0x0":99.711,"queue worker 0x28":96.847},"top_phases_ms_per_frame":{"Driver.Packet":6383.273,"Driver.Packet.memory_wait":3929.957,"Driver.Packet.dispatch":1399.155,"Driver.Dispatch":1303.774,"Resources.Complete":1000.844,"Driver.Packet.draw":927.537,"Driver.Draw":927.094,"Graphics.Draw":794.631},"trace_dropped":false,"trace":"aps5-trace-a9b16f94d161-3039591.json.gz"}

Trace files: 1, base (aps5-trace-a9b16f94d161-2684461), 2, change (aps5-trace-e5b4c1a76648-2745028), 3, change (aps5-trace-e5b4c1a76648-2978920), 4, base (aps5-trace-a9b16f94d161-3039591).

python3 tools/trace_digest.py <trace>:

  • 1: seconds 410:20 from present 2289: 13 presents, frame p50 1596.4 / p90 1765.3 / p99 1914.3 / max 1914.3 ms, GPU busy 273.1 ms per present
  • 2: seconds 410:20 from present 2425: 10 presents, frame p50 2109.1 / p90 2828.1 / p99 2828.1 / max 2828.1 ms, GPU busy 314.3 ms per present
  • 3: seconds 410:20 from present 2292: 13 presents, frame p50 1612.9 / p90 1918.2 / p99 1923.4 / max 1923.4 ms, GPU busy 270.9 ms per present
  • 4: seconds 410:20 from present 2270: 12 presents, frame p50 1760.8 / p90 2023.4 / p99 2109.7 / max 2109.7 ms, GPU busy 296.6 ms per present
Full digest, capture 3 (change)

seconds 410:20 from present 2292: 13 presents, frame p50 1612.9 / p90 1918.2 / p99 1923.4 / max 1923.4 ms, GPU busy 270.9 ms per present
AMD Radeon RX 9070 XT (RADV GFX1201), radv Mesa 26.2.6-arch1.1, Linux 7.2.11-arch1-1, 3840x2160, commit e5b4c1a, dropped: no

{"commit":"e5b4c1a76648","dirty":null,"env":{"APS5_PAD_INPUT_FILE":"<path>","APS5_TRACE_SECONDS":"410:20"},"gpu":"AMD Radeon RX 9070 XT (RADV GFX1201)","driver":"radv Mesa 26.2.6-arch1.1","os":"Linux 7.2.11-arch1-1","cpu":"AMD Ryzen 7 9800X3D 8-Core Processor","cpu_threads":8,"memory_mib":31192,"title_id":"PPSA02530","title":"PRAGMATA","content_version":"01.200.000","resolution":"3840x2160","window":{"spec":"seconds 410:20","first_present":2292,"ms":21376.039},"presents":13,"frame_ms":{"p50":1612.93,"p90":1918.206,"p99":1923.364,"max":1923.364},"gpu_busy_ms_per_present":270.926,"worker_busy_pct":{"queue worker 0x38":94.585,"queue worker 0x20":72.484,"queue worker 0x0":99.506,"queue worker 0x28":96.598},"top_phases_ms_per_frame":{"Driver.Packet":5969.986,"Driver.Packet.memory_wait":3613.671,"Driver.Packet.dispatch":1393.41,"Driver.Dispatch":1261.634,"Resources.Complete":907.912,"Driver.Packet.draw":850.179,"Driver.Draw":849.714,"Graphics.Draw":738.702},"trace_dropped":false,"trace":"aps5-trace-e5b4c1a76648-2978920.json.gz"}

Slowest frames (largest slices inside each, inclusive)

  • present 2301: 1923.4 ms at 14829 ms: Driver.Packet (queue worker 0x0) 1900.2, Driver.Packet (queue worker 0x28) 1876.6, Driver.Packet (queue worker 0x38) 1852.9, Driver.Packet.memory_wait (queue worker 0x28) 1741.1
  • present 2294: 1918.2 ms at 3591 ms: Driver.Packet (queue worker 0x0) 1894.6, Driver.Packet (queue worker 0x28) 1869.0, Driver.Packet (queue worker 0x38) 1786.1, Driver.Packet.memory_wait (queue worker 0x28) 1731.6
  • present 2293: 1819.7 ms at 1771 ms: Driver.Packet (queue worker 0x0) 1797.5, Driver.Packet (queue worker 0x28) 1774.7, Driver.Packet (queue worker 0x38) 1724.0, Driver.Packet.memory_wait (queue worker 0x28) 1626.9
  • present 2292: 1771.4 ms at 0 ms: Driver.Packet (queue worker 0x0) 1704.6, Driver.Packet (queue worker 0x28) 1624.1, Driver.Packet (queue worker 0x38) 1571.9, Driver.Packet.memory_wait (queue worker 0x28) 1529.8
  • present 2298: 1686.0 ms at 10151 ms: Driver.Packet (queue worker 0x0) 1662.4, Driver.Packet (queue worker 0x38) 1641.9, Driver.Packet (queue worker 0x28) 1631.4, Driver.Packet.memory_wait (queue worker 0x28) 1497.7

Threads (ms per frame)

thread busy wait untraced in slices < 20 us largest
shader prepare 7.4 (0 %) 0.0 (0 %) 1637.0 0.0 Vulkan.ComputePipeline 7.4
shader prepare 6.6 (0 %) 0.0 (0 %) 1637.7 0.0 Vulkan.ComputePipeline 6.6
queue worker 0x38 256.9 (16 %) 1372.5 (83 %) 14.8 43.9 Driver.Packet 1549.8, Vulkan.Dispatch 4.1
queue worker 0x20 112.5 (7 %) 1466.6 (89 %) 65.2 29.0 Driver.Packet 1187.1, Driver.EndSubmission 0.5
queue worker 0x0 1253.9 (76 %) 367.3 (22 %) 23.2 154.2 Driver.Packet 1618.1, Recorder.Sync 0.2
draw committer 672.5 (41 %) 133.0 (8 %) 838.8 14.8 Graphics.Draw 664.5, Recorder.Submit 9.3
presenter 0.7 (0 %) 7.5 (0 %) 1636.1 0.1 Driver.Present 7.3, VideoOut.Flip 0.9
queue worker 0x28 13.5 (1 %) 1619.4 (98 %) 11.5 0.2 Driver.Packet 1587.9, Driver.EndSubmission 0.5
gpu 270.8 (16 %) 0.0 (0 %) 1373.5 0.0 batch 270.8

Largest slices (ms per frame, inclusive, all threads): Driver.Packet 5942.8, Driver.Packet.memory_wait 3613.6, Driver.Packet.dispatch 1377.6, Driver.Dispatch 1234.5, Resources.Complete 905.4, Driver.Packet.draw 846.7, Driver.Draw 846.3, Graphics.Draw 732.2, Graphics.Draw.draw_and_resource_release 720.6, Vulkan.Dispatch 658.9

Longest waits

  • Driver.Packet.memory_wait (queue worker 0x38) 1495.3 ms at 14941 ms, present 2301
  • Driver.Packet.memory_wait (queue worker 0x38) 1347.3 ms at 101 ms, present 2292
  • Driver.Packet.memory_wait (queue worker 0x28) 1314.3 ms at 4148 ms, present 2294
  • Driver.Packet.memory_wait (queue worker 0x38) 1297.5 ms at 10256 ms, present 2298
  • Driver.Packet.memory_wait (queue worker 0x28) 1255.7 ms at 470 ms, present 2292
  • Driver.Packet.memory_wait (queue worker 0x28) 1238.1 ms at 15469 ms, present 2301
  • Driver.Packet.memory_wait (queue worker 0x38) 1223.9 ms at 13328 ms, present 2300
  • Driver.Packet.memory_wait (queue worker 0x28) 1220.6 ms at 2327 ms, present 2293
  • Driver.Packet.memory_wait (queue worker 0x28) 1209.8 ms at 18499 ms, present 2303
  • Driver.Packet.memory_wait (queue worker 0x38) 1180.4 ms at 19910 ms, present 2304

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

  • batch 246: 20.4 ms at 3237 ms, present 2293: GPU no ranges; recorded by Driver.Packet (queue worker 0x0) 57.4, Driver.Packet.dispatch (queue worker 0x0) 57.4, Driver.Dispatch (queue worker 0x0) 57.4, Vulkan.Dispatch (queue worker 0x0) 40.9
  • batch 92: 20.0 ms at 1396 ms, present 2292: GPU no ranges; recorded by Driver.Packet (queue worker 0x0) 50.8, Driver.Packet.dispatch (queue worker 0x0) 50.8, Driver.Dispatch (queue worker 0x0) 50.8, Vulkan.Dispatch (queue worker 0x0) 44.0
  • batch 537: 19.4 ms at 6700 ms, present 2295: GPU no ranges; recorded by Driver.Packet (queue worker 0x0) 46.8, Driver.Packet.dispatch (queue worker 0x0) 46.8, Driver.Dispatch (queue worker 0x0) 46.8, Vulkan.Dispatch (queue worker 0x0) 39.9
  • batch 395: 19.3 ms at 5142 ms, present 2294: GPU no ranges; recorded by Driver.Packet (queue worker 0x0) 59.3, Driver.Packet.dispatch (queue worker 0x0) 59.3, Driver.Dispatch (queue worker 0x0) 59.2, Vulkan.Dispatch (queue worker 0x0) 43.4
  • batch 1268: 19.0 ms at 14502 ms, present 2300: GPU no ranges; recorded by Driver.Packet (queue worker 0x0) 53.3, Driver.Packet.dispatch (queue worker 0x0) 53.3, Driver.Dispatch (queue worker 0x0) 53.3, Vulkan.Dispatch (queue worker 0x0) 46.3
Full digest, capture 4 (base)

seconds 410:20 from present 2270: 12 presents, frame p50 1760.8 / p90 2023.4 / p99 2109.7 / max 2109.7 ms, GPU busy 296.6 ms per present
AMD Radeon RX 9070 XT (RADV GFX1201), radv Mesa 26.2.6-arch1.1, Linux 7.2.11-arch1-1, 3840x2160, commit a9b16f9, dropped: no

{"commit":"a9b16f94d161","dirty":null,"env":{"APS5_PAD_INPUT_FILE":"<path>","APS5_TRACE_SECONDS":"410:20"},"gpu":"AMD Radeon RX 9070 XT (RADV GFX1201)","driver":"radv Mesa 26.2.6-arch1.1","os":"Linux 7.2.11-arch1-1","cpu":"AMD Ryzen 7 9800X3D 8-Core Processor","cpu_threads":8,"memory_mib":31192,"title_id":"PPSA02530","title":"PRAGMATA","content_version":"01.200.000","resolution":"3840x2160","window":{"spec":"seconds 410:20","first_present":2270,"ms":21051.273},"presents":12,"frame_ms":{"p50":1760.807,"p90":2023.421,"p99":2109.706,"max":2109.706},"gpu_busy_ms_per_present":296.581,"worker_busy_pct":{"queue worker 0x20":74.765,"queue worker 0x38":92.637,"queue worker 0x0":99.711,"queue worker 0x28":96.847},"top_phases_ms_per_frame":{"Driver.Packet":6383.273,"Driver.Packet.memory_wait":3929.957,"Driver.Packet.dispatch":1399.155,"Driver.Dispatch":1303.774,"Resources.Complete":1000.844,"Driver.Packet.draw":927.537,"Driver.Draw":927.094,"Graphics.Draw":794.631},"trace_dropped":false,"trace":"aps5-trace-a9b16f94d161-3039591.json.gz"}

Slowest frames (largest slices inside each, inclusive)

  • present 2272: 2109.7 ms at 3547 ms: Driver.Packet (queue worker 0x0) 2081.1, Driver.Packet (queue worker 0x28) 2063.3, Driver.Packet.memory_wait (queue worker 0x28) 2062.7, Driver.Packet (queue worker 0x38) 1813.3
  • present 2273: 2023.4 ms at 5657 ms: Driver.Packet (queue worker 0x0) 2000.7, Driver.Packet (queue worker 0x28) 1980.8, Driver.Packet.memory_wait (queue worker 0x28) 1980.3, Driver.Packet (queue worker 0x38) 1942.3
  • present 2275: 1920.6 ms at 9423 ms: Driver.Packet (queue worker 0x0) 1894.9, Driver.Packet (queue worker 0x28) 1846.4, Driver.Packet.memory_wait (queue worker 0x28) 1845.1, Driver.Packet (queue worker 0x38) 1516.7
  • present 2281: 1890.1 ms at 19161 ms: Driver.Packet (queue worker 0x0) 1866.6, Driver.Packet (queue worker 0x28) 1788.1, Driver.Packet.memory_wait (queue worker 0x28) 1704.1, Driver.Packet (queue worker 0x38) 1597.3
  • present 2271: 1786.0 ms at 1761 ms: Driver.Packet (queue worker 0x0) 1760.4, Driver.Packet (queue worker 0x28) 1741.6, Driver.Packet.memory_wait (queue worker 0x28) 1741.1, Driver.Packet (queue worker 0x38) 1709.5

Threads (ms per frame)

thread busy wait untraced in slices < 20 us largest
shader prepare 1.6 (0 %) 0.0 (0 %) 1752.6 0.0 Vulkan.ComputePipeline 1.6
shader prepare 8.1 (0 %) 0.0 (0 %) 1746.2 0.0 Vulkan.ComputePipeline 8.1
shader prepare 0.0 (0 %) 0.0 (0 %) 1754.3 0.0 Vulkan.ComputePipeline 0.0
queue worker 0x20 112.9 (6 %) 1594.5 (91 %) 46.9 29.5 Driver.Packet 1306.6, Driver.EndSubmission 0.5
queue worker 0x38 245.3 (14 %) 1503.1 (86 %) 5.9 45.5 Driver.Packet 1619.2, Driver.EndSubmission 0.3
queue worker 0x0 1449.4 (83 %) 283.6 (16 %) 21.4 163.2 Driver.Packet 1730.2, Recorder.Reap 0.0
draw committer 713.1 (41 %) 124.1 (7 %) 917.1 16.3 Graphics.Draw 704.6, Recorder.Submit 9.6
presenter 0.6 (0 %) 0.7 (0 %) 1752.9 0.1 VideoOut.Flip 1.1, Driver.Present 0.3
queue worker 0x28 9.9 (1 %) 1735.7 (99 %) 8.7 0.2 Driver.Packet 1698.3, Driver.EndSubmission 0.7
gpu 287.6 (16 %) 0.0 (0 %) 1466.6 0.0 batch 287.6

Largest slices (ms per frame, inclusive, all threads): Driver.Packet 6354.3, Driver.Packet.memory_wait 3929.9, Driver.Packet.dispatch 1381.8, Driver.Dispatch 1276.4, Resources.Complete 997.3, Driver.Packet.draw 924.0, Driver.Draw 923.6, Graphics.Draw 787.1, Graphics.Draw.draw_and_resource_release 776.0, Vulkan.Dispatch 695.2

Longest waits

  • Driver.Packet.memory_wait (queue worker 0x38) 1646.2 ms at 5763 ms, present 2273
  • Driver.Packet.memory_wait (queue worker 0x38) 1545.5 ms at 3801 ms, present 2272
  • Driver.Packet.memory_wait (queue worker 0x28) 1456.0 ms at 4157 ms, present 2272
  • Driver.Packet.memory_wait (queue worker 0x28) 1413.4 ms at 9858 ms, present 2275
  • Driver.Packet.memory_wait (queue worker 0x38) 1411.5 ms at 1867 ms, present 2271
  • Driver.Packet.memory_wait (queue worker 0x28) 1349.9 ms at 19598 ms, present 2281
  • Driver.Packet.memory_wait (queue worker 0x28) 1345.3 ms at 6294 ms, present 2273
  • Driver.Packet.memory_wait (queue worker 0x38) 1308.2 ms at 7787 ms, present 2274
  • Driver.Packet.memory_wait (queue worker 0x28) 1295.0 ms at 17823 ms, present 2280
  • Driver.Packet.memory_wait (queue worker 0x28) 1284.8 ms at 2221 ms, present 2271

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

  • batch 764: 25.5 ms at 9046 ms, present 2274: GPU no ranges; recorded by Driver.Packet (queue worker 0x0) 55.3, Driver.Packet.dispatch (queue worker 0x0) 55.3, Driver.Dispatch (queue worker 0x0) 55.3, Vulkan.Dispatch (queue worker 0x0) 39.7
  • batch 1228: 21.4 ms at 14181 ms, present 2277: GPU no ranges; recorded by Driver.Packet (queue worker 0x0) 57.4, Driver.Packet.dispatch (queue worker 0x0) 57.4, Driver.Dispatch (queue worker 0x0) 57.4, Vulkan.Dispatch (queue worker 0x0) 42.4
  • batch 1369: 21.3 ms at 15613 ms, present 2278: GPU no ranges; recorded by Driver.Packet (queue worker 0x0) 55.6, Driver.Packet.dispatch (queue worker 0x0) 55.6, Driver.Dispatch (queue worker 0x0) 55.6, Vulkan.Dispatch (queue worker 0x0) 39.8
  • batch 1084: 21.0 ms at 12581 ms, present 2276: GPU no ranges; recorded by Driver.Packet (queue worker 0x0) 46.4, Driver.Packet.dispatch (queue worker 0x0) 46.4, Driver.Dispatch (queue worker 0x0) 46.4, Vulkan.Dispatch (queue worker 0x0) 39.5
  • batch 1696: 20.7 ms at 18767 ms, present 2280: GPU no ranges; recorded by Driver.Packet (queue worker 0x0) 57.9, Driver.Packet.dispatch (queue worker 0x0) 57.9, Driver.Dispatch (queue worker 0x0) 57.9, Vulkan.Dispatch (queue worker 0x0) 41.8

Frame rate through the forklift room, same builds and route, APS5_TRACE_SUMMARY_EVERY=10 (separate runs, not the captures above), presents per 10 s counted from the end of the loading screen:

gameplay seconds base change
0-100 (corridor) 9.4 9.5
100-200 (lobby) 6.2 7.0
200-290 (to the forklift room door) 5.4 5.2
290-400 (forklift room) stopped at its entrance: 1315 MiB VRAM and 3055 MiB GTT free, process VRAM 15214 MiB 4.3
400-640 (the room after it) - 6.7

The change's process VRAM peaked at 13561 MiB over its 900 s run.

Tested

On main f2d874c1fd and this head (b491e43), same machine (RX 9070 XT, RADV Mesa 26.2.6, Linux), ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation:

  • ctest -V -R 'agc_device_memory_fallback|agc_adaptive_staging|agc_buffer_pool|staging': 7/7 pass on both (agc_adaptive_staging, agc_buffer_pool and its two small-device modes, agc_device_memory_fallback, agc_bda_staging, agc_read_written_staging), no VUID- line and no was not found but was requested line in either log.
  • agc_device_memory_fallback (mock budget): HeadroomTests checks room below seven eighths, an allocation ending exactly at seven eighths, one crossing it, usage already past it, no reported budget, a host memory type, an unknown type, no VK_EXT_memory_budget and no device-local heap. SecondHeapHeadroomTests adds a second device-local heap and type and picks the type from the mask as Buffer does: with a mask that excludes the first device-local type, pressure on the first heap leaves room and pressure on the second refuses; with a mask that allows both, only the first heap counts.
  • agc_buffer_pool (mock device), StagingHeadroom: a 24 MiB shadow made with room and released to the pool is reused at 1900 of 2048 MiB (past seven eighths) with no new allocation; a 40 MiB shadow at the same usage is refused with no allocation and no VkBuffer left alive; with memoryTypeBits excluding the first device-local type, a full first heap does not refuse a shadow that goes to the second heap, and a full second heap does.
  • Negative controls: with the check reading the first device-local type's heap whatever type it is given, agc_device_memory_fallback fails the two mask-excludes-first cases (and the host-type and no-device-local-heap cases) and agc_buffer_pool fails both second-heap cases; with the check moved back before the pool lookup, agc_buffer_pool fails a retained staging buffer was refused within the last eighth of the budget, although reusing it allocates nothing.
  • python tools/check_conventions.py --base origin/main passes.

Overlap: no open PR changes stagingBuffer or the shadow size limits (checked the diffs of the 11 open PRs that touch GuestBufferMemory.cpp). #4472 drops the buffer pool's retained device memory over the budget; it is complementary (the 1.3 GiB of retained shadow memory above is that pool's) and does not act here, because the heap stays under the reported budget until the very end.

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: none
  • Fixes: none
  • Unblocks: PPSA02530 past the forklift room (device memory)
  • GPUs tested: AMD Radeon RX 9070 XT, RADV (Mesa 26.2.6), Arch Linux
  • AI-assisted: yes

@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 — changes requested

The headroom gate can refuse reusable staging buffers and does not necessarily inspect the heap selected for a new buffer.

What I ran

Reviewed head a37af8b9107e47a6d3236942a0a98a581c1c567a against base f2d874c1fdccf781c0fa5d86619bb5dd8894b958; the stack preview was clean. Environment: Linux x86_64, Python 3.11.2, GCC 12.2.0. I did not build or compile.

git diff --check f2d874c1fdccf781c0fa5d86619bb5dd8894b958...a37af8b9107e47a6d3236942a0a98a581c1c567a
python3 tools/pr_precheck.py --repo boykopovar/AnyPS5 --pr 14815
python3 tools/pr_test_quality.py --root /marc/AnyPS5 --json core/libs/prx/libSceAgcDriver/tests/DeviceMemoryFallback.cpp
python3 tools/pr_abi_audit.py --repo /marc/AnyPS5 --base f2d874c1fdccf781c0fa5d86619bb5dd8894b958 --head a37af8b9107e47a6d3236942a0a98a581c1c567a --json
GITHUB_REPOSITORY=boykopovar/AnyPS5 python3 tools/pr_labels.py --pr 14815 --dry-run
python3 tools/pr_stack_check.py 14815 --repo boykopovar/AnyPS5

Results

Check Result Note
Patch whitespace passed No diff errors.
Conventions and template passed Local check passed.
Test-quality heuristic passed after inspection Its registration warning is a false positive; the test is in the included CMake fragment.
ABI audit not applicable No changed export declaration or alias.
Performance report failed The title requires perf evidence; summary lines and traces are absent.
Build and C++ tests not run No build was performed.
Hosted CI not run to completion Required jobs were queued; an earlier conventions run was cancelled.
Merge preview passed Clean against the PR base.
Precheck output and full table
/tmp/anyps5-pr-precheck/boykopovar-AnyPS5-pr-14815-a37af8b9107e/report.md
/tmp/anyps5-pr-precheck/boykopovar-AnyPS5-pr-14815-a37af8b9107e/report.json
Conclusion: checks failed
Check Status Command / reason
build_and_compile not_applicable The precheck deliberately does not configure, build, or compile AnyPS5.
diff_check passed git diff --check f2d874c1fdccf781c0fa5d86619bb5dd8894b958...a37af8b9107e47a6d3236942a0a98a581c1c567a
conventions_and_pr_template passed /usr/bin/python3 tools/check_conventions.py --base f2d874c1fdccf781c0fa5d86619bb5dd8894b958 --head a37af8b9107e47a6d3236942a0a98a581c1c567a --title perf(agc): refuse a staging shadow that would take the last eighth of the device-local budget --body /tmp/anyps5-pr-precheck/boykopovar-AnyPS5-pr-14815-a37af8b9107e/pr-body.md
changed_export_abi_audit failed /usr/bin/python3 tools/pr_abi_audit.py --base f2d874c1fdccf781c0fa5d86619bb5dd8894b958 --head a37af8b9107e47a6d3236942a0a98a581c1c567a --json
python_syntax not_applicable No changed Python implementation files.
related_python_unit_tests not_applicable No changed tools/ module has an existing sibling tools/tests/test_<module>.py suite.
python_test_registration not_applicable No changed test_*.py files.
live_dependency_and_mergeability_check passed /usr/bin/python3 /marc/AnyPS5/tools/pr_stack_check.py 14815 --repo boykopovar/AnyPS5 --output-dir /tmp/anyps5-pr-precheck/boykopovar-AnyPS5-pr-14815-a37af8b9107e/stack
build_dependent_cpp_tests not_applicable Not run: C++ tests need exact-head binaries, which require a build; the precheck does not build.
test_quality_heuristics failed /usr/bin/python3 /tmp/anyps5-pr-precheck/boykopovar-AnyPS5-pr-14815-a37af8b9107e/head-a37af8b9107e-25a7f1e3/tools/pr_test_quality.py --root /tmp/anyps5-pr-precheck/boykopovar-AnyPS5-pr-14815-a37af8b9107e/head-a37af8b9107e-25a7f1e3 --json core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp core/libs/prx/libSceAgcDriver/tests/DeviceMemoryFallback.cpp
negative_controls not_applicable No changed Python test module in tools/ can be run as a no-build base-source control.

The precheck's ABI and test-quality helper launches failed because those local scripts are not part of the isolated PR checkout. I ran both helpers from the workspace; the ABI check was not applicable, and manual inspection confirmed the test-quality warning is a false positive because agc_device_memory_fallback_tests.cmake registers this source.

Unedited helper output:

{
  "findings": [
    {
      "path": "core/libs/prx/libSceAgcDriver/tests/DeviceMemoryFallback.cpp",
      "line": 1,
      "kind": "possible-unregistered-cpp-test",
      "message": "Changed C++ test source path was not found literally in CMake files; inspect registration, generated source lists, and workflow coverage."
    }
  ],
  "negative_control_candidates": [],
  "limits": [
    "Heuristics can miss weak assertions and can flag valid tests; inspect every finding.",
    "A test that passes against base is not by itself proof that the PR test is inadequate.",
    "Negative controls are only candidates until the test actually runs against base and fails by assertion rather than import/setup error."
  ]
}

Unedited label dry-run output:

would change #14815: +perf +perf numbers missing +unblocks title comment

Unedited relevant command output:

git diff --check produced no output.

Conventions:

All conventions checks passed.

Stack check:

/tmp/anyps5-pr-stack/boykopovar-AnyPS5-pr-14815-a37af8b9107e/stack-report.md
/tmp/anyps5-pr-stack/boykopovar-AnyPS5-pr-14815-a37af8b9107e/stack-report.json

Negative control

Not run. The C++ tests require a built binary; no build was performed.

Findings

Blocking

  • stagingBuffer checks DeviceLocalHeadroom and returns nullptr before constructing a Buffer. The Buffer constructor first asks BufferPool::Take for a matching cached allocation. At the 7/8 threshold, the new early return therefore skips a possible cache hit even though reusing that allocation would add no heap usage; the retained allocation remains in the pool while this region falls back to the unstaged path. Please preserve cached-buffer reuse and apply the headroom refusal only when a fresh device allocation is needed, with a test for a reusable entry at the threshold.
  • DeviceLocalHeadroom uses the first device-local memory type, but Buffer chooses a type after Vulkan returns this buffer's memoryTypeBits. If the selected type belongs to another heap, the check reads the wrong heap's budget and can either refuse useful staging or permit allocation past the selected heap's threshold. Please base the check on the actual compatible type/heap and cover differing memory-type masks in the budget test.
  • The title matches the repository's perf(...) rule. The description has no two valid, distinct-commit aps5-summary.jsonl lines, raw traces or trace_digest.py output; the label dry run also reports perf numbers missing. Please add the matched baseline and candidate captures required by the performance report form.

Non-blocking

  • None.

Sources

Not verified

  • No build, CTest run, negative control, independent GPU run, or Linux/Windows/console behavior check was performed. The live hosted jobs were still queued or cancelled.

To get this to a good state

Preserve pool reuse, check the actual selected heap, and provide the matched performance artifacts. I will rerun the same no-build checks on the updated head.

@oneandonlydean

Copy link
Copy Markdown
Collaborator

Thanks for the measurements; the breakdown by category makes the case clearly, and falling back to the existing unstaged path keeps the change small. Two requests at a37af8b910:

  1. DeviceLocalHeadroom checks the heap of the first device-local memory type (core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp lines 368-373), but the allocation picks its type from the buffer's memoryTypeBits (core/libs/prx/libSceAgcDriver/Graphics/src/Resources.cpp line 100). On a device with two device-local heaps and a buffer compatible only with the second, the guard can refuse staging because the unrelated first heap is full, or allow it while the heap actually used is already past the threshold. Could you check the budget of the heap the allocation will use, and add mock cases to HeadroomTests (DeviceMemoryFallback.cpp line 141) where the mask excludes the first local type, with each heap under pressure in turn?
  2. The eighth is a heuristic, like the storage image cache's reserve recorded in the texture cache budgets entry of docs/dev/debt/libSceAgcDriver.md (line 127). Could you add a short debt entry for it? It should say that staging shadows are refused within the last eighth of the reported device-local budget, that the eighth comes from one title on one GPU, that budget readings are estimates and the check does not reserve memory against concurrent allocations, and that devices without VK_EXT_memory_budget behave as before.

Reviewed at a37af8b910.

@github-actions github-actions Bot added perf Performance change perf numbers missing perf pull request without a before and after summary line unblocks title Names a title ID on the Unblocks line labels Nov 1, 2026
@github-actions

github-actions Bot commented Nov 1, 2026

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.

@github-actions github-actions Bot added the agc libSceAgc* label Nov 1, 2026
…heap it uses

The headroom check ran before the Buffer was made, so a shadow the buffer
pool could serve without allocating was refused too, and it read the heap
of the first device-local memory type rather than the one the buffer's
memoryTypeBits select. Buffer::WithinDeviceLocalHeadroom makes the shadow:
a pooled allocation is reused as before, and a new one is refused when it
would end within the last eighth of the reported budget of the heap of
the memory type chosen for it. The eighth gets a debt entry.
@github-actions

github-actions Bot commented Nov 1, 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 8748 core/libs/prx/libSceAgcDriver/tests/BufferPool.cpp L1480
PR 9508 core/libs/prx/libSceAgcDriver/Graphics/src/Resources.cpp L52
PR 11920 core/libs/prx/libSceAgcDriver/tests/BufferPool.cpp L66
PR 14220 docs/dev/debt/libSceAgcDriver.md L133

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 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
docs/dev/debt/libSceAgcDriver.md
PR 4472 core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp
core/libs/prx/libSceAgcDriver/tests/BufferPool.cpp
PR 5021 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 5925 docs/dev/debt/libSceAgcDriver.md
PR 6186 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6194 docs/dev/debt/libSceAgcDriver.md
PR 6197 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 6223 docs/dev/debt/libSceAgcDriver.md
PR 6273 docs/dev/debt/libSceAgcDriver.md
PR 6280 docs/dev/debt/libSceAgcDriver.md
PR 6412 docs/dev/debt/libSceAgcDriver.md
PR 6481 core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6548 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6553 core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp
core/libs/prx/libSceAgcDriver/tests/BufferPool.cpp
core/libs/prx/libSceAgcDriver/tests/DeviceMemoryFallback.cpp
PR 6804 core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp
docs/dev/debt/libSceAgcDriver.md
PR 6808 docs/dev/debt/libSceAgcDriver.md
PR 6918 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 6987 docs/dev/debt/libSceAgcDriver.md
PR 6989 docs/dev/debt/libSceAgcDriver.md
PR 6995 docs/dev/debt/libSceAgcDriver.md
PR 7002 docs/dev/debt/libSceAgcDriver.md
PR 7085 docs/dev/debt/libSceAgcDriver.md
PR 7256 docs/dev/debt/libSceAgcDriver.md
PR 7275 core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp
PR 7449 docs/dev/debt/libSceAgcDriver.md
PR 7457 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 7514 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 7604 docs/dev/debt/libSceAgcDriver.md
PR 7642 core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp
core/libs/prx/libSceAgcDriver/Graphics/include/Resources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Resources.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7668 docs/dev/debt/libSceAgcDriver.md
PR 8592 docs/dev/debt/libSceAgcDriver.md
PR 8707 docs/dev/debt/libSceAgcDriver.md
PR 9012 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 9020 docs/dev/debt/libSceAgcDriver.md
PR 9318 docs/dev/debt/libSceAgcDriver.md
PR 9335 docs/dev/debt/libSceAgcDriver.md
PR 9356 core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp
docs/dev/debt/libSceAgcDriver.md
PR 9387 core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp
docs/dev/debt/libSceAgcDriver.md
PR 9592 docs/dev/debt/libSceAgcDriver.md
PR 9672 docs/dev/debt/libSceAgcDriver.md
PR 9673 docs/dev/debt/libSceAgcDriver.md
PR 9675 docs/dev/debt/libSceAgcDriver.md
PR 9700 docs/dev/debt/libSceAgcDriver.md
PR 9712 core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp
core/libs/prx/libSceAgcDriver/Graphics/include/Resources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Resources.cpp
core/libs/prx/libSceAgcDriver/tests/BufferPool.cpp
PR 9748 docs/dev/debt/libSceAgcDriver.md
PR 9852 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 9895 docs/dev/debt/libSceAgcDriver.md
PR 9898 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9915 docs/dev/debt/libSceAgcDriver.md
PR 9950 docs/dev/debt/libSceAgcDriver.md
PR 10025 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 10049 docs/dev/debt/libSceAgcDriver.md
PR 10193 core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp
core/libs/prx/libSceAgcDriver/Graphics/include/Resources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Resources.cpp
docs/dev/debt/libSceAgcDriver.md
PR 10233 docs/dev/debt/libSceAgcDriver.md
PR 10256 docs/dev/debt/libSceAgcDriver.md
PR 10359 docs/dev/debt/libSceAgcDriver.md
PR 10442 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 10743 docs/dev/debt/libSceAgcDriver.md
PR 11444 core/libs/prx/libSceAgcDriver/Graphics/src/Resources.cpp
PR 11825 docs/dev/debt/libSceAgcDriver.md
PR 11998 docs/dev/debt/libSceAgcDriver.md
PR 12120 core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp
docs/dev/debt/libSceAgcDriver.md
PR 12157 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 12565 docs/dev/debt/libSceAgcDriver.md
PR 12567 docs/dev/debt/libSceAgcDriver.md
PR 12944 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 13148 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
PR 13599 docs/dev/debt/libSceAgcDriver.md
PR 13707 docs/dev/debt/libSceAgcDriver.md
PR 13863 core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp
core/libs/prx/libSceAgcDriver/Graphics/include/Resources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Resources.cpp
docs/dev/debt/libSceAgcDriver.md
PR 13920 core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp
core/libs/prx/libSceAgcDriver/Graphics/include/Resources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Resources.cpp
docs/dev/debt/libSceAgcDriver.md
PR 13928 core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp
core/libs/prx/libSceAgcDriver/Graphics/include/Resources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Resources.cpp
docs/dev/debt/libSceAgcDriver.md
PR 13929 core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp
core/libs/prx/libSceAgcDriver/Graphics/include/Resources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Resources.cpp
docs/dev/debt/libSceAgcDriver.md
PR 13994 docs/dev/debt/libSceAgcDriver.md
PR 14212 docs/dev/debt/libSceAgcDriver.md
PR 14311 docs/dev/debt/libSceAgcDriver.md
PR 14344 docs/dev/debt/libSceAgcDriver.md
PR 14561 docs/dev/debt/libSceAgcDriver.md
PR 14621 docs/dev/debt/libSceAgcDriver.md
PR 14943 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Resources.cpp
docs/dev/debt/libSceAgcDriver.md
PR 14944 docs/dev/debt/libSceAgcDriver.md
PR 14976 core/libs/prx/libSceAgcDriver/Graphics/src/GuestBufferMemory.cpp
docs/dev/debt/libSceAgcDriver.md

@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ AMD GPU test: passed

PR head a37af8b merged onto main f2d874c · tested 2026-11-01 19:15 UTC · 33 min

GPU AMD Radeon RX 6300 (RADV NAVI24), driver Mesa 25.2.8-0ubuntu0.24.04.4, Vulkan 1.4.318
Host Ubuntu 26.04.1 LTS, kernel 7.0.0-42-generic, container ubuntu:24.04
Logs build and test logs for this run
Build ✅ passed (Release, -DANYPS5_ENABLE_SPIRV_TOOLS=ON)
Tests ✅ 2,433 passed · 13 failed (0 new, 9 also fail on main, 4 unstable on main) · 55 skipped (ANYPS5_REQUIRE_VULKAN=1)
Test setup CPU-only tests without a GPU; GPU tests (and any CPU-only test that failed or skipped without one) once on the GPU with VK_LAYER_KHRONOS_validation and ANYPS5_NO_SHADER_CACHE=1; main ran the same way
Test selection 2,501 of 3,168 tests run: the ones this change can reach, chosen by tools/select_tests.py from main's build graph
Vulkan validation ✅ no new validation IDs vs main (936 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 120.4 s, ⚠️ agc_driver_graphics_maps_fallback 103.8 s, ⚠️ agc_driver_graphics 94.4 s, ⚠️ agc_driver_lazy_resolved_abi_switch_set 37.5 s, ⚠️ unwrap_self 36.2 s
Unstable on main (4, these also failed in recent main runs on this machine; not counted against this PR)
agc_driver_job_manager_compute_capacity: failed in 4 of the last 5 main runs
agc_driver_pipeline_journal: failed in 3 of the last 5 main runs
agc_submit_progress: failed in 4 of the last 5 main runs
agc_submit_progress_no_timeline: failed in 4 of the last 5 main runs
Failing on main too (9, not counted against this PR)
agc_driver_guest_memory_lifetime_direct
agc_driver_image_table
agc_driver_native_depth_bda_clear
agc_driver_native_depth_buffer_clear
agc_driver_native_depth_clears
agc_driver_native_multisample_depth
agc_idle_publish_wait
guest_mmap_executable
guest_socket_options_multicast
Validation IDs already present on main (5 IDs in 484 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (484 tests): agc_driver, agc_driver_address_passes, agc_driver_alias_copy_label, agc_driver_alpha_to_coverage, agc_driver_array_layer_target, agc_driver_bc_block_copy, agc_driver_bda_anchor_reads, agc_driver_bda_span_reads, and 476 more
VUID-vkCmdCopyImage-srcImage-01548 (6 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_partial_store, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-vkCmdCopyImage-srcImage-01551 (6 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_partial_store, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 (1 test): agc_driver_prepared_exports
VUID-VkShaderModuleCreateInfo-pCode-08737 (1 test): agc_driver_image_sample_derivatives
Skipped (55)
agc_driver_bda_reads_shadowed_results: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_bda_reads_shadowed_results_per_build: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_copied_writer_label_order: skipped, the device reports a minStorageBufferOffsetAlignment of 4, so the dispatch binds its record at +0x1004 in place and nothing is written back; the test needs an alignment above 4
agc_driver_image_table_vouched_lookups: skipped, the device reports 4 of 4 host-imported pages written after a GPU read, so a watched imported table cannot be vouched for
agc_driver_linear_target_direct_write_completion: skipped, the device does not keep host imports write-watched, so no completion stamp over the target is tracked
agc_driver_ngg_vertex_wave_reduction: skipped, s3 describes a 32-lane wave only on 32-lane subgroups, and the device has 64 lanes
agc_driver_unit_shadow: skipped, the device does not import watched host memory for unit shadows
agc_driver_unit_shadow_budget: skipped, the device does not import watched host memory for unit shadows
agc_host_import_sparse: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_import_settle_initial_dcc: skipped, the device has no deferred settle of host imports: imports under 1 MiB wait for one only on Windows
agc_pipeline_binary_vulkan: skipped, the device lacks VK_KHR_pipeline_binary
agc_shadowed_key_stores: skipped, the device imports no watched host memory under a unit shadow
agc_small_tiled_shadow_label: skipped, host imports are unavailable: the test block is not imported and watched
agc_storage_clear_hand_over: skipped, the device imports no watched host memory for the clear-key hand-over
agc_unit_shadow: skipped, the device does not import watched host memory for unit shadows
agc_unit_shadow_completion_store: skipped, the device reports watched host memory written when it imports or reads it
guest_http_uri_locale: 
guest_net_ctl: skipped, the host has no IPv4 address
guest_video_out_color_space: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_hdr: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_high_frame_rate: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_output_mode: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_resolution_status: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_wqhd_detection: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
video_out_flip_aftergpu: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_backtoback: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_controls: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip_in_order: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_dcc: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not 
Reproduce
git fetch origin a37af8b9107e47a6d3236942a0a98a581c1c567a f2d874c1fdccf781c0fa5d86619bb5dd8894b958
git checkout f2d874c1fdccf781c0fa5d86619bb5dd8894b958 && git merge --no-ff a37af8b9107e47a6d3236942a0a98a581c1c567a
git submodule update --init --recursive
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON -DANYPS5_ENABLE_SPIRV_TOOLS=ON
cmake --build build && cmake --build build --target libs
VK_DRIVER_FILES=/nonexistent/icd.json ctest --test-dir build -E '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 12 --output-on-failure
ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation \
  ctest --test-dir build -R '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 16 --output-on-failure
# failures are then re-run alone: --timeout 360 --parallel 2; new validation IDs: the test alone, twice, --parallel 1

Automated build and test on a contributor's AMD machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs.

@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head a37af8b merged onto main f2d874c · tested 2026-11-01 19:48 UTC · 23 min

GPU NVIDIA RTX 2000 Ada Generation, driver 595.99.02, Vulkan 1.4.329
Host Ubuntu 26.04.1 LTS, kernel 7.0.0-38-generic, container ubuntu:24.04
Logs build and test logs for this run
Build ✅ passed (Release, -DANYPS5_ENABLE_SPIRV_TOOLS=ON)
Tests ✅ 2,449 passed · 6 failed (0 new, 4 also fail on main, 2 unstable on main) · 46 skipped (ANYPS5_REQUIRE_VULKAN=1)
Test setup CPU-only tests without a GPU; GPU tests (and any CPU-only test that failed or skipped without one) once on the GPU with VK_LAYER_KHRONOS_validation and ANYPS5_NO_SHADER_CACHE=1; main ran the same way
Test selection 2,501 of 3,168 tests run: the ones this change can reach, chosen by tools/select_tests.py from main's build graph
Vulkan validation ✅ no new validation IDs vs main (936 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 120.1 s, ⚠️ agc_driver_graphics_maps_fallback 33.1 s, ⚠️ agc_driver_graphics 32.6 s
Unstable on main (2, these also failed in recent main runs on this machine; not counted against this PR)
agc_driver_job_manager_compute_capacity: failed in 1 of the last 10 main runs
agc_driver_pipeline_journal: failed in 1 of the last 10 main runs
Failing on main too (4, not counted against this PR)
agc_driver_dcc_keys_first_write
agc_driver_image_table
guest_mmap_executable
guest_socket_options_multicast
Validation IDs already present on main (5 IDs in 484 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (484 tests): agc_driver, agc_driver_address_passes, agc_driver_alias_copy_label, agc_driver_alpha_to_coverage, agc_driver_array_layer_target, agc_driver_bc_block_copy, agc_driver_bda_anchor_reads, agc_driver_bda_span_reads, and 476 more
VUID-vkCmdCopyImage-srcImage-01548 (7 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_sampling, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-vkCmdCopyImage-srcImage-01551 (7 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_sampling, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 (1 test): agc_driver_prepared_exports
VUID-VkShaderModuleCreateInfo-pCode-08737 (1 test): agc_driver_image_sample_derivatives
Skipped (46)
agc_driver_bda_reads_shadowed_results: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_bda_reads_shadowed_results_per_build: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_sample_order_grid_reference: skipped, the device does not keep depth drawn at custom sample locations at those locations, even after a transition that names them: the composite of uniform renders holds the guest's depth in 0 of 3005 sloped samples, so no path can be compared with it bit for bit
agc_host_import_sparse: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_import_settle_initial_dcc: skipped, the device has no deferred settle of host imports: imports under 1 MiB wait for one only on Windows
agc_pipeline_binary_vulkan: skipped, the device lacks VK_KHR_pipeline_binary
agc_unit_shadow_completion_store: skipped, the device reports watched host memory written when it imports or reads it
guest_http_uri_locale: 
guest_net_ctl: skipped, the host has no IPv4 address
guest_video_out_color_space: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_hdr: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_high_frame_rate: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_output_mode: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_resolution_status: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_wqhd_detection: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
video_out_flip_aftergpu: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_backtoback: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_controls: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip_in_order: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_dcc: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_deferred: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_eop: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_eop_aftergpu: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_eop_main: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_fps_limit: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL
Reproduce
git fetch origin a37af8b9107e47a6d3236942a0a98a581c1c567a f2d874c1fdccf781c0fa5d86619bb5dd8894b958
git checkout f2d874c1fdccf781c0fa5d86619bb5dd8894b958 && git merge --no-ff a37af8b9107e47a6d3236942a0a98a581c1c567a
git submodule update --init --recursive
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON -DANYPS5_ENABLE_SPIRV_TOOLS=ON
cmake --build build && cmake --build build --target libs
VK_DRIVER_FILES=/nonexistent/icd.json ctest --test-dir build -E '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 32 --output-on-failure
ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation \
  ctest --test-dir build -R '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 4 --output-on-failure
# failures are then re-run alone: --timeout 360 --parallel 2; new validation IDs: the test alone, twice, --parallel 1

Automated build and test on a contributor's NVIDIA machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs.

@hugodearaujo

Copy link
Copy Markdown
Contributor Author

Thanks to both of you. The two code points were the same underlying mistake (the check ran before the Buffer existed, against a heap picked without the buffer's requirements), so b491e43 fixes them together.

@oneandonlydean

  1. Context::DeviceLocalHeadroom now takes the memory type the allocation will be made from and reads the budget of that type's heap; a type on a heap without VK_MEMORY_HEAP_DEVICE_LOCAL_BIT is not held to it. The check moved into Buffer's constructor, right after BufferMemoryType(requirements.memoryTypeBits, ...) picks the type, so it uses the same memoryTypeBits and the same type the vkAllocateMemory call uses. In DeviceMemoryFallback.cpp, SecondHeapHeadroomTests adds a second device-local heap and type and runs the type choice plus the check for a mask that excludes the first local type with the first heap and then the second heap under pressure (room on the second / no room), and for a mask that allows both (the first type is chosen, so only the first heap counts). HeadroomTests keeps the earlier cases and adds a host type and an unknown type. agc_buffer_pool covers the same pair end to end through Buffer with a mock memoryTypeBits of 0b110.
  2. Added a "Staging shadow headroom" entry to docs/dev/debt/libSceAgcDriver.md, next to the texture cache budgets: refused within the last eighth of the reported budget of the heap it would be allocated from, the eighth comes from one title on one GPU, budget readings are estimates and nothing is reserved against concurrent allocations, devices without VK_EXT_memory_budget (or without a reported budget) behave as before.

@MarcZX10

  • Pool reuse: stagingBuffer now calls Buffer::WithinDeviceLocalHeadroom, which runs the normal constructor path: BufferPool::Take first, and a hit is used as before with no check. Only on a miss, after the type is chosen, is a new allocation refused when it would end within the last eighth of that heap's budget; the VkBuffer already created is destroyed and the function returns nullptr, so the region takes Region::unstaged as before. New StagingHeadroom case in agc_buffer_pool: a 24 MiB shadow is made with room, released to the pool, then with usage at 1900 of 2048 MiB (past seven eighths) a 24 MiB request gets the retained allocation with no vkAllocateMemory, while a 40 MiB request is refused with no allocation and no VkBuffer left alive.
  • Selected heap: as in point 1 above.
  • Negative controls: with the check reading the first device-local type's heap again, agc_device_memory_fallback fails the two mask-excludes-first cases and agc_buffer_pool fails both second-heap cases; with the check back before the pool lookup, agc_buffer_pool fails "a retained staging buffer was refused within the last eighth of the budget, although reusing it allocates nothing".
  • Performance: the description now has a Performance section with four aps5-summary.jsonl lines (base, change, change, base; same save, scripted route, 20 s window in the lobby before the point where the base is stopped, same machine and session, standard switches only), the trace_digest.py output and the names of the four trace files (I'll attach the files). Frame p50 is 1596 and 1761 ms on the base and 2109 and 1613 ms with the change; the slow change capture had not refused a shadow yet inside its window, so the spread is run to run. Separate APS5_TRACE_SUMMARY_EVERY=10 runs give the frame rate through the forklift room: the same presents per 10 s up to its door (9.4/6.2/5.4 base, 9.5/7.0/5.2 change), then the base is stopped at the entrance (1.3 GiB VRAM free) and the change walks through at 4.3 per 10 s and continues at 6.7.

Validation (RX 9070 XT, RADV Mesa 26.2.6, Linux), ctest -V -R 'agc_device_memory_fallback|agc_adaptive_staging|agc_buffer_pool|staging' with VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation ANYPS5_NO_SHADER_CACHE=1 ANYPS5_REQUIRE_VULKAN=1: 7/7 on main f2d874c and 7/7 on b491e43, no VUID- line and no missing-layer line in either log. tools/check_conventions.py --base origin/main passes.

Could you take another look at b491e43?

AI-assisted: yes (Claude Code)

@github-actions github-actions Bot added docs and removed perf numbers missing perf pull request without a before and after summary line labels Nov 1, 2026
@TechLevelZero

TechLevelZero commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head b491e43 merged onto main 1d91f29 · tested 2026-11-02 20:37 UTC · 27 min

GPU NVIDIA RTX 2000 Ada Generation, driver 595.99.02, Vulkan 1.4.329
Host Ubuntu 26.04.1 LTS, kernel 7.0.0-38-generic, container ubuntu:24.04
Logs build and test logs for this run
Build ✅ passed (Release, -DANYPS5_ENABLE_SPIRV_TOOLS=ON)
Tests ✅ 2,622 passed · 4 failed (0 new, 2 also fail on main, 2 unstable on main) · 44 skipped (ANYPS5_REQUIRE_VULKAN=1)
Test setup CPU-only tests without a GPU; GPU tests (and any CPU-only test that failed or skipped without one) once on the GPU with VK_LAYER_KHRONOS_validation and ANYPS5_NO_SHADER_CACHE=1; main ran the same way
Test selection 2,670 of 3,544 tests run: the ones this change can reach, chosen by tools/select_tests.py from main's build graph
Vulkan validation ✅ no new validation IDs vs main (981 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 120.3 s, ⚠️ agc_driver_graphics_maps_fallback 34.1 s, ⚠️ agc_driver_graphics 32.2 s, ⚠️ agc_driver_native_depth_clears 30.1 s
Unstable on main (2, these also failed in recent main runs on this machine; not counted against this PR)
agc_driver_job_manager_compute_capacity: failed in 1 of the last 10 main runs
agc_driver_pipeline_journal: failed in 3 of the last 10 main runs
Failing on main too (2, not counted against this PR)
agc_driver_image_table
guest_socket_options_multicast
Passed on retry (1, failed in the parallel run, passed when re-run with a 360 s timeout; not counted against this PR)
agc_driver_native_depth_clears: Timeout in the parallel run; also passed only on retry in 18 other runs in the last 7 days
Validation IDs already present on main (4 IDs in 510 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (510 tests): agc_driver, agc_driver_address_passes, agc_driver_alias_copy_label, agc_driver_alpha_to_coverage, agc_driver_array_layer_target, agc_driver_bc_block_copy, agc_driver_bda_anchor_reads, agc_driver_bda_span_reads, and 502 more
VUID-vkCmdCopyImage-srcImage-01548 (7 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_sampling, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-vkCmdCopyImage-srcImage-01551 (7 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_sampling, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 (1 test): agc_driver_prepared_exports
Skipped (44)
agc_driver_bda_reads_shadowed_results: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_bda_reads_shadowed_results_per_build: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_sample_order_grid_reference: skipped, the device does not keep depth drawn at custom sample locations at those locations, even after a transition that names them: the composite of uniform renders holds the guest's depth in 0 of 3005 sloped samples, so no path can be compared with it bit for bit
agc_host_import_sparse: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_import_settle_initial_dcc: skipped, the device has no deferred settle of host imports: imports under 1 MiB wait for one only on Windows
agc_unit_shadow_completion_store: skipped, the device reports watched host memory written when it imports or reads it
guest_http_uri_locale: 
guest_video_out_color_space: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_hdr: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_high_frame_rate: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_output_mode: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_resolution_status: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_wqhd_detection: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
video_out_flip_aftergpu: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_backtoback: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_controls: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip_in_order: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_dcc: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_deferred: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_eop: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_eop_aftergpu: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_eop_main: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_fps_limit: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_fresh: skipped, no display or Vulkan device: 
Reproduce
git fetch origin b491e43a205dd9bab4c7823efab9f7f899ebcfe6 1d91f2966d0eef82a021628a7aa8e78e615ac807
git checkout 1d91f2966d0eef82a021628a7aa8e78e615ac807 && git merge --no-ff b491e43a205dd9bab4c7823efab9f7f899ebcfe6
git submodule update --init --recursive
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON -DANYPS5_ENABLE_SPIRV_TOOLS=ON
cmake --build build && cmake --build build --target libs
VK_DRIVER_FILES=/nonexistent/icd.json ctest --test-dir build -E '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 32 --output-on-failure
ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation \
  ctest --test-dir build -R '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 4 --output-on-failure
# failures are then re-run alone: --timeout 360 --parallel 2; new validation IDs: the test alone, twice, --parallel 1

Automated build and test on a contributor's NVIDIA machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs.

@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ AMD GPU test: passed

PR head b491e43 merged onto main f2d874c · tested 2026-11-01 21:06 UTC · 41 min

GPU AMD Radeon RX 6300 (RADV NAVI24), driver Mesa 25.2.8-0ubuntu0.24.04.4, Vulkan 1.4.318
Host Ubuntu 26.04.1 LTS, kernel 7.0.0-42-generic, container ubuntu:24.04
Logs build and test logs for this run
Build ✅ passed (Release, -DANYPS5_ENABLE_SPIRV_TOOLS=ON)
Tests ✅ 2,433 passed · 13 failed (0 new, 9 also fail on main, 4 unstable on main) · 55 skipped (ANYPS5_REQUIRE_VULKAN=1)
Test setup CPU-only tests without a GPU; GPU tests (and any CPU-only test that failed or skipped without one) once on the GPU with VK_LAYER_KHRONOS_validation and ANYPS5_NO_SHADER_CACHE=1; main ran the same way
Test selection 2,501 of 3,168 tests run: the ones this change can reach, chosen by tools/select_tests.py from main's build graph
Vulkan validation ✅ no new validation IDs vs main (936 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 120.1 s, ⚠️ agc_driver_graphics_maps_fallback 105.0 s, ⚠️ agc_driver_graphics 102.1 s, ⚠️ public_headers 45.5 s, ⚠️ agc_driver_lazy_resolved_abi_switch_set 32.9 s
Unstable on main (4, these also failed in recent main runs on this machine; not counted against this PR)
agc_driver_job_manager_compute_capacity: failed in 4 of the last 5 main runs
agc_driver_pipeline_journal: failed in 3 of the last 5 main runs
agc_submit_progress: failed in 4 of the last 5 main runs
agc_submit_progress_no_timeline: failed in 4 of the last 5 main runs
Failing on main too (9, not counted against this PR)
agc_driver_guest_memory_lifetime_direct
agc_driver_image_table
agc_driver_native_depth_bda_clear
agc_driver_native_depth_buffer_clear
agc_driver_native_depth_clears
agc_driver_native_multisample_depth
agc_idle_publish_wait
guest_mmap_executable
guest_socket_options_multicast
Validation IDs already present on main (5 IDs in 484 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (484 tests): agc_driver, agc_driver_address_passes, agc_driver_alias_copy_label, agc_driver_alpha_to_coverage, agc_driver_array_layer_target, agc_driver_bc_block_copy, agc_driver_bda_anchor_reads, agc_driver_bda_span_reads, and 476 more
VUID-vkCmdCopyImage-srcImage-01548 (6 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_partial_store, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-vkCmdCopyImage-srcImage-01551 (6 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_partial_store, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 (1 test): agc_driver_prepared_exports
VUID-VkShaderModuleCreateInfo-pCode-08737 (1 test): agc_driver_image_sample_derivatives
Skipped (55)
agc_driver_bda_reads_shadowed_results: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_bda_reads_shadowed_results_per_build: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_copied_writer_label_order: skipped, the device reports a minStorageBufferOffsetAlignment of 4, so the dispatch binds its record at +0x1004 in place and nothing is written back; the test needs an alignment above 4
agc_driver_image_table_vouched_lookups: skipped, the device reports 4 of 4 host-imported pages written after a GPU read, so a watched imported table cannot be vouched for
agc_driver_linear_target_direct_write_completion: skipped, the device does not keep host imports write-watched, so no completion stamp over the target is tracked
agc_driver_ngg_vertex_wave_reduction: skipped, s3 describes a 32-lane wave only on 32-lane subgroups, and the device has 64 lanes
agc_driver_unit_shadow: skipped, the device does not import watched host memory for unit shadows
agc_driver_unit_shadow_budget: skipped, the device does not import watched host memory for unit shadows
agc_host_import_sparse: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_import_settle_initial_dcc: skipped, the device has no deferred settle of host imports: imports under 1 MiB wait for one only on Windows
agc_pipeline_binary_vulkan: skipped, the device lacks VK_KHR_pipeline_binary
agc_shadowed_key_stores: skipped, the device imports no watched host memory under a unit shadow
agc_small_tiled_shadow_label: skipped, host imports are unavailable: the test block is not imported and watched
agc_storage_clear_hand_over: skipped, the device imports no watched host memory for the clear-key hand-over
agc_unit_shadow: skipped, the device does not import watched host memory for unit shadows
agc_unit_shadow_completion_store: skipped, the device reports watched host memory written when it imports or reads it
guest_http_uri_locale: 
guest_net_ctl: skipped, the host has no IPv4 address
guest_video_out_color_space: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_hdr: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_high_frame_rate: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_output_mode: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_resolution_status: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_wqhd_detection: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
video_out_flip_aftergpu: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_backtoback: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_controls: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip_in_order: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_dcc: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not 
Reproduce
git fetch origin b491e43a205dd9bab4c7823efab9f7f899ebcfe6 f2d874c1fdccf781c0fa5d86619bb5dd8894b958
git checkout f2d874c1fdccf781c0fa5d86619bb5dd8894b958 && git merge --no-ff b491e43a205dd9bab4c7823efab9f7f899ebcfe6
git submodule update --init --recursive
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON -DANYPS5_ENABLE_SPIRV_TOOLS=ON
cmake --build build && cmake --build build --target libs
VK_DRIVER_FILES=/nonexistent/icd.json ctest --test-dir build -E '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 12 --output-on-failure
ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation \
  ctest --test-dir build -R '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 16 --output-on-failure
# failures are then re-run alone: --timeout 360 --parallel 2; new validation IDs: the test alone, twice, --parallel 1

Automated build and test on a contributor's AMD machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs.

@hugodearaujo

Copy link
Copy Markdown
Contributor Author

The four trace captures from the Performance section are now linked in the description: 1, base, 2, change, 3, change, 4, base.

@BunnyFl

BunnyFl commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

Windows re-check of b491e43a20

Re-check of @MarcZX10's three blockers from a37af8b910, on Windows with an AMD GPU.

Blockers 1 and 2 (pool reuse at the threshold, heap of the chosen type)

b491e43a20 moves the check into Buffer's constructor (Resources.cpp):

  • It now runs after a BufferPool::Take miss (Resources.cpp:64, check at :108): a pooled allocation is reused before the check is reached.
  • It takes the type from BufferMemoryType(requirements.memoryTypeBits, …) at :107, the one the allocation uses, and reads that type's heap.
  • On refusal the constructor destroys the VkBuffer, nulls it and returns with ready false. No memory has been allocated at :108, and release() (:143) frees only a non-null memory.
Run, Windows 11, WinLibs GCC 15.2.0, Release, RX 9070 XT ctest -R '^agc_(buffer_pool.*|device_memory_fallback|memory_accounting.*)$'
Head merged onto current main 7/7 pass
Same tree with the check disabled (if (false && headroom && …) in Resources.cpp) 6/7; agc_buffer_pool fails: "a staging buffer that needs a new allocation within the last eighth of its heap's budget was not refused", "the second device-local heap is full, the buffer's mask allows only the second: made", "a refused staging buffer left its VkBuffer alive"

Blocker 3 (performance report)

The description now has four summary lines, the trace files and trace_digest.py output. One question, @hugodearaujo: the change captures are from e5b4c1a76648 and the base captures from a9b16f94d161. Neither commit is on GitHub (gh api repos/boykopovar/AnyPS5/commits/e5b4c1a76648 returns 422). From GitHub alone I can't tell whether e5b4c1a76648 contains b491e43a20's rework or the earlier gate. Could you say which, or point it at a pushed commit?

I didn't run the validation layer or PRAGMATA.

@hugodearaujo

Copy link
Copy Markdown
Contributor Author

@BunnyFl thanks for the re-check. Both capture commits are now pushed to my fork, on the branch pr14815-perf-captures: e5b4c1a766 is its tip and a9b16f94d1 is two commits below.

So the change captures include b491e43a20's rework. Comparing git diff a9b16f94d1 e5b4c1a766 with this PR's own diff gives the same changed lines in GuestBufferMemory.cpp, Resources.cpp, Resources.hpp and Context.hpp. Only the tests and the debt text differ, and those don't affect the captured run.

AI-assisted: yes (Claude Code)

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

Thanks @hugodearaujo, that settles my question about the captures.

I fetched pr14815-perf-captures. a9b16f94d1 is exactly two commits below e5b4c1a766, and between them the four production files (GuestBufferMemory.cpp, Resources.cpp, Resources.hpp, Context.hpp) change in exactly the same lines as this PR's own diff at b491e43a20 (0 differing +/- lines). So the change captures ran this head's rework, including the check in Buffer's constructor.

That and my Windows re-check of b491e43a20 cover what I raised. On Windows 11 with an RX 9070 XT, the 7 agc_buffer_pool*/agc_device_memory_fallback/agc_memory_accounting* tests pass merged onto main. With the check disabled, agc_buffer_pool fails on the threshold, chosen-heap and VkBuffer cases. The PR head is still b491e43a20 today.

I didn't run the validation layer or PRAGMATA, and I didn't re-derive the trace_digest.py numbers. @MarcZX10's change request from a37af8b910 is still open on his side.

@oneandonlydean oneandonlydean self-assigned this Nov 3, 2026
@oneandonlydean
oneandonlydean merged commit a8544c6 into boykopovar:main Nov 3, 2026
14 of 15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agc libSceAgc* docs perf Performance change unblocks title Names a title ID on the Unblocks line

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants