Skip to content

perf(recompiler): back compute scratch with a device buffer slot pool - #12764

Merged
oneandonlydean merged 8 commits into
boykopovar:mainfrom
Pipodi:perf/flat-private-aperture-1028
Nov 2, 2026
Merged

oneandonlydean merged 8 commits into
boykopovar:mainfrom
Pipodi:perf/flat-private-aperture-1028

Conversation

@Pipodi

@Pipodi Pipodi commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

What

Every compute FLAT load, store and atomic in a program with scratch tests its address against the shared and the private aperture (c35f29b). The private path reaches the per-lane scratch, held in Function scratch_dwords arrays indexed dynamically at every FLAT site. On NVIDIA that indexing is what makes large compute programs slow to compile: the SPIR-V front end (nvoglv64) spends about a third of the compile on it.

This PR keeps the FLAT routing exactly as on main, for every access, and changes only where scratch lives. A compute program that uses scratch (scratch_*, or a FLAT access routed to the private aperture) now keeps it in a storage buffer, so no Function array is declared or indexed:

  • The driver allocates one buffer per compute pipeline at its first dispatch and binds it in descriptor set 2 (the layout of the device-memory LDS buffer). The buffer holds a lock word and an invocation counter per slot, then the slots. It is capped by APS5_SCRATCH_POOL_MIB (default 64, never below one slot), by maxStorageBufferRange and by 2 GiB: on the RTX 4090 a larger buffer returned wrong values (2049 MiB fails, 2047 MiB passes). All pools together stay under APS5_SCRATCH_POOL_TOTAL_MIB (default 256); a new pool evicts the least recently used ones first. The shader takes the slot count from the array length.
  • Invocation 0 of each workgroup claims a slot with a scan that reads each lock word and tries a compare-exchange only on a free one, starting at its linear workgroup id; a barrier publishes the slot. Every invocation decrements the slot counter at every compute exit and the last one frees the lock, so divergent exits and concurrent dispatches of one pipeline share the buffer safely. The emitter fails the compile if a compute return lacks the release.
  • Programs without scratch keep their SPIR-V and pipeline layout. Graphics stages are unchanged.
  • tests/GuardedMemoryLoads.cpp changes too: that fixture runs the emitted code in its interpreter, which now skips the slot claim and offsets scratch indexes by the 2-dword slot header. It also gains checks for the new layout.

The buffer is decorated Coherent. Without it, on an RTX 4090, an unaligned 32-bit FLAT store to scratch (emitted as four byte read-modify-writes) loses the first byte of each pair sharing a dword: flat_apertures_2, flat_apertures_5 and flat_aperture_sources fail, always with the same value. It is not lane overlap (4× lane spacing gives the same result), not spirv-opt (same with it off) and Aliased doesn't help. The SPIR-V is a plain load, mask and store in program order, so this looks like a driver ordering issue, but I haven't read the GPU assembly to prove it. The debt entry in docs/dev/debt/shader.md says so.

On the review of the first version: the provenance rule, formsPrivateAperture, APS5_FLAT_PRIVATE_ALWAYS and the edit to FlatApertures.cpp are gone. main's FlatApertures.cpp is unchanged and passes. Callees reached through s_swappc_b64 are linked into the caller's graph (GraphBuilder LinkCalls), so they are translated with it and use the same buffer; the new test covers that case.

On the second review (discarded batch): the slot headers were zeroed inside the first dispatch's batch and the pool was marked zeroed before submit, so a discarded batch left a cached pool marked zeroed with garbage headers. Now the headers are zeroed once when the pool is created, in a batch submitted and waited on under the GPU lock; the zeroed flag and the in-batch fill are gone, and the pool lookup runs before the recorder opens the dispatch's commands. The debt entry "Compute scratch pool header clear" in docs/dev/debt/libSceAgcDriver.md covers the blocking submit.

On the AMD report: the test seam Recorder::FailNextSubmitsForTest threw before vkEndCommandBuffer, so the discarded batch went back to the spare list while still recording, and the next vkBeginCommandBuffer on it failed on RDNA 4 (VUID-vkBeginCommandBuffer-commandBuffer-00049, result -13). The injected failure now comes after the end and stands for a failed vkQueueSubmit.

The PR has six commits, meant to be read in order (squash on merge is fine):

  1. a46f050af8 perf(recompiler): back compute scratch with a device buffer slot pool — the change described above.
  2. f369273365 fix(agc): zero the scratch pool header when the pool is created — the fix for the discarded-batch review.
  3. d9668fdbee fix(agc): end the command buffer before the injected submit failure — the fix for the AMD report; it touches only the test seam.
  4. cc61c3ae31 perf(agc): hold all compute scratch pools under one memory budget — APS5_SCRATCH_POOL_TOTAL_MIB with LRU eviction (review point 3).
  5. ce38162aa1 fix(agc): hold one compute scratch pool under 2 GiB and the total budget.
  6. 28a30ed35d perf(shader): read a scratch pool slot lock before trying to take it (review point 4).
Why the dynamic indexing is the cost (offline replay, cold driver cache, one compile thread, PPSA26344 program 0x1994ed, 1.52M SPIR-V words)
Variant compile thread CPU nvoglv64 share
as emitted on main 141-145 s 36-37 %
scratch indices made constant 92-100 s 1.45 %
scratch arrays as Workgroup 101 s 1.34 %
scratch arrays as a storage buffer 100 s 1.38 %

Workgroup memory can't hold it: 56 dwords per lane × 512 lanes is 114 KB.

The runtime side (third review) has a cost. A local bench, not in this PR: one compute program with 448 scratch dwords per lane, median of repeated dispatches, RTX 4090, driver 617.42. It is listed in the debt file as "Compute scratch runtime cost".

Dispatch time of a scratch-heavy program, `main` against this PR
groups main (Function arrays) PR, 64 MiB pool (~580 slots) PR, Coherent dropped PR, 1 MiB pool (~9 slots) PR, 4096 MiB asked (held at 256)
256 1.56 ms 3.8 ms 3.6 ms 10.6 ms 3.7 ms
4096 22.1 ms 49 ms 48 ms 172 ms 54 ms
32768 183 ms 389 ms 379 ms 1377 ms (1308 ms with the lock read) 425 ms

About 2.4× slower at the default size; Coherent is not the cost. With fewer slots than resident groups the groups wait for a slot: reading the lock before the compare-exchange gains about 5 % at 9 slots and nothing at 580.

Tested

Windows 11, MinGW GCC 15.2, RTX 4090 (driver 617.42), i9-13900K.

  • New agc_driver_scratch_pool (tests/execution/ScratchPool.cpp), wave32 and wave64:
    • private-aperture pointers from a table load, a literal and a computed address, through FLAT store and atomic, and both ways through scratch_*;
    • a callee reached through s_swappc_b64;
    • isolation of 64 workgroups over one or two slots;
    • divergent wave exits, then a second dispatch reusing the slots;
    • module shape: no Function scratch array, and no extra binding in a program without scratch.
  • Focused run with ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation: 45/45 pass (FLAT apertures, LDS, scratch, guarded memory loads), no VUID-. Rerun of the 16 FLAT aperture and scratch pool tests with VK_LOADER_DEBUG=layer to confirm the layer loads: 16/16, no VUID-.
  • Negative control: with the release ignoring the counter, agc_driver_scratch_pool fails (isolation: "round 0 lane 0 dword 0 read 0x00002200, expected 0x00000000"; divergent exit: "round 0 lane 160 dword 0 read 0x00003180, expected 0x00000280").
  • RunDiscardedInitialization in agc_driver_scratch_pool (test seam Recorder::FailNextSubmitsForTest): discards the first dispatch's batch, then dispatches again on the cached pool. Fails before the header fix ("header word 0 reads 0xffffffff"), passes after.
  • Full ctest after rebasing onto main f7f03da: 3107/3107. The focused run above, repeated on the rebased branch: 43/43 FLAT aperture, scratch pool, LDS and guarded memory load tests, no VUID-. The rebase conflicted only where main's meshWindowBuffer field (fix(shader): keep mesh register windows out of local memory on NVIDIA #12233) sits next to scratchPoolSlotDwords (kept both, same order in the disk cache writer and reader) and in the debt file.
  • After the third commit, rebased onto main f2d874c: full ctest 3286/3286; focused run with the same environment 56/56 (FLAT apertures, scratch pool, LDS, guarded memory loads, recorder), agc_driver_scratch_pool included, no VUID-. The rebase conflicted only where main's compute pipeline binary key (0c572f1) is built: the key's first word now also sets bit 1 when the scratch pool set is bound, so keys of pipelines without scratch are unchanged.
  • After the review commits, rebased onto main be24202: full ctest 3283/3283. Focused run with the same environment (flat|scratch|lds|guarded|recorder): 64/64 on the PR, 63/63 on main, no VUID- in either.
  • The game measurements below were taken on main aaccd0b and the first commit on top of it.

PPSA26344 (Ghost of Yōtei 01.008.000), 3840x2160, fresh save, shader cache warmed by a previous run of the same build, frames 250-280 (loading). main aaccd0b and this PR alternate, three runs each. The PR build compiled about 13 compute programs with the slot pool before frame 350 (26 shader cache entries bind descriptor set 2; none on main); Those 13 are compiled, not dispatched: a local build that logs every pool creation, run warm with APS5_PROFILE_GPU=1 for 1500 s, created no pool up to frame 517 (main) and 530 (PR). So no scratch program dispatches in the window, and the trace pair below can only show compile-side effects. GPU time over frames 250-280 was 2.08 s on main and 2.20 s on the PR (noise; 50.9 s against 52.5 s over the whole run).

main:

{"commit":"aaccd0ba39b7","dirty":false,"env":{"APS5_GPU_CHECKPOINTS":"1","APS5_HOST_IMPORT_MIB":"16384","APS5_NO_PIPELINE_JOURNAL":"1","APS5_NO_RESULT_MEMO":"1","APS5_NO_SNAPSHOT_CHECK":"1APS5_SPANNED_WAVE=1","APS5_PIPELINE_DISPATCH":"1","APS5_PREBUILD_THREADS":"2","APS5_PREPARED_SPIRV_MIB":"6144","APS5_PROFILE_DRAW":"1","APS5_RESOURCE_CACHE_ENTRIES":"1024","APS5_STAGING_POOL_MIB":"2048","APS5_TRACE_FRAMES":"250:30"},"gpu":"NVIDIA GeForce RTX 4090","driver":"NVIDIA 617.42","os":"Windows 10.0.26200","cpu":"13th Gen Intel(R) Core(TM) i9-13900K","cpu_threads":32,"memory_mib":32476,"title_id":"PPSA26344","title":"Ghost of Yōtei","content_version":"01.008.000","resolution":"3840x2160","window":{"spec":"frames 250:30","first_present":250,"ms":16996.075},"presents":30,"frame_ms":{"p50":308.640,"p90":1276.579,"p99":1890.406,"max":1890.406},"gpu_busy_ms_per_present":111.751,"worker_busy_pct":{"queue worker 0x0":75.642,"queue worker 0x52":1.078,"queue worker 0x53":0.000,"queue worker 0x20":27.602,"queue worker 0x30":62.036,"queue worker 0x38":59.136,"queue worker 0x48":24.100},"top_phases_ms_per_frame":{"Driver.Packet":1410.773,"Driver.Packet.memory_wait":757.111,"Driver.Packet.dispatch":422.516,"Driver.Dispatch":407.334,"GpuMutex.wait.other":160.332,"Vulkan.Dispatch":144.609,"Vulkan.Dispatch.shader_resources":130.486,"Driver.Packet.prepare_memory":110.346},"trace_dropped":false,"trace":"aps5-trace-aaccd0ba39b7-2756.json.gz"}

This PR:

{"commit":"659d07bbc8c0","dirty":false,"env":{"APS5_GPU_CHECKPOINTS":"1","APS5_HOST_IMPORT_MIB":"16384","APS5_NO_PIPELINE_JOURNAL":"1","APS5_NO_RESULT_MEMO":"1","APS5_NO_SNAPSHOT_CHECK":"1APS5_SPANNED_WAVE=1","APS5_PIPELINE_DISPATCH":"1","APS5_PREBUILD_THREADS":"2","APS5_PREPARED_SPIRV_MIB":"6144","APS5_PROFILE_DRAW":"1","APS5_RESOURCE_CACHE_ENTRIES":"1024","APS5_STAGING_POOL_MIB":"2048","APS5_TRACE_FRAMES":"250:30"},"gpu":"NVIDIA GeForce RTX 4090","driver":"NVIDIA 617.42","os":"Windows 10.0.26200","cpu":"13th Gen Intel(R) Core(TM) i9-13900K","cpu_threads":32,"memory_mib":32476,"title_id":"PPSA26344","title":"Ghost of Yōtei","content_version":"01.008.000","resolution":"3840x2160","window":{"spec":"frames 250:30","first_present":250,"ms":13989.698},"presents":30,"frame_ms":{"p50":263.902,"p90":1098.961,"p99":1768.352,"max":1768.352},"gpu_busy_ms_per_present":102.834,"worker_busy_pct":{"queue worker 0x0":83.139,"queue worker 0x52":0.717,"queue worker 0x53":0.000,"queue worker 0x20":26.429,"queue worker 0x30":69.186,"queue worker 0x38":66.501,"queue worker 0x48":26.299},"top_phases_ms_per_frame":{"Driver.Packet":1266.947,"Driver.Packet.memory_wait":702.545,"Driver.Packet.dispatch":377.420,"Driver.Dispatch":362.764,"Vulkan.Dispatch":132.113,"Vulkan.Dispatch.shader_resources":119.352,"GpuMutex.wait.other":110.325,"Driver.Packet.prepare_memory":87.509},"trace_dropped":false,"trace":"aps5-trace-659d07bbc8c0-15012.json.gz"}
pair main (window, frame, GPU per present) this PR
1 14.5 s, p50 283 / p99 1604 ms, GPU 102.2 ms 16.5 s, p50 349 / p99 2658 ms, GPU 113.9 ms
2 16.5 s, p50 346 / p99 1939 ms, GPU 100.2 ms 15.9 s, p50 264 / p99 2134 ms, GPU 110.0 ms
3 17.0 s, p50 309 / p99 1890 ms, GPU 111.8 ms 14.0 s, p50 264 / p99 1768 ms, GPU 102.8 ms

The spread between runs of the same build (14.5-17.0 s) is larger than any difference between the two; no frame cost from the device-memory scratch shows in this scene. APS5_NO_SNAPSHOT_CHECK reads 1APS5_SPANNED_WAVE=1 because of a missing comma in my launcher, so APS5_SPANNED_WAVE is off in all six runs, as on main by default.

trace_digest, `main` (last pair)

frames 250:30 from present 250: 30 presents, frame p50 308.6 / p90 1276.6 / p99 1890.4 / max 1890.4 ms, GPU busy 111.8 ms per present
NVIDIA GeForce RTX 4090, NVIDIA 617.42, Windows 10.0.26200, 3840x2160, commit aaccd0b, dropped: no

{"commit":"aaccd0ba39b7","dirty":false,"env":{"APS5_GPU_CHECKPOINTS":"1","APS5_HOST_IMPORT_MIB":"16384","APS5_NO_PIPELINE_JOURNAL":"1","APS5_NO_RESULT_MEMO":"1","APS5_NO_SNAPSHOT_CHECK":"1APS5_SPANNED_WAVE=1","APS5_PIPELINE_DISPATCH":"1","APS5_PREBUILD_THREADS":"2","APS5_PREPARED_SPIRV_MIB":"6144","APS5_PROFILE_DRAW":"1","APS5_RESOURCE_CACHE_ENTRIES":"1024","APS5_STAGING_POOL_MIB":"2048","APS5_TRACE_FRAMES":"250:30"},"gpu":"NVIDIA GeForce RTX 4090","driver":"NVIDIA 617.42","os":"Windows 10.0.26200","cpu":"13th Gen Intel(R) Core(TM) i9-13900K","cpu_threads":32,"memory_mib":32476,"title_id":"PPSA26344","title":"Ghost of Y\u014dtei","content_version":"01.008.000","resolution":"3840x2160","window":{"spec":"frames 250:30","first_present":250,"ms":16996.075},"presents":30,"frame_ms":{"p50":308.64,"p90":1276.579,"p99":1890.406,"max":1890.406},"gpu_busy_ms_per_present":111.751,"worker_busy_pct":{"queue worker 0x0":75.642,"queue worker 0x52":1.078,"queue worker 0x53":0.0,"queue worker 0x20":27.602,"queue worker 0x30":62.036,"queue worker 0x38":59.136,"queue worker 0x48":24.1},"top_phases_ms_per_frame":{"Driver.Packet":1410.773,"Driver.Packet.memory_wait":757.111,"Driver.Packet.dispatch":422.516,"Driver.Dispatch":407.334,"GpuMutex.wait.other":160.332,"Vulkan.Dispatch":144.609,"Vulkan.Dispatch.shader_resources":130.486,"Driver.Packet.prepare_memory":110.346},"trace_dropped":false,"trace":"aps5-trace-aaccd0ba39b7-2756.json.gz"}

Slowest frames (largest slices inside each, inclusive)

  • present 273: 1890.4 ms at 8317 ms: Driver.WorkerWait (queue worker 0x20) 1812.0, Driver.WorkerWait.idle_and_completion_poll (queue worker 0x20) 1812.0, Driver.WorkerWait (queue worker 0x48) 1469.0, Driver.WorkerWait.idle_and_completion_poll (queue worker 0x48) 1469.0
  • present 277: 1312.8 ms at 13271 ms: Driver.WorkerWait (queue worker 0x48) 1114.1, Driver.WorkerWait.idle_and_completion_poll (queue worker 0x48) 1114.1, Driver.WorkerWait (queue worker 0x20) 788.8, Driver.WorkerWait.idle_and_completion_poll (queue worker 0x20) 788.8
  • present 275: 1276.6 ms at 10986 ms: Driver.WorkerWait (queue worker 0x48) 905.0, Driver.WorkerWait.idle_and_completion_poll (queue worker 0x48) 905.0, Driver.Packet (queue worker 0x0) 744.6, Driver.Packet (queue worker 0x30) 711.7
  • present 279: 1215.3 ms at 15781 ms: GpuMutex.wait.other (title) 750.5, Driver.Packet (queue worker 0x0) 607.9, Driver.WorkerWait (queue worker 0x0) 605.1, Driver.WorkerWait.idle_and_completion_poll (queue worker 0x0) 605.0
  • present 278: 1196.5 ms at 14584 ms: Driver.WorkerWait (queue worker 0x20) 1171.1, Driver.WorkerWait.idle_and_completion_poll (queue worker 0x20) 1171.1, Driver.WorkerWait (queue worker 0x48) 1022.8, Driver.WorkerWait.idle_and_completion_poll (queue worker 0x48) 1022.8

Threads (ms per frame)

thread busy wait untraced in slices < 20 us largest
title 8.6 (2 %) 160.0 (28 %) 397.9 0.5 Shader.Register 6.8, Shader.ResolveAbi 1.8
shader prepare 3.5 (1 %) 0.0 (0 %) 563.0 0.0 Shader.PrepareArtifact 3.5
shader prepare 3.3 (1 %) 0.0 (0 %) 563.2 0.0 Shader.PrepareArtifact 3.3
shader prepare 3.4 (1 %) 0.0 (0 %) 563.1 0.0 Shader.PrepareArtifact 3.4
shader prepare 3.7 (1 %) 0.0 (0 %) 562.9 0.0 Shader.PrepareArtifact 3.7
shader prepare 3.2 (1 %) 0.0 (0 %) 563.3 0.0 Shader.PrepareArtifact 3.2
shader prepare 3.6 (1 %) 0.0 (0 %) 562.9 0.0 Shader.PrepareArtifact 3.6
shader prepare 3.4 (1 %) 0.0 (0 %) 563.2 0.0 Shader.PrepareArtifact 3.4
shader prepare 3.4 (1 %) 0.0 (0 %) 563.1 0.0 Shader.PrepareArtifact 3.4
shader prepare 3.4 (1 %) 0.0 (0 %) 563.2 0.0 Shader.PrepareArtifact 3.4
shader prepare 3.5 (1 %) 0.0 (0 %) 563.1 0.0 Shader.PrepareArtifact 3.5
shader prepare 3.1 (1 %) 0.0 (0 %) 563.4 0.0 Shader.PrepareArtifact 3.1
shader prepare 3.8 (1 %) 0.0 (0 %) 562.7 0.0 Shader.PrepareArtifact 3.8
shader prepare 3.3 (1 %) 0.0 (0 %) 563.3 0.0 Shader.PrepareArtifact 3.3
shader prepare 3.9 (1 %) 0.0 (0 %) 562.7 0.0 Shader.PrepareArtifact 3.9
shader prepare 3.6 (1 %) 0.0 (0 %) 562.9 0.0 Shader.PrepareArtifact 3.6
shader prepare 3.4 (1 %) 0.0 (0 %) 563.1 0.0 Shader.PrepareArtifact 3.4
shader prepare 11.1 (2 %) 0.0 (0 %) 555.4 0.0 Vulkan.ComputePipeline 10.4, Vulkan.GraphicsPipelinePrebuild 0.7
shader prepare 9.4 (2 %) 0.0 (0 %) 557.1 0.0 Vulkan.ComputePipeline 8.6, Vulkan.GraphicsPipelinePrebuild 0.8
queue worker 0x0 312.0 (55 %) 251.3 (44 %) 3.3 13.7 Driver.Packet 426.0, Driver.Completion 0.0
queue worker 0x52 1.6 (0 %) 174.2 (31 %) 390.7 0.1 Driver.Packet 5.7, Driver.EndSubmission 0.4
queue worker 0x20 13.8 (2 %) 532.2 (94 %) 20.5 0.2 Driver.Packet 155.8, Driver.EndSubmission 0.5
title 1.9 (0 %) 0.0 (0 %) 564.6 0.0 Shader.ResolveAbi 1.9, Shader.ResolveGraphicsStagesAbi 0.1
title 1.6 (0 %) 0.0 (0 %) 564.9 0.0 Shader.ResolveAbi 1.5, Shader.ResolveGraphicsStagesAbi 0.1
title 0.3 (0 %) 0.0 (0 %) 566.2 0.0 Shader.ResolveAbi 0.3, Shader.ResolveGraphicsStagesAbi 0.0
queue worker 0x30 23.5 (4 %) 538.4 (95 %) 4.6 0.8 Driver.Packet 351.1, Driver.EndSubmission 0.3
queue worker 0x38 120.2 (21 %) 440.0 (78 %) 6.3 4.6 Driver.Packet 333.6, Driver.EndSubmission 0.7
queue worker 0x48 37.7 (7 %) 516.1 (91 %) 12.8 1.7 Driver.Packet 135.1, Driver.EndSubmission 1.3
draw committer 87.8 (15 %) 27.5 (5 %) 451.2 0.8 Graphics.Draw 90.2, Recorder.Sync 1.7
presenter 6.1 (1 %) 0.0 (0 %) 560.4 0.1 VideoOut.Flip 5.9, Driver.Present 0.2
title 0.9 (0 %) 0.0 (0 %) 565.6 0.0 Shader.ResolveAbi 0.9, Shader.ResolveGraphicsStagesAbi 0.0
title 1.5 (0 %) 0.0 (0 %) 565.0 0.0 Shader.ResolveAbi 1.4, Shader.ResolveGraphicsStagesAbi 0.0
title 3.8 (1 %) 0.0 (0 %) 562.8 0.0 Shader.ResolveAbi 3.7, Shader.ResolveGraphicsStagesAbi 0.1
title 1.4 (0 %) 0.0 (0 %) 565.1 0.0 Shader.ResolveAbi 1.3, Shader.ResolveGraphicsStagesAbi 0.1
title 1.4 (0 %) 0.0 (0 %) 565.2 0.0 Shader.ResolveAbi 1.3, Shader.ResolveGraphicsStagesAbi 0.0
title 0.1 (0 %) 0.0 (0 %) 566.4 0.0 Shader.ResolveAbi 0.1, Shader.ResolveGraphicsStagesAbi 0.0
title 1.3 (0 %) 0.0 (0 %) 565.2 0.0 Shader.ResolveAbi 1.2, Shader.ResolveGraphicsStagesAbi 0.0
gpu 112.1 (20 %) 0.0 (0 %) 454.5 0.0 batch 112.1

Largest slices (ms per frame, inclusive, all threads): Driver.WorkerWait 1550.5, Driver.WorkerWait.idle_and_completion_poll 1550.5, Driver.Packet 1407.2, Driver.Packet.memory_wait 757.1, Driver.Packet.dispatch 421.3, Driver.Dispatch 405.4, GpuMutex.wait.other 160.2, Vulkan.Dispatch 143.7

Longest waits

  • Driver.WorkerWait (queue worker 0x20) 1637.3 ms at 7592 ms, present 271
  • Driver.WorkerWait (queue worker 0x48) 1427.7 ms at 7878 ms, present 272
  • Driver.WorkerWait (queue worker 0x20) 1281.9 ms at 13907 ms, present 277
  • Driver.WorkerWait (queue worker 0x48) 1275.1 ms at 12633 ms, present 276
  • Driver.WorkerWait (queue worker 0x20) 1204.3 ms at 12179 ms, present 275
  • Driver.WorkerWait (queue worker 0x38) 1175.3 ms at 8130 ms, present 272
  • Driver.WorkerWait (queue worker 0x20) 1158.9 ms at 15215 ms, present 278
  • Driver.WorkerWait (queue worker 0x30) 1153.5 ms at 8152 ms, present 272

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

  • batch 3891: 93.2 ms at 13076 ms, present 276: GPU no ranges; recorded by Recorder.Sync (queue worker 0x30) 93.6, Driver.Packet (queue worker 0x30) 23.0, Driver.Packet.dispatch (queue worker 0x30) 23.0, Driver.Dispatch (queue worker 0x30) 23.0
  • batch 450: 50.0 ms at 3280 ms, present 256: GPU no ranges; recorded by Driver.Packet (queue worker 0x30) 207.8, Driver.Packet.dispatch (queue worker 0x30) 207.8, Recorder.Sync (queue worker 0x30) 50.2, Driver.Dispatch (queue worker 0x30) 45.9
  • batch 3875: 40.9 ms at 12860 ms, present 276: GPU no ranges; recorded by Recorder.Sync (queue worker 0x38) 41.6, Driver.Packet (queue worker 0x38) 41.5, Driver.Packet.dispatch (queue worker 0x38) 41.5, Driver.Dispatch (queue worker 0x38) 41.5
  • batch 2948: 29.0 ms at 9835 ms, present 273: GPU no ranges; recorded by Driver.Packet (queue worker 0x38) 110.7, Driver.Packet.memory_wait (queue worker 0x38) 82.6, Driver.Dispatch (queue worker 0x38) 28.1, Driver.Packet.dispatch (queue worker 0x38) 28.1
  • batch 361: 28.5 ms at 2637 ms, present 255: GPU no ranges; recorded by Recorder.Sync (queue worker 0x38) 28.9, Driver.Packet (queue worker 0x38) 9.6, Driver.Packet.dispatch (queue worker 0x38) 9.6, Driver.Dispatch (queue worker 0x38) 9.6
trace_digest, this PR (last pair)

frames 250:30 from present 250: 30 presents, frame p50 263.9 / p90 1099.0 / p99 1768.4 / max 1768.4 ms, GPU busy 102.8 ms per present
NVIDIA GeForce RTX 4090, NVIDIA 617.42, Windows 10.0.26200, 3840x2160, commit 659d07b, dropped: no

{"commit":"659d07bbc8c0","dirty":false,"env":{"APS5_GPU_CHECKPOINTS":"1","APS5_HOST_IMPORT_MIB":"16384","APS5_NO_PIPELINE_JOURNAL":"1","APS5_NO_RESULT_MEMO":"1","APS5_NO_SNAPSHOT_CHECK":"1APS5_SPANNED_WAVE=1","APS5_PIPELINE_DISPATCH":"1","APS5_PREBUILD_THREADS":"2","APS5_PREPARED_SPIRV_MIB":"6144","APS5_PROFILE_DRAW":"1","APS5_RESOURCE_CACHE_ENTRIES":"1024","APS5_STAGING_POOL_MIB":"2048","APS5_TRACE_FRAMES":"250:30"},"gpu":"NVIDIA GeForce RTX 4090","driver":"NVIDIA 617.42","os":"Windows 10.0.26200","cpu":"13th Gen Intel(R) Core(TM) i9-13900K","cpu_threads":32,"memory_mib":32476,"title_id":"PPSA26344","title":"Ghost of Y\u014dtei","content_version":"01.008.000","resolution":"3840x2160","window":{"spec":"frames 250:30","first_present":250,"ms":13989.698},"presents":30,"frame_ms":{"p50":263.902,"p90":1098.961,"p99":1768.352,"max":1768.352},"gpu_busy_ms_per_present":102.834,"worker_busy_pct":{"queue worker 0x0":83.139,"queue worker 0x52":0.717,"queue worker 0x53":0.0,"queue worker 0x20":26.429,"queue worker 0x30":69.186,"queue worker 0x38":66.501,"queue worker 0x48":26.299},"top_phases_ms_per_frame":{"Driver.Packet":1266.947,"Driver.Packet.memory_wait":702.545,"Driver.Packet.dispatch":377.42,"Driver.Dispatch":362.764,"Vulkan.Dispatch":132.113,"Vulkan.Dispatch.shader_resources":119.352,"GpuMutex.wait.other":110.325,"Driver.Packet.prepare_memory":87.509},"trace_dropped":false,"trace":"aps5-trace-659d07bbc8c0-15012.json.gz"}

Slowest frames (largest slices inside each, inclusive)

  • present 274: 1768.4 ms at 7705 ms: Driver.WorkerWait (queue worker 0x20) 1676.9, Driver.WorkerWait.idle_and_completion_poll (queue worker 0x20) 1676.9, Driver.WorkerWait (queue worker 0x48) 1336.1, Driver.WorkerWait.idle_and_completion_poll (queue worker 0x48) 1336.1
  • present 278: 1159.4 ms at 11731 ms: Driver.WorkerWait (queue worker 0x48) 971.2, Driver.WorkerWait.idle_and_completion_poll (queue worker 0x48) 971.2, Driver.WorkerWait (queue worker 0x38) 696.6, Driver.WorkerWait.idle_and_completion_poll (queue worker 0x38) 696.6
  • present 279: 1099.0 ms at 12891 ms: Driver.WorkerWait (queue worker 0x20) 992.4, Driver.WorkerWait.idle_and_completion_poll (queue worker 0x20) 992.4, Driver.WorkerWait (queue worker 0x0) 626.3, Driver.WorkerWait.idle_and_completion_poll (queue worker 0x0) 626.3
  • present 257: 1086.3 ms at 2263 ms: Driver.WorkerWait (queue worker 0x52) 1081.9, Driver.WorkerWait.idle_and_completion_poll (queue worker 0x52) 1081.9, Driver.Packet (queue worker 0x0) 1081.7, Driver.WorkerWait (queue worker 0x48) 935.8
  • present 277: 768.1 ms at 10963 ms: Driver.WorkerWait (queue worker 0x20) 768.1, Driver.WorkerWait.idle_and_completion_poll (queue worker 0x20) 768.1, Driver.Packet (queue worker 0x0) 754.4, Driver.Packet (queue worker 0x30) 684.8

Threads (ms per frame)

thread busy wait untraced in slices < 20 us largest
title 8.2 (2 %) 110.1 (24 %) 348.0 0.5 Shader.Register 5.4, Shader.ResolveAbi 2.8
shader prepare 3.3 (1 %) 0.0 (0 %) 463.0 0.0 Shader.PrepareArtifact 3.3
shader prepare 3.4 (1 %) 0.0 (0 %) 463.0 0.0 Shader.PrepareArtifact 3.4
shader prepare 3.8 (1 %) 0.0 (0 %) 462.5 0.0 Shader.PrepareArtifact 3.8
shader prepare 3.4 (1 %) 0.0 (0 %) 462.9 0.0 Shader.PrepareArtifact 3.4
shader prepare 3.3 (1 %) 0.0 (0 %) 463.0 0.0 Shader.PrepareArtifact 3.3
shader prepare 3.4 (1 %) 0.0 (0 %) 462.9 0.0 Shader.PrepareArtifact 3.4
shader prepare 3.0 (1 %) 0.0 (0 %) 463.3 0.0 Shader.PrepareArtifact 3.0
shader prepare 3.4 (1 %) 0.0 (0 %) 462.9 0.0 Shader.PrepareArtifact 3.4
shader prepare 3.4 (1 %) 0.0 (0 %) 462.9 0.0 Shader.PrepareArtifact 3.4
shader prepare 3.3 (1 %) 0.0 (0 %) 463.0 0.0 Shader.PrepareArtifact 3.3
shader prepare 3.4 (1 %) 0.0 (0 %) 462.9 0.0 Shader.PrepareArtifact 3.4
shader prepare 3.4 (1 %) 0.0 (0 %) 462.9 0.0 Shader.PrepareArtifact 3.4
shader prepare 3.2 (1 %) 0.0 (0 %) 463.1 0.0 Shader.PrepareArtifact 3.2
shader prepare 3.7 (1 %) 0.0 (0 %) 462.7 0.0 Shader.PrepareArtifact 3.7
shader prepare 3.4 (1 %) 0.0 (0 %) 462.9 0.0 Shader.PrepareArtifact 3.4
shader prepare 3.6 (1 %) 0.0 (0 %) 462.7 0.0 Shader.PrepareArtifact 3.6
shader prepare 8.0 (2 %) 0.0 (0 %) 458.3 0.0 Vulkan.ComputePipeline 7.3, Vulkan.GraphicsPipelinePrebuild 0.8
shader prepare 11.0 (2 %) 0.0 (0 %) 455.3 0.0 Vulkan.ComputePipeline 10.3, Vulkan.GraphicsPipelinePrebuild 0.7
queue worker 0x0 276.8 (59 %) 186.4 (40 %) 3.2 13.2 Driver.Packet 385.2, Driver.Completion 0.0
queue worker 0x52 1.4 (0 %) 170.9 (37 %) 294.1 0.1 Driver.Packet 3.0, Driver.EndSubmission 0.3
queue worker 0x20 9.7 (2 %) 447.0 (96 %) 9.6 0.2 Driver.Packet 123.0, Driver.EndSubmission 0.2
title 0.3 (0 %) 0.0 (0 %) 466.1 0.0 Shader.ResolveAbi 0.2, Shader.ResolveGraphicsStagesAbi 0.0
title 1.3 (0 %) 0.0 (0 %) 465.0 0.0 Shader.ResolveAbi 1.3, Shader.ResolveGraphicsStagesAbi 0.0
title 1.3 (0 %) 0.0 (0 %) 465.1 0.0 Shader.ResolveAbi 1.2, Shader.ResolveGraphicsStagesAbi 0.0
queue worker 0x30 19.6 (4 %) 444.8 (95 %) 1.9 0.8 Driver.Packet 322.3, Driver.EndSubmission 0.2
queue worker 0x38 111.6 (24 %) 351.8 (75 %) 3.0 4.6 Driver.Packet 308.5, Driver.EndSubmission 0.9
queue worker 0x48 35.5 (8 %) 421.7 (90 %) 9.1 1.8 Driver.Packet 121.5, Driver.EndSubmission 1.0
draw committer 76.9 (16 %) 23.1 (5 %) 366.3 0.8 Graphics.Draw 77.5, Vulkan.DrawFromRecipe 1.5
presenter 6.3 (1 %) 0.0 (0 %) 460.0 0.1 VideoOut.Flip 6.0, Driver.Present 0.2
title 1.4 (0 %) 0.0 (0 %) 465.0 0.0 Shader.ResolveAbi 1.3, Shader.ResolveGraphicsStagesAbi 0.0
title 0.9 (0 %) 0.0 (0 %) 465.4 0.0 Shader.ResolveAbi 0.9, Shader.ResolveGraphicsStagesAbi 0.0
title 0.8 (0 %) 0.0 (0 %) 465.5 0.0 Shader.ResolveAbi 0.7, Shader.ResolveGraphicsStagesAbi 0.0
title 1.6 (0 %) 0.0 (0 %) 464.8 0.0 Shader.ResolveAbi 1.5, Shader.ResolveGraphicsStagesAbi 0.0
title 1.3 (0 %) 0.0 (0 %) 465.0 0.0 Shader.ResolveAbi 1.3, Shader.ResolveGraphicsStagesAbi 0.0
title 2.0 (0 %) 0.0 (0 %) 464.3 0.0 Shader.ResolveAbi 1.9, Shader.ResolveGraphicsStagesAbi 0.0
title 1.3 (0 %) 0.0 (0 %) 465.0 0.0 Shader.ResolveAbi 1.3, Shader.ResolveGraphicsStagesAbi 0.1
gpu 99.8 (21 %) 0.0 (0 %) 366.6 0.0 batch 99.8

Largest slices (ms per frame, inclusive, all threads): Driver.Packet 1263.4, Driver.WorkerWait 1211.0, Driver.WorkerWait.idle_and_completion_poll 1211.0, Driver.Packet.memory_wait 702.5, Driver.Packet.dispatch 376.2, Driver.Dispatch 360.8, Vulkan.Dispatch 131.1, Vulkan.Dispatch.shader_resources 118.4

Longest waits

  • Driver.WorkerWait (queue worker 0x20) 1598.9 ms at 6995 ms, present 272
  • Driver.WorkerWait (queue worker 0x48) 1420.1 ms at 7238 ms, present 273
  • Driver.WorkerWait (queue worker 0x20) 1213.3 ms at 12289 ms, present 278
  • Driver.WorkerWait (queue worker 0x38) 1160.9 ms at 7497 ms, present 273
  • Driver.WorkerWait (queue worker 0x30) 1141.5 ms at 7516 ms, present 273
  • Driver.WorkerWait (queue worker 0x52) 1122.8 ms at 2287 ms, present 257
  • Driver.WorkerWait (queue worker 0x48) 1039.0 ms at 12478 ms, present 278
  • Driver.WorkerWait (queue worker 0x48) 964.4 ms at 11325 ms, present 277

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

  • batch 3981: 77.5 ms at 11579 ms, present 277: GPU no ranges; recorded by Recorder.Sync (queue worker 0x30) 77.8, Driver.Packet (queue worker 0x30) 21.3, Driver.Packet.dispatch (queue worker 0x30) 21.3, Driver.Dispatch (queue worker 0x30) 21.3
  • batch 505: 57.1 ms at 2702 ms, present 257: GPU no ranges; recorded by Driver.Packet (queue worker 0x30) 171.0, Driver.Packet.dispatch (queue worker 0x30) 171.0, Recorder.Sync (queue worker 0x30) 57.5, Driver.Dispatch (queue worker 0x30) 45.1
  • batch 581: 18.7 ms at 3680 ms, present 258: GPU no ranges; recorded by Driver.Packet (queue worker 0x38) 19.2, Driver.Packet.prepare_memory (queue worker 0x38) 19.0, Vulkan.Dispatch.shader_resources (queue worker 0x38) 0.4, Driver.Dispatch (queue worker 0x38) 0.2
  • batch 648: 18.1 ms at 3945 ms, present 259: GPU no ranges; recorded by Driver.Packet (queue worker 0x0) 18.6, Driver.Packet.prepare_memory (queue worker 0x0) 18.4, Resources.Prepare (queue worker 0x0) 0.8, Recorder.Sync (queue worker 0x0) 0.3
  • batch 717: 18.0 ms at 4178 ms, present 260: GPU no ranges; recorded by GpuMutex.wait.end (queue worker 0x20) 0.2, Driver.Packet (queue worker 0x20) 0.1, Driver.Packet.dispatch (queue worker 0x20) 0.1, Driver.Dispatch (queue worker 0x20) 0.1
Downstream only (Celegans12's yotei/best plus local changes, not main): PPSA26344 all cold to frame 1200

Same downstream build and environment in each row; only the scratch handling differs. Cold shader cache, NVIDIA driver cache moved aside, fresh save.

run scratch frame 700 frame 1000 frame 1200 compile s: 0x8000173b00 / 117800 / 14e300 / 167500
run570 Function arrays (as on main) 363 s 758 s 1,012 s 199 / 217 / 162 / 176
run575 this PR 322 s 664 s 905 s 146 / 168 / 117 / 114

run570 also lacks one other local change (#6867), so its frame times are not a pure A/B; the compile times of the four programs are. Offline, from captures of the same programs (one compile thread, cold driver cache): 1.69M and 1.57M words compile in 100 s each with this PR, against 135-137 s for 1.45-1.52M words with the arrays.

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: none
  • GPUs tested: NVIDIA RTX 4090, driver 617.42, Windows 11
  • AI-assisted: yes

🤖 Generated with Claude Code

@github-actions github-actions Bot added perf Performance change perf numbers missing perf pull request without a before and after summary line labels Oct 29, 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.

@oneandonlydean

Copy link
Copy Markdown
Collaborator

@Pipodi Please keep private-aperture routing when FLAT pointer provenance is unknown. No src_private_base/limit read does not prove a pointer loaded from memory, supplied in SGPRs, or made from a literal cannot name scratch; the new default drops previously supported accesses to BDA. Eliminate the route only with a conservative address proof, or retain the safe default for this experiment.

Please retain the original memory-fed Private/Mixed FlatApertures kernels without injecting the unused MovPrivateBase at lines 150/181. Add execution coverage of private pointers from memory/literals/computation and callee cases, with load/store/atomic and both wave sizes; structural absence of a constant or array is not proof that routing can be removed.

In the new shader debt entry, use PPSA26344 instead of the game name and label the compile-time numbers as downstream-tree results. Also correct the cache-key sentence: the quoted APS5_FLAT_PRIVATE_ALWAYS name is automatically discovered into Generated::RecompilerSwitches and is not neutral, so normal disk keys already include its value. FormatVersion stays 49; changed source hashes invalidate older entries.

@adriadam10 Keeping you in the loop as the assigned maintainer.

Two smaller points from a second review:

  • ENVIRONMENT.md order. The APS5_FLAT_PRIVATE_ALWAYS row sits between APS5_BDA_BYTE_READS and APS5_BDA_DWORD_STORES; the table is alphabetical, so it goes after APS5_EXACT_RCP.
  • Question (callees). formsPrivateAperture is set on the program's ShaderInfo when readRawU32 sees the operand. If a program calls code that reads src_private_base and that code is translated as a separate program, does the flag reach the program that owns the FLAT access? A line saying how callees are handled would settle it (the debt entry could carry it).

@Pipodi
Pipodi marked this pull request as draft October 29, 2026 09:00
@Pipodi

Pipodi commented Oct 29, 2026

Copy link
Copy Markdown
Contributor Author

@oneandonlydean thanks for the careful review. You're right on the main point, and I'm converting this to a draft.

Provenance. Not reading src_private_base/src_private_limit doesn't prove that no private-aperture pointer reaches a FLAT access: one can come from memory, user SGPRs or a literal. The PR made that case fault by default, so the rule is unsound. The FlatApertures change made it worse: those kernels load their Private/Mixed pointers from memory, and adding MovPrivateBase hid exactly the case they cover. I'll restore them unchanged.

Plan. The cost isn't the routing itself but the shape of the private branch: dynamically indexed scratch arrays at every FLAT site. In an offline replay of one 1.52M-word compute program (downstream tree, PPSA26344, RTX 4090), backing scratch with a storage buffer instead of function-local arrays brought the compile from 141-145 s to about 100 s, and NVIDIA's front end from 36-37 % to 1.4 % of it, the same as removing the branch. So the next version keeps private-aperture routing for every compute FLAT access and changes only how the private branch reaches scratch. No provenance assumption, no switch.

Coverage I'll add: private pointers loaded from memory, from a literal and computed, through load, store and atomic, in wave32 and wave64, plus a callee case.

Smaller points, all of them taken:

  • The cache-key sentence was wrong: ShaderCacheVersion.cmake picks up the quoted name into Generated::RecompilerSwitches, so disk keys already include it. With the rework, the switch and that sentence go away.
  • The debt entry will name PPSA26344 and mark the compile times as downstream-tree results.
  • The ENVIRONMENT.md row was out of order. It goes away with the switch; any new row will sit in alphabetical order.
  • Callees: LinkCalls links s_swappc_b64 callees into the caller's graph, so they are translated as part of the program that owns the FLAT access, not separately. That will be in the debt entry if anything there still depends on it.

I'll mark it ready again once the storage-buffer version and the tests are in.

@github-actions

github-actions Bot commented Oct 29, 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 7464 core/libs/prx/libSceAgcDriver/Graphics/src/Recorder.cpp L3812
PR 9508 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp L4241-4242, L5520, L5522-5527
core/shader/recompiler/Recompiler.hpp L436
PR 10193 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp L4241-4242, L5520, L5522-5527
core/shader/recompiler/Recompiler.hpp L436
PR 10443 docs/dev/ENVIRONMENT.md L420
PR 12840 core/libs/prx/libSceAgcDriver/Execution/include/VulkanDevice.hpp L390-391
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp L5519-5520
PR 12944 core/libs/prx/libSceAgcDriver/tests/GuardedMemoryLoads.cpp L250
core/shader/recompiler/Recompiler.cpp L731, L1168
core/shader/recompiler/Recompiler.hpp L768
core/shader/recompiler/ShaderDiskCache.cpp L546, L612
core/shader/recompiler/SpirvBackend/include/SpirvBackend/SpirvEmitter.hpp L53
core/shader/recompiler/SpirvBackend/src/SpirvEmitter.cpp L343-344
PR 13021 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp L5303
PR 13023 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp L5303
PR 13858 docs/dev/debt/libSceAgcDriver.md L355
PR 13863 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp L703-704
PR 13920 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp L703-704
PR 13928 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp L4241-4242, L5520, L5522-5527
core/shader/recompiler/Recompiler.hpp L436
PR 13929 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp L4241-4242, L5520, L5522-5527
core/shader/recompiler/Recompiler.hpp L436
PR 15169 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp L5519-5520

Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.

Pull request Shared files not compared
PR 1395 core/libs/prx/libSceAgcDriver/Execution/include/VulkanDevice.hpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 1896 docs/dev/ENVIRONMENT.md
PR 2434 core/libs/prx/libSceAgcDriver/Execution/include/VulkanDevice.hpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/debt/libSceAgcDriver.md
PR 4040 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 4472 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/ENVIRONMENT.md
PR 5021 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/SpirvBackend/include/SpirvBackend/SpirvEmitterState.hpp
core/shader/recompiler/SpirvBackend/src/SpirvEmitter.cpp
core/shader/recompiler/SpirvBackend/src/SpirvFlowEmitter.cpp
docs/dev/debt/shader.md
PR 5371 docs/dev/debt/shader.md
PR 5609 core/libs/prx/libSceAgcDriver/Graphics/include/Recorder.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Recorder.cpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Recompiler.hpp
core/shader/recompiler/ShaderDiskCache.cpp
PR 5925 core/libs/prx/libSceAgcDriver/Execution/include/VulkanDevice.hpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/shader/recompiler/CMakeLists.txt
core/shader/recompiler/Recompiler.hpp
core/shader/recompiler/ShaderDiskCache.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6186 core/libs/prx/libSceAgcDriver/Graphics/include/Recorder.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Recorder.cpp
docs/dev/ENVIRONMENT.md
docs/dev/debt/libSceAgcDriver.md
PR 6188 core/libs/prx/libSceAgcDriver/Execution/include/VulkanDevice.hpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/shader/recompiler/Recompiler.hpp
PR 6194 docs/dev/debt/libSceAgcDriver.md
PR 6223 docs/dev/debt/libSceAgcDriver.md
PR 6235 core/shader/recompiler/Recompiler.hpp
core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvEmitterHelpers.cpp
core/shader/recompiler/SpirvBackend/src/SpirvModuleEmitter.cpp
docs/dev/debt/shader.md
PR 6273 docs/dev/debt/libSceAgcDriver.md
PR 6280 core/shader/recompiler/ShaderDiskCache.cpp
docs/dev/debt/libSceAgcDriver.md
docs/dev/debt/shader.md
PR 6412 core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Recompiler.hpp
core/shader/recompiler/ShaderDiskCache.cpp
docs/dev/debt/libSceAgcDriver.md
docs/dev/debt/shader.md
PR 6481 docs/dev/debt/libSceAgcDriver.md
PR 6488 core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/ShaderDiskCache.cpp
core/shader/recompiler/SpirvBackend/src/SpirvEmitter.cpp
docs/dev/debt/shader.md
PR 6548 docs/dev/debt/libSceAgcDriver.md
PR 6751 core/shader/recompiler/SpirvBackend/include/SpirvBackend/SpirvEmitterState.hpp
core/shader/recompiler/SpirvBackend/src/SpirvBdaFault.cpp
core/shader/recompiler/SpirvBackend/src/SpirvEmitter.cpp
core/shader/recompiler/SpirvBackend/src/SpirvFlowEmitter.cpp
PR 6804 core/libs/prx/libSceAgcDriver/Execution/include/VulkanDevice.hpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6808 docs/dev/debt/libSceAgcDriver.md
PR 6924 core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/ShaderDiskCache.cpp
docs/dev/ENVIRONMENT.md
docs/dev/debt/shader.md
PR 6970 core/shader/recompiler/Recompiler.hpp
core/shader/recompiler/ShaderDiskCache.cpp
PR 7223 core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/ShaderDiskCache.cpp
docs/dev/debt/shader.md
PR 7256 docs/dev/debt/libSceAgcDriver.md
PR 7275 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 7392 core/shader/recompiler/SpirvBackend/include/SpirvBackend/SpirvEmitterState.hpp
core/shader/recompiler/SpirvBackend/src/SpirvBdaFault.cpp
core/shader/recompiler/SpirvBackend/src/SpirvEmitter.cpp
core/shader/recompiler/SpirvBackend/src/SpirvFlowEmitter.cpp
docs/dev/debt/shader.md
PR 7410 core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Recompiler.hpp
core/shader/recompiler/SpirvBackend/src/SpirvFlowEmitter.cpp
docs/dev/debt/shader.md
PR 7449 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/ENVIRONMENT.md
docs/dev/debt/libSceAgcDriver.md
PR 7457 docs/dev/ENVIRONMENT.md
PR 7514 docs/dev/ENVIRONMENT.md
PR 7604 docs/dev/ENVIRONMENT.md
docs/dev/debt/libSceAgcDriver.md
PR 7642 core/libs/prx/libSceAgcDriver/Execution/include/VulkanDevice.hpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/Recorder.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Recorder.cpp
core/shader/recompiler/CMakeLists.txt
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Recompiler.hpp
core/shader/recompiler/ShaderDiskCache.cpp
core/shader/recompiler/SpirvBackend/include/SpirvBackend/SpirvEmitter.hpp
core/shader/recompiler/SpirvBackend/include/SpirvBackend/SpirvEmitterHelpers.hpp
core/shader/recompiler/SpirvBackend/include/SpirvBackend/SpirvEmitterState.hpp
core/shader/recompiler/SpirvBackend/include/SpirvBackend/SpirvMemory/SpirvBufferAccess.hpp
core/shader/recompiler/SpirvBackend/src/SpirvBdaFault.cpp
core/shader/recompiler/SpirvBackend/src/SpirvEmitter.cpp
core/shader/recompiler/SpirvBackend/src/SpirvFlowEmitter.cpp
core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvBufferAccess.cpp
core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvEmitterHelpers.cpp
core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvModuleSetup.cpp
core/shader/recompiler/SpirvBackend/src/SpirvModuleEmitter.cpp
docs/dev/ENVIRONMENT.md
docs/dev/debt/libSceAgcDriver.md
PR 7668 docs/dev/debt/libSceAgcDriver.md
PR 7684 core/shader/recompiler/ShaderDiskCache.cpp
docs/dev/debt/shader.md
PR 7689 core/shader/recompiler/Recompiler.hpp
core/shader/recompiler/ShaderDiskCache.cpp
PR 8004 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/shader/recompiler/CMakeLists.txt
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Recompiler.hpp
core/shader/recompiler/SpirvBackend/include/SpirvBackend/SpirvEmitter.hpp
core/shader/recompiler/SpirvBackend/include/SpirvBackend/SpirvEmitterState.hpp
core/shader/recompiler/SpirvBackend/src/SpirvEmitter.cpp
docs/dev/ENVIRONMENT.md
docs/dev/debt/shader.md
PR 8246 docs/dev/ENVIRONMENT.md
PR 8484 docs/dev/ENVIRONMENT.md
PR 8592 docs/dev/debt/libSceAgcDriver.md
PR 8707 docs/dev/debt/libSceAgcDriver.md
PR 9012 docs/dev/ENVIRONMENT.md
PR 9020 core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Recompiler.hpp
core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvModuleSetup.cpp
core/shader/recompiler/SpirvBackend/src/SpirvModuleEmitter.cpp
docs/dev/debt/libSceAgcDriver.md
docs/dev/debt/shader.md
PR 9183 core/shader/recompiler/ShaderDiskCache.cpp
docs/dev/debt/shader.md
PR 9318 docs/dev/debt/libSceAgcDriver.md
PR 9335 core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Recompiler.hpp
core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvModuleSetup.cpp
core/shader/recompiler/SpirvBackend/src/SpirvModuleEmitter.cpp
docs/dev/debt/libSceAgcDriver.md
docs/dev/debt/shader.md
PR 9345 docs/dev/ENVIRONMENT.md
PR 9356 core/libs/prx/libSceAgcDriver/Execution/include/VulkanDevice.hpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Recorder.cpp
core/shader/recompiler/CMakeLists.txt
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Recompiler.hpp
core/shader/recompiler/ShaderDiskCache.cpp
core/shader/recompiler/SpirvBackend/include/SpirvBackend/SpirvEmitter.hpp
core/shader/recompiler/SpirvBackend/include/SpirvBackend/SpirvEmitterState.hpp
core/shader/recompiler/SpirvBackend/src/SpirvEmitter.cpp
core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvEmitterHelpers.cpp
core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvModuleSetup.cpp
core/shader/recompiler/SpirvBackend/src/SpirvModuleEmitter.cpp
docs/dev/ENVIRONMENT.md
docs/dev/debt/libSceAgcDriver.md
PR 9387 core/libs/prx/libSceAgcDriver/Execution/include/VulkanDevice.hpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Recorder.cpp
core/shader/recompiler/CMakeLists.txt
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Recompiler.hpp
core/shader/recompiler/ShaderDiskCache.cpp
core/shader/recompiler/SpirvBackend/include/SpirvBackend/SpirvEmitter.hpp
core/shader/recompiler/SpirvBackend/include/SpirvBackend/SpirvEmitterState.hpp
core/shader/recompiler/SpirvBackend/src/SpirvEmitter.cpp
core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvEmitterHelpers.cpp
core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvModuleSetup.cpp
core/shader/recompiler/SpirvBackend/src/SpirvModuleEmitter.cpp
docs/dev/ENVIRONMENT.md
docs/dev/debt/libSceAgcDriver.md
docs/dev/debt/shader.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/src/Recorder.cpp
docs/dev/ENVIRONMENT.md
PR 9852 core/shader/recompiler/Recompiler.hpp
core/shader/recompiler/ShaderDiskCache.cpp
docs/dev/ENVIRONMENT.md
PR 9889 core/shader/recompiler/ShaderDiskCache.cpp
docs/dev/debt/shader.md
PR 9898 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/Recorder.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Recorder.cpp
docs/dev/ENVIRONMENT.md
docs/dev/debt/libSceAgcDriver.md
PR 9915 docs/dev/debt/libSceAgcDriver.md
PR 9950 docs/dev/debt/libSceAgcDriver.md
PR 10049 core/shader/recompiler/Recompiler.hpp
core/shader/recompiler/ShaderDiskCache.cpp
docs/dev/debt/libSceAgcDriver.md
PR 10233 docs/dev/debt/libSceAgcDriver.md
docs/dev/debt/shader.md
PR 10249 core/libs/prx/libSceAgcDriver/Graphics/src/Recorder.cpp
PR 10256 docs/dev/debt/libSceAgcDriver.md
PR 10359 core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Recompiler.hpp
docs/dev/debt/libSceAgcDriver.md
PR 10442 core/libs/prx/libSceAgcDriver/Execution/include/VulkanDevice.hpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/Recorder.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Recorder.cpp
docs/dev/ENVIRONMENT.md
PR 10757 core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Recompiler.hpp
docs/dev/ENVIRONMENT.md
PR 10867 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/shader/recompiler/SpirvBackend/src/SpirvEmitter.cpp
core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvEmitterHelpers.cpp
core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvModuleSetup.cpp
docs/dev/debt/shader.md
PR 10894 docs/dev/ENVIRONMENT.md
PR 11435 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/ENVIRONMENT.md
PR 11436 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/ENVIRONMENT.md
PR 11444 core/libs/prx/libSceAgcDriver/Graphics/include/Recorder.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Recorder.cpp
PR 11483 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Recompiler.hpp
core/shader/recompiler/SpirvBackend/include/SpirvBackend/SpirvEmitter.hpp
core/shader/recompiler/SpirvBackend/include/SpirvBackend/SpirvEmitterHelpers.hpp
core/shader/recompiler/SpirvBackend/include/SpirvBackend/SpirvEmitterState.hpp
core/shader/recompiler/SpirvBackend/src/SpirvEmitter.cpp
core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvModuleSetup.cpp
core/shader/recompiler/SpirvBackend/src/SpirvModuleEmitter.cpp
docs/dev/debt/shader.md
PR 11825 docs/dev/debt/libSceAgcDriver.md
PR 11998 docs/dev/debt/libSceAgcDriver.md
PR 12120 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/ENVIRONMENT.md
docs/dev/debt/libSceAgcDriver.md
PR 12323 docs/dev/ENVIRONMENT.md
PR 12324 core/shader/recompiler/CMakeLists.txt
core/shader/recompiler/Recompiler.cpp
docs/dev/ENVIRONMENT.md
PR 12544 docs/dev/ENVIRONMENT.md
PR 12548 core/shader/recompiler/CMakeLists.txt
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/SpirvBackend/src/SpirvFlowEmitter.cpp
docs/dev/debt/shader.md
PR 12565 docs/dev/debt/libSceAgcDriver.md
PR 12619 core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvEmitterHelpers.cpp
PR 12746 docs/dev/ENVIRONMENT.md
PR 12790 core/shader/recompiler/Recompiler.cpp
docs/dev/debt/shader.md
PR 12828 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/shader/recompiler/CMakeLists.txt
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Recompiler.hpp
PR 12863 docs/dev/ENVIRONMENT.md
PR 12921 docs/dev/ENVIRONMENT.md
PR 12930 docs/dev/ENVIRONMENT.md
PR 12970 docs/dev/ENVIRONMENT.md
PR 13148 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 13486 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/Recorder.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Recorder.cpp
core/shader/recompiler/CMakeLists.txt
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/ShaderDiskCache.cpp
core/shader/recompiler/SpirvBackend/src/SpirvModuleEmitter.cpp
docs/dev/ENVIRONMENT.md
docs/dev/debt/libSceAgcDriver.md
docs/dev/debt/shader.md
PR 13599 docs/dev/debt/libSceAgcDriver.md
PR 13707 docs/dev/ENVIRONMENT.md
docs/dev/debt/libSceAgcDriver.md
PR 13994 docs/dev/debt/libSceAgcDriver.md
PR 14032 core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Recompiler.hpp
core/shader/recompiler/ShaderDiskCache.cpp
PR 14212 docs/dev/debt/libSceAgcDriver.md
docs/dev/debt/shader.md
PR 14217 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/tests/GuardedMemoryLoads.cpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Recompiler.hpp
core/shader/recompiler/SpirvBackend/include/SpirvBackend/SpirvEmitter.hpp
core/shader/recompiler/SpirvBackend/include/SpirvBackend/SpirvEmitterState.hpp
core/shader/recompiler/SpirvBackend/src/SpirvEmitter.cpp
docs/dev/debt/shader.md
PR 14218 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Recompiler.hpp
core/shader/recompiler/SpirvBackend/include/SpirvBackend/SpirvEmitter.hpp
core/shader/recompiler/SpirvBackend/include/SpirvBackend/SpirvEmitterState.hpp
core/shader/recompiler/SpirvBackend/src/SpirvEmitter.cpp
core/shader/recompiler/SpirvBackend/src/SpirvFlowEmitter.cpp
docs/dev/debt/shader.md
PR 14262 docs/dev/ENVIRONMENT.md
PR 14299 docs/dev/ENVIRONMENT.md
PR 14344 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/ENVIRONMENT.md
docs/dev/debt/libSceAgcDriver.md
PR 14943 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/Recorder.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Recorder.cpp
docs/dev/ENVIRONMENT.md
docs/dev/debt/libSceAgcDriver.md
PR 14944 core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/Recompiler.hpp
core/shader/recompiler/ShaderDiskCache.cpp
docs/dev/debt/libSceAgcDriver.md
PR 15059 docs/dev/ENVIRONMENT.md
PR 15136 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/Recorder.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Recorder.cpp
docs/dev/ENVIRONMENT.md
docs/dev/debt/libSceAgcDriver.md

@Pipodi
Pipodi force-pushed the perf/flat-private-aperture-1028 branch from 0573779 to 659d07b Compare October 29, 2026 11:28
@Pipodi Pipodi changed the title perf(recompiler): route the FLAT private aperture only in programs that form a private address perf(recompiler): back compute scratch with a device buffer slot pool Oct 29, 2026
@Pipodi
Pipodi marked this pull request as ready for review October 29, 2026 11:28
@github-actions github-actions Bot removed the perf numbers missing perf pull request without a before and after summary line label Oct 29, 2026
@Pipodi
Pipodi force-pushed the perf/flat-private-aperture-1028 branch from 659d07b to 83d6baf Compare October 29, 2026 11:38
@Pipodi

Pipodi commented Oct 29, 2026

Copy link
Copy Markdown
Contributor Author

Reworked as promised, and rebased onto current main. The PR now has one commit, and the description is rewritten. Going through your points:

  • Provenance rule: gone. FLAT routing is exactly main's for every access, including pointers that come from memory, SGPRs or literals. Only the storage behind the private aperture changes: compute scratch now lives in a per-pipeline storage buffer split into workgroup slots instead of dynamically indexed Function arrays. formsPrivateAperture and APS5_FLAT_PRIVATE_ALWAYS are removed.
  • FlatApertures.cpp: untouched now, and it passes. The new agc_driver_scratch_pool test covers private-aperture pointers loaded from a table, taken from a literal and computed, through FLAT store and atomic and through scratch_* in both directions. It also checks isolation between workgroups sharing one or two slots and divergent wave exits. With the slot release changed to ignore the counter, the isolation and divergent-exit checks fail (the description has the output).
  • Cache key: you were right that ShaderCacheVersion.cmake collects quoted APS5_ names on its own. The new APS5_SCRATCH_POOL_MIB is read only by the driver to size the buffer, and the shader takes the slot count from OpArrayLength, so the SPIR-V doesn't depend on it.
  • Callees: GraphBuilder LinkCalls links s_swappc_b64 callees into the caller's graph, so they're translated with the caller and use the same slot. The test has a callee that does the FLAT private access.
  • Numbers: the description now has main and PR summary lines from the same PPSA26344 scene with trace digests, three runs each. The runs differ from each other by more than main differs from the PR, so I see no frame cost. The compile-time numbers are in a block labelled downstream. They come from Celegans12's branch, because main doesn't reach those programs in this title.
  • ENVIRONMENT.md: the row is in alphabetical order.

One thing I can't fully explain is that the buffer needs Coherent. Without it, on my RTX 4090, an unaligned 32-bit FLAT store to scratch (emitted as four byte read-modify-writes) loses one byte per dword, and it does so every time. I ruled out lanes sharing data, spirv-opt and Aliased. The SPIR-V does the loads and stores in order, so it looks like a driver issue, but I haven't read the GPU assembly to prove it. The debt entry says so. If you'd rather have sub-dword scratch stores done with atomics and drop Coherent, I can do that instead.

@oneandonlydean oneandonlydean self-assigned this Oct 29, 2026
@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head 83d6baf merged onto main ba5b533 · tested 2026-10-29 13:48 UTC · 30 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,223 passed · 6 failed (0 new, 5 also fail on main, 1 unstable on main) · 39 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,268 of 2,891 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 (863 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) none
Intermittent validation messages (1, seen once in the parallel run, not reproduced when the test was re-run alone 2 times; not counted against this PR)
agc_driver_depth_clear_hle: VUID-vkCmdCopyBuffer-commonparent (6x)
Unstable on main (1, these also failed in recent main runs on this machine; not counted against this PR)
agc_driver_submit_progress: failed in 3 of the last 5 main runs
Failing on main too (5, not counted against this PR)
agc_compute_pipeline_inspection
agc_submit_progress
agc_submit_progress_no_timeline
guest_mmap_executable
guest_socket_options_multicast
Passed on retry (2, failed in the parallel run, passed when re-run with a 360 s timeout; not counted against this PR)
agc_driver_depth_clear_hle: SEGFAULT in the parallel run; also passed only on retry in 32 other runs in the last 7 days
agc_driver_job_manager_compute_capacity: Failed in the parallel run; also passed only on retry in 34 other runs in the last 7 days
Validated but not compared (1, not in the main baseline's validation pass)
agc_driver_scratch_pool
Validation IDs already present on main (4 IDs in 408 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (408 tests): agc_compute_pipeline_replay, agc_driver, agc_driver_address_passes, agc_driver_address_passes_draw_transitions, agc_driver_address_passes_targets_split, agc_driver_alpha_to_coverage, agc_driver_array_layer_target_cpu, agc_driver_bc_block_copy, and 400 more
VUID-vkCmdCopyImage-srcImage-01548 (11 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_cpu_write_after_memo, agc_driver_depth_plane_cpu_write_after_page_unwatch, agc_driver_depth_plane_cpu_write_after_partial_unwatch, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_partial_store_unimported, agc_driver_depth_storage_dispatch, and 3 more
VUID-vkCmdCopyImage-srcImage-01551 (11 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_cpu_write_after_memo, agc_driver_depth_plane_cpu_write_after_page_unwatch, agc_driver_depth_plane_cpu_write_after_partial_unwatch, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_partial_store_unimported, agc_driver_depth_storage_dispatch, and 3 more
VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 (2 tests): agc_driver_prepared_exports, agc_driver_srgb8_color_target
Skipped (39)
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_msaa_dcc_compared_import_2: skipped, the device reports host imports that keep write protection, so the write-watch probe compares none of them
agc_driver_msaa_dcc_compared_import_4: skipped, the device reports host imports that keep write protection, so the write-watch probe compares none of them
agc_driver_msaa_dcc_compared_import_8: skipped, the device reports host imports that keep write protection, so the write-watch probe compares none of them
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_driver_sparse_dma_buf_import: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_stencil_ref_export: skipped, the device lacks VK_EXT_shader_stencil_export
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_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_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_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_fresh: 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_labels: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SD
Reproduce
git fetch origin 83d6bafdce65aa2ddaf7e0629bdcf38b249a2ed4 ba5b5330b37724bca4b99f30faab504653635a04
git checkout ba5b5330b37724bca4b99f30faab504653635a04 && git merge --no-ff 83d6bafdce65aa2ddaf7e0629bdcf38b249a2ed4
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.

@github-actions github-actions Bot added build shader core/shader docs agc libSceAgc* labels Oct 29, 2026
@oneandonlydean

Copy link
Copy Markdown
Collaborator

@Pipodi thanks for restoring conservative FLAT routing and trying a different optimization. One initialization failure path needs fixing: VulkanDevice.cpp:5356-5359 records vkCmdFillBuffer and immediately sets the cached pool's zeroed flag. Recorder::Submit can subsequently discard that unsubmitted batch (Recorder.cpp:3658-3666, including a vkEndCommandBuffer failure), while scratchPools still owns the pool. A later dispatch then skips its header clear, so scratch acquisition can read uninitialized ownership words and spin. Please make initialization follow successful ordered submission, with rollback/reinitialization after discard; simply clearing on every dispatch could overwrite another in-flight use. Add a fault-injection regression that discards the first initializing batch and retries the same shader/pool, checking initialization is actually executed before acquisition. Please account for separate recorded batches using the same cached pool before the initializing batch submits. This is source-derived; no GPU hang was induced here.

@Pipodi

Pipodi commented Oct 30, 2026

Copy link
Copy Markdown
Contributor Author

@oneandonlydean thanks, you were right: a discarded batch left the cached pool marked zeroed with uninitialized lock words. Fixed in 30930bc, and rebased onto current main (f7f03da):

  • The slot headers are now zeroed once, when the pool is created, in their own batch that is submitted and waited on (Graphics::CommandBatch::SubmitAndWait). The pool is only stored in the cache after that succeeds: if the submit fails it throws first, so the next dispatch creates and clears a new pool.
  • The zeroed flag and the vkCmdFillBuffer inside the dispatch's batch are gone. The pool lookup now runs before the recorder opens the dispatch's commands, so a later discard can't leave a half-initialized pool behind.
  • New test RunDiscardedInitialization in agc_driver_scratch_pool: it makes the first dispatch's submit fail (test hook Recorder::FailNextSubmitsForTest), then dispatches again on the cached pool. Before the fix it fails with "header word 0 reads 0xffffffff"; after it, it passes.
  • The blocking submit at pool creation has a debt entry ("Compute scratch pool header clear" in docs/dev/debt/libSceAgcDriver.md).

After the rebase: full ctest 3107/3107, and the FLAT aperture, scratch pool, LDS and guarded memory load tests with VK_LAYER_KHRONOS_validation pass 43/43 with no VUID-. The rebase only conflicted where main's meshWindowBuffer field (#12233) sits next to scratchPoolSlotDwords. I kept both, in the same order in the shader disk cache writer and reader.

@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 30, 2026
@bunbeans2-arch

Copy link
Copy Markdown
Contributor

An AMD RDNA 4 run on Windows of 30930bc172: the new agc_driver_scratch_pool fails here 3 of 3. The cause looks like the test's injected submit failure, not the scratch pool.

Windows 11 Pro 10.0.22631, AMD Radeon RX 9070 XT (1002:7550, driver 32.0.32015.7029, amdvlk64), MSYS2 UCRT64 g++ 16.1.0, Release, this head merged onto main f7f03daf52. ANYPS5_REQUIRE_VULKAN=1, ANYPS5_NO_SHADER_CACHE=1, VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation; with VK_LOADER_DEBUG=layer the loader logs Insert instance layer "VK_LAYER_KHRONOS_validation" in every run of every test below that creates a Vulkan instance.

  • agc_driver_scratch_pool fails 3 of 3. Each run ends with AGC graphics: vkBeginCommandBuffer recorder: Vulkan result -13, after VUID-vkBeginCommandBuffer-commandBuffer-00049: Cannot be called for VkCommandBuffer ... while it is still in the recording state.
  • With VK_INSTANCE_LAYERS unset, it still fails 3 of 3 with the same -13, so the driver itself refuses the begin.
  • agc_guarded_memory_loads, agc_driver_recorder and the agc_recorder_* tests pass 3 of 3, as on main.

What I think happens, from the code: in Recorder.cpp, the FailNextSubmitsForTest throw (line 3671) comes before vkEndCommandBuffer (line 3672). So DiscardUnsubmitted hands discard() a batch whose command buffer is still recording, release() keeps it in spare (line 4330), and the next batch that takes it from spare calls vkBeginCommandBuffer on a recording buffer. Implicit reset doesn't cover that state.

To check, I swapped lines 3671 and 3672 locally (the throw now comes after vkEndCommandBuffer, nothing else changed). Then agc_driver_scratch_pool passes 3 of 3 with the layer on, and no VUID- line. Moving the injection after the end is the fix I ran. Freeing a still-recording buffer in release() instead of keeping it would be the other way, but I haven't tried it.

AI-assisted: yes (Claude Code)

@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head 30930bc merged onto main 98ddd9c · tested 2026-10-30 14:27 UTC · 31 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,299 passed · 3 failed (0 new, 2 also fail on main, 1 unstable on main) · 41 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,343 of 2,987 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 (870 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_bda_device 38.8 s
Unstable on main (1, these also failed in recent main runs on this machine; not counted against this PR)
agc_driver_submit_progress: failed in 5 of the last 8 main runs
Failing on main too (2, not counted against this PR)
guest_mmap_executable
guest_socket_options_multicast
Validated but not compared (1, not in the main baseline's validation pass)
agc_driver_scratch_pool
Validation IDs already present on main (4 IDs in 392 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (392 tests): agc_compute_pipeline_replay, agc_driver, agc_driver_address_passes_draw_transitions, agc_driver_address_passes_targets_split, agc_driver_array_layer_target_cpu, agc_driver_bda_span_reads_draw_pipeline, agc_driver_bindless_images, agc_driver_branch_past_endpgm, and 384 more
VUID-vkCmdCopyImage-srcImage-01548 (13 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_cpu_write_after_memo, agc_driver_depth_plane_cpu_write_after_page_unwatch, agc_driver_depth_plane_cpu_write_after_partial_unwatch, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_partial_store_unimported, agc_driver_depth_plane_sampling, and 5 more
VUID-vkCmdCopyImage-srcImage-01551 (13 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_cpu_write_after_memo, agc_driver_depth_plane_cpu_write_after_page_unwatch, agc_driver_depth_plane_cpu_write_after_partial_unwatch, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_partial_store_unimported, agc_driver_depth_plane_sampling, and 5 more
VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 (2 tests): agc_driver_prepared_exports, agc_driver_srgb8_color_target
Skipped (41)
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_msaa_dcc_compared_import_2: skipped, the device reports host imports that keep write protection, so the write-watch probe compares none of them
agc_driver_msaa_dcc_compared_import_4: skipped, the device reports host imports that keep write protection, so the write-watch probe compares none of them
agc_driver_msaa_dcc_compared_import_8: skipped, the device reports host imports that keep write protection, so the write-watch probe compares none of them
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_driver_sparse_dma_buf_import: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_stencil_ref_export: skipped, the device lacks VK_EXT_shader_stencil_export
agc_driver_vertex_elected_atomic_max: skipped, the device runs vertex programs in subgroups, so they keep their cross-lane reductions
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_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_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_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_fresh: 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 plat
Reproduce
git fetch origin 30930bc17202ac553cf8741bafebc370a63b2a9e 98ddd9c1792bbab016ceed5db267a93d1d61f00a
git checkout 98ddd9c1792bbab016ceed5db267a93d1d61f00a && git merge --no-ff 30930bc17202ac553cf8741bafebc370a63b2a9e
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.

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Nov 1, 2026
@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ AMD GPU test: passed

PR head ee700f7 merged onto main f2d874c · tested 2026-11-01 20:52 UTC · 43 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,448 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,516 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 (943 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 120.6 s, ⚠️ agc_driver_graphics 88.8 s, ⚠️ agc_driver_graphics_maps_fallback 88.4 s, ⚠️ public_headers 58.7 s, ⚠️ unwrap_self 42.7 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 ee700f7235643d57a95383f3924f0c5562c7b23f f2d874c1fdccf781c0fa5d86619bb5dd8894b958
git checkout f2d874c1fdccf781c0fa5d86619bb5dd8894b958 && git merge --no-ff ee700f7235643d57a95383f3924f0c5562c7b23f
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.

@bunbeans2-arch

Copy link
Copy Markdown
Contributor

@Pipodi confirmed on the AMD card where it failed: agc_driver_scratch_pool now passes 3 of 3 on ee700f7235 ✅

Same setup as my first run: Windows 11 Pro 10.0.22631, AMD Radeon RX 9070 XT (1002:7550, driver 32.0.32015.7029, amdvlk64), MSYS2 UCRT64 g++ 16.1.0, Release, this head as is (on main f2d874c1fd). ANYPS5_REQUIRE_VULKAN=1, ANYPS5_NO_SHADER_CACHE=1, VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation; with VK_LOADER_DEBUG=layer the loader logs Insert instance layer "VK_LAYER_KHRONOS_validation" in all 3 runs.

  • 3 of 3 pass, no VUID- line. On the old head every run ended with VUID-vkBeginCommandBuffer-commandBuffer-00049 and Vulkan result -13; neither appears now.

This adds the Windows amdvlk side to the RADV run above. Thanks for the quick swap 🙂

AI-assisted: yes (Claude Code)

@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head ee700f7 merged onto main f2d874c · tested 2026-11-01 21:10 UTC · 24 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,462 passed · 8 failed (0 new, 4 also fail on main, 4 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,516 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 (943 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 120.1 s, ⚠️ agc_driver_lookup_log_fits_build 70.7 s, ⚠️ agc_driver_graphics_maps_fallback 31.9 s, ⚠️ agc_driver_graphics 30.8 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 1 of the last 10 main runs
agc_driver_pipeline_journal: failed in 1 of the last 10 main runs
agc_submit_progress: failed in 5 of the last 10 main runs
agc_submit_progress_no_timeline: failed in 7 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 ee700f7235643d57a95383f3924f0c5562c7b23f f2d874c1fdccf781c0fa5d86619bb5dd8894b958
git checkout f2d874c1fdccf781c0fa5d86619bb5dd8894b958 && git merge --no-ff ee700f7235643d57a95383f3924f0c5562c7b23f
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.

Pipodi and others added 6 commits November 2, 2026 04:35
NVIDIA's front end spends tens of seconds per large compute program on the
dynamically indexed Function arrays that held the per-lane scratch. A compute
program that uses scratch (scratch_* or a FLAT access that the aperture split
routes to the private aperture) now keeps it in a storage buffer instead, so
no Function array is declared or indexed. FLAT routing is unchanged.

The driver allocates one buffer per compute pipeline on its first dispatch,
capped by APS5_SCRATCH_POOL_MIB (default 64), holding a lock word and an
invocation counter per slot followed by the slots, and binds it in descriptor
set 2 (the layout of the device-memory LDS buffer). The shader takes the slot
count from the array length. Invocation 0 of each workgroup claims a slot with
a compare-exchange scan that starts at its linear workgroup id and spins until
it wins one; a barrier publishes the slot. Every invocation decrements the
slot's counter on every compute exit and the last one frees the lock, so
divergent exits and concurrent dispatches of one pipeline share the buffer
safely. The emitter fails the compile if a compute return lacks the release.
Programs without scratch keep their SPIR-V and pipeline layout.

The buffer is decorated Coherent: without it NVIDIA lost earlier byte stores
of a sequence of byte read-modify-writes to one dword. Lane-private
read-modify-writes no longer use atomics.

Tests: a new execution test covers the private aperture reached through a
table load, a literal and a computed address (store, atomic, and both ways
through scratch_*), a callee reached through s_swappc_b64, isolation of 64
workgroups over one or two slots, divergent wave exits with a second dispatch
reusing the slots, and the module shape (no Function array, no binding in a
program without scratch). The guarded memory load fixture skips the slot
acquisition.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The slot-lock header of a compute scratch pool was cleared by a fill recorded
into the first dispatch batch that used the pool, and a flag set at record time
said it was done. A batch that Recorder::Submit discarded unsubmitted (for
example a vkEndCommandBuffer failure) left the pool cached with the flag set,
so later dispatches skipped the clear and slot acquisition read uninitialized
ownership words and could spin; a second dispatch recorded against the same
pool before the first batch submitted trusted the same flag.

The header is now zeroed by a one-off command batch that is submitted and
waited on when the pool is created, before the dispatch's own batch opens, so
discards and recording order no longer matter. The zeroed flag and the
in-batch fill are gone. A new test discards the first batch that uses a pool
(two dispatches against it) on top of dirtied pool memory and checks that the
header reads zero and the retried dispatch completes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each compute program that uses scratch kept its own pool of up to APS5_SCRATCH_POOL_MIB (64 MiB) until device teardown, so the pools of many such programs added up without bound.

All pools together are now held under APS5_SCRATCH_POOL_TOTAL_MIB (default 256 MiB). A new or enlarged pool first drops the least recently used pools until it fits; the newest pool is always kept. A dropped pool stays alive until the batches that recorded it complete, since the recorder keeps a reference, and the program gets a new pool with a zeroed header when it dispatches again.

The test dispatches two scratch programs over a 1 MiB budget and checks that the second evicts the first, and that the first then runs correctly in a recreated pool.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On an RTX 4090 (driver 617.42) a scratch pool buffer of 2049 MiB returned wrong scratch values in the scratch dispatch bench, while 2047 MiB was correct, though maxStorageBufferRange is larger. One pool is now held under 2 GiB, under APS5_SCRATCH_POOL_MIB and under APS5_SCRATCH_POOL_TOTAL_MIB, so a large APS5_SCRATCH_POOL_MIB no longer creates a pool over the total budget or over 2 GiB.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A workgroup looking for a scratch pool slot now loads the lock and tries the compare-exchange only when it reads free, so waiting workgroups stop issuing atomics on locks their holders use. In the scratch dispatch bench on an RTX 4090 with about 9 slots for 32768 workgroups (APS5_SCRATCH_POOL_MIB=1) the dispatch goes from 1377 ms to 1308 ms; with the default 64 MiB pool it is unchanged (389 to 395 ms). The debt notes the measured runtime cost of the pool against Function arrays.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Pipodi
Pipodi force-pushed the perf/flat-private-aperture-1028 branch from ee700f7 to 28a30ed Compare November 2, 2026 03:47
@Pipodi

Pipodi commented Nov 2, 2026

Copy link
Copy Markdown
Contributor Author

Thanks, all four were fair. I measured each one; two of them changed the PR.

1. Runtime of a scratch-heavy program. New bench ScratchBench (local, not in the PR): one compute program with 448 scratch dwords per lane, dynamic and static indexing, median of repeated dispatches. RTX 4090, driver 617.42.

groups main (Function arrays) PR, 64 MiB pool PR, Coherent dropped PR, 1 MiB pool (~9 slots)
256 1.56 ms 3.8 ms 3.6 ms 10.6 ms
4096 22.1 ms 49 ms 48 ms 172 ms
32768 183 ms 389 ms 379 ms 1377 ms

So the PR costs about 2.4× at run time on a scratch-heavy kernel. Coherent is not the cost (dropping it changes 2-3 %). The cost comes from moving scratch from Function memory to a storage buffer. This is now a debt entry ("Compute scratch runtime cost") with these numbers. The trade is compile time (141-145 s to about 100 s on 0x1994ed) against dispatch time of programs that use scratch.

2. Which pool programs dispatch in the window. I added a log line at pool creation and ran warm pairs with APS5_PROFILE_GPU=1. On Ghost of Yōtei no pool was created up to frame 517 on main and frame 530 on the PR (1500 s each), so no scratch program dispatches in frames 250-280 or for a long time after. GPU time in the window is 2.08 s on main and 2.20 s on the PR (noise; the whole run is 50.9 s against 52.5 s). The 13 programs in the body were compiled with a pool binding (26 shader cache entries), not dispatched. You were right that the trace pair could not show a runtime change. In this title the change is compile-time only up to frame 530; I have no scene yet where the scratch programs run every frame.

3. Pool memory. Fixed:

  • APS5_SCRATCH_POOL_TOTAL_MIB (default 256) bounds all pools together, with LRU eviction of the least recently used pool. A pool is also capped by that total, so the default bound is 256 MiB, not 13 × 64.
  • While testing large caps I found a pool above 2 GiB returns wrong values on the 4090 (2049 MiB fails, 2047 MiB is fine), so one pool is now held under 2 GiB as well as maxStorageBufferRange. A cap of 4096 MiB now gives 3.7 / 54 / 425 ms in the bench above.

4. Slot claim spin. With slots below resident groups the waiting groups serialize. At 1 MiB (~9 slots) a 4096-group dispatch takes 172 ms against 49 ms at 64 MiB (~580 slots), so the cost is the slot count, not the atomics. I changed the claim to read the lock word first and try the CompareExchange only when it reads free. That gives about 5 % at 9 slots (1377 to 1308 ms) and nothing at 580 slots (389 to 395 ms). A back-off would not help much while the cost is the waiting itself, so I left the default cap at 64 MiB and listed the spin in the debt entry with these numbers.

Commits added, after a rebase onto main be24202: cc61c3ae31 (total budget with LRU), ce38162aa1 (pool under 2 GiB and inside the total), 28a30ed35d (read the lock before the exchange). Full ctest 3283/3283; focused run with the validation layer 64/64 on the PR and 63/63 on main, no VUID-. The body has the bench table and the game finding.

Given point 1 and 2, I understand if you prefer this off by default or not merged until a title needs the compile-time saving: it saves about 40 s of compile per giant program and costs ~2.4× dispatch time on scratch programs, which this title does not dispatch before frame 530.

@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Nov 2, 2026
# Conflicts:
#	core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
#	docs/dev/debt/libSceAgcDriver.md
#	docs/dev/debt/shader.md
@github-actions github-actions Bot added needs rebase Conflicts with main, rebase needed and removed needs rebase Conflicts with main, rebase needed labels Nov 2, 2026
@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head 28a30ed merged onto main 2517aa0 · tested 2026-11-02 09:31 UTC · 35 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,463 passed · 6 failed (0 new, 3 also fail on main, 3 unstable on main) · 45 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,514 of 3,174 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 119.9 s, ⚠️ agc_driver_lookup_log_fits_build 44.8 s, ⚠️ agc_driver_graphics_maps_fallback 31.0 s
Unstable on main (3, 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_submit_progress: failed in 8 of the last 10 main runs
agc_submit_progress_no_timeline: failed in 8 of the last 10 main runs
Failing on main too (3, not counted against this PR)
agc_driver_image_table
guest_mmap_executable
guest_socket_options_multicast
Validation IDs already present on main (5 IDs in 483 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (483 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 475 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 (45)
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_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 or not available in current SDL video driver (offscreen) or platform
video_o
Reproduce
git fetch origin 28a30ed35d45b0b989460ddb91b69e2846b6e8a7 2517aa02f78e00b8b06ae5ff4206a8c04e22a1cb
git checkout 2517aa02f78e00b8b06ae5ff4206a8c04e22a1cb && git merge --no-ff 28a30ed35d45b0b989460ddb91b69e2846b6e8a7
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.

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Nov 2, 2026
SpirvEmitter.cpp: main now calls Finalize() before filling info and checks
spanned-wave barriers on the words; keep that and run this branch's
VerifyScratchPoolReturns(state, words) on the same words before returning.
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Nov 2, 2026
@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head e9d8998 merged onto main 1d91f29 · tested 2026-11-02 18: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,637 passed · 7 failed (0 new, 3 also fail on main, 4 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,688 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 (990 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 120.2 s, ⚠️ agc_driver_graphics_maps_fallback 49.7 s, ⚠️ agc_driver_graphics 41.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 1 of the last 10 main runs
agc_driver_pipeline_journal: failed in 3 of the last 10 main runs
agc_submit_progress: failed in 8 of the last 10 main runs
agc_submit_progress_no_timeline: failed in 7 of the last 10 main runs
Failing on main too (3, not counted against this PR)
agc_driver_image_table
guest_mmap_executable
guest_socket_options_multicast
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 e9d8998d5861fd37171ca4ee91063051b28f8e32 1d91f2966d0eef82a021628a7aa8e78e615ac807
git checkout 1d91f2966d0eef82a021628a7aa8e78e615ac807 && git merge --no-ff e9d8998d5861fd37171ca4ee91063051b28f8e32
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.

@oneandonlydean
oneandonlydean merged commit 1f27253 into boykopovar:main Nov 2, 2026
14 checks passed
Raghav314 added a commit to Raghav314/AnyPS5 that referenced this pull request Nov 3, 2026
The compute scratch pool from boykopovar#12764 sizes itself with OpArrayLength on a
storage buffer at descriptor set 2. A GPU-mode stage maps its buffers onto
VK_EXT_descriptor_heap through pushed addresses, which cannot carry an
array length (VUID-VkPipelineShaderStageCreateInfo-pNext-11378), so every
GPU-mode compute stage with scratch was refused by the heap and recompiled
in CPU mode. GPU-mode compute stages keep scratch in function storage, as
they did before the merge; the scratch pool test also runs in heap mode.
Raghav314 added a commit to Raghav314/AnyPS5 that referenced this pull request Nov 3, 2026
GPU-mode compute stages now use the boykopovar#12764 scratch pool instead of
function-storage scratch. The pool binds at descriptor set 5 through a
pushed address after the workgroup memory address, and because a pushed
address carries no array length, the stage reads its pool size in dwords
from push data instead of OpArrayLength. The scratch pool test runs every
case in heap mode and requires the descriptor heap pipeline.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agc libSceAgc* build docs perf Performance change shader core/shader

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants