Repository navigation
Description
Title and scene
ASTRO BOT, PPSA21567 (EU) 01.018.000, Linux. Continuing a save from the title screen: the warp transition after pressing Continue (swirling PlayStation shape icons, the controller ship with the bots flying into the centre while the music fades out), then the galaxy map coming into view (zoom-out with the locations appearing).
What is slow or what changed
Everything up to the point where the warp ships reach the centre runs normally. From the moment the galaxy map starts loading, the title drops below 1 fps and stays there:
- the screen is black while the music fades out extremely slowly, so the game loop itself is throttled, not only presentation;
- the galaxy map's normal zoom-out reveal then crawls at 0.3-1 fps.
On the same machine:
| Build | Title screen | Galaxy map |
|---|---|---|
main 329efe1 (22 Oct) |
about 12 fps | about 8-11 fps |
main 9bbb7f3 (26 Oct) |
fast until Continue, then 0.3-3 fps | 0.8-2 fps (avg 2.1, mostly below 1 while it comes into view) |
oneandonlydean's frozen astrobot reference build 222bccd, for scale |
18.9 fps | 11.9-13.9 fps, a short dip while the map loads |
Measured after a clean reboot with nothing else running (432 MiB VRAM in use before launch, 27 GB RAM free), warm shader cache (2,088 hits, 0 misses).
What I checked:
- Not compilation: the shader disk cache reports 0 misses during the slow phase.
- Not VRAM: the peak was 6.3 GB of 8 GB.
- Host import budget: with the default budget the log reports
host import budget: 11925 MiB live of 11972 MiB (the default; host heap 1 reports a budget of 23944 MiB ...); 11 imports (35552 MiB) refused so far, last 0x1000000000+0xca000000. WithAPS5_HOST_IMPORT_MIB=16384there are no refusals, but it is just as slow. - One thread runs at about 99 % for the whole slow phase. A
perf record -e cpu-clocksample (call stacks were not available on this kernel) puts about 60 % of the process's samples in glibc'smemcpy(__memcpy_avx_unaligned_erms), almost all of them on that thread. Page faults stay low (about 70 minor faults in 3 s), so it does not look like a write-watch fault storm. - At startup:
[write-watch] host imports resolve write protection: no (0 of 4 scratch pages written after a GPU read, 0 after a GPU write, 4 after the import); imported ranges stay watched. This NVIDIA proprietary path may be the one that changed, since most of the measurements in perf(agc): the queue-0 draw committer bounds draw-heavy titles on the CPU — is parallel draw recording planned? #7895 and [Astro Bot / PPSA21567] Strict Linker Unresolved Imports inlibSceNpCppWebApiand Hard AGCwrite watchAbort Panic #8052 come from AMD cards.
Local changes in my build: an opt-in texture mip-skip (off for this comparison, APS5_TEXTURE_DOWNSCALE=0, same result) and a fallback to transparent black for border colour table samplers (#665). Neither touches the memory paths above. The slowdown also reproduces with both runtime switches at their defaults.
Summary lines
Capture with APS5_TRACE_SUMMARY_EVERY=30 APS5_TRACE_BENCH=1 on 9bbb7f3 (warm caches), fps per 30 s interval:
| Seconds after first present | fps | What is on screen |
|---|---|---|
| 0-60 | 23-31 | logos, title |
| 60-150 | 6-11 | title, Continue pressed |
| 150-368 | 0.35-0.44 | end of the warp, black screen, music fading out |
| 368-398 | 3.5 | galaxy map appears |
| 398-551 | 0.8-1.0 | galaxy map |
The line for the 213-243 s interval (black screen, music fading):
{"commit":"9bbb7f37c655","dirty":true,"env":{"APS5_LEVEL_MENU":"1","APS5_NO_SNAPSHOT_CHECK":"1","APS5_TEXTURE_DOWNSCALE":"1","APS5_TRACE_BENCH":"1","APS5_TRACE_SUMMARY_EVERY":"30"},"gpu":"NVIDIA GeForce RTX 2080","driver":"NVIDIA 615.78.08","os":"Linux 7.3.0-2-wyrmix","cpu":"Intel(R) Core(TM) i7-8700K CPU @ 3.70GHz","cpu_threads":12,"memory_mib":31926,"title_id":"PPSA21567","title":"ASTRO BOT","content_version":"01.018.000","resolution":"3840x2160","window":{"spec":"summary_every 30","first_present":2466,"ms":30149.564},"interval_start_s":213.006,"interval_end_s":243.156,"presents":11,"frame_ms":{"p50":2742.957,"p90":2830.330,"p99":2970.930,"max":2970.930},"gpu_busy_ms_per_present":1248.522,"worker_busy_pct":{"queue worker 0x0":99.973,"queue worker 0x40":99.663,"queue worker 0x48":99.667,"queue worker 0x3a":0.000},"top_phases_ms_per_frame":{"Driver.Packet":8202.644,"Driver.Packet.memory_wait":5449.958,"Resources.Complete":1979.435,"Driver.Packet.draw":1954.795,"Driver.Draw":1954.522,"Driver.Draw.draw_enqueued":1929.425,"Graphics.Draw":1882.845,"Graphics.Draw.draw_and_resource_release":1878.780},"trace_dropped":false,"trace":""}dirty is the two local changes described above; APS5_TEXTURE_DOWNSCALE=1 was set in this capture.
What stands out in that line: a frame takes about 2.7 s (p50 2743 ms), and of the 8.2 s per frame in Driver.Packet, 5.4 s is Driver.Packet.memory_wait. The trace below shows how that splits up: queue worker 0x0 is busy 98 % in Driver.Packet, the draw committer 70 % (mostly Graphics.Draw and Resources.Complete, about 1.5-1.6 s per frame each), while queue workers 0x40 and 0x48 spend 96 % of each frame in Driver.Packet.memory_wait (about 2.4 s per frame). The GPU is busy 42 % of the time (939 ms per present).
Traces
aps5-trace-9bbb7f37c655-16277.json.gz, attached in a comment below: APS5_TRACE_SECONDS=180:60, Continue pressed as soon as the title allowed it, so the window covers the end of the warp and the black screen while the music fades out. Tracing adds its own overhead.
Digest
seconds 180:60 from present 2155: 27 presents, frame p50 2278.4 / p90 2535.4 / p99 2554.0 / max 2554.0 ms, GPU busy 939.1 ms per present
NVIDIA GeForce RTX 2080, NVIDIA 615.78.08, Linux 7.3.0-2-wyrmix, 3840x2160, commit 9bbb7f3 (dirty), dropped: no
{"commit":"9bbb7f37c655","dirty":true,"env":{"APS5_LEVEL_MENU":"1","APS5_NO_SNAPSHOT_CHECK":"1","APS5_TEXTURE_DOWNSCALE":"1","APS5_TRACE_SECONDS":"180:60"},"gpu":"NVIDIA GeForce RTX 2080","driver":"NVIDIA 615.78.08","os":"Linux 7.3.0-2-wyrmix","cpu":"Intel(R) Core(TM) i7-8700K CPU @ 3.70GHz","cpu_threads":12,"memory_mib":31926,"title_id":"PPSA21567","title":"ASTRO BOT","content_version":"01.018.000","resolution":"3840x2160","window":{"spec":"seconds 180:60","first_present":2155,"ms":61279.833},"presents":27,"frame_ms":{"p50":2278.409,"p90":2535.389,"p99":2554.048,"max":2554.048},"gpu_busy_ms_per_present":939.089,"worker_busy_pct":{"queue worker 0x0":99.966,"queue worker 0x40":96.245,"queue worker 0x48":96.015,"queue worker 0x3a":0.0},"top_phases_ms_per_frame":{"Driver.Packet":6631.596,"Driver.Packet.memory_wait":4350.519,"Resources.Complete":1641.98,"Driver.Packet.draw":1565.562,"Driver.Draw":1565.304,"Graphics.Draw":1542.999,"Driver.Draw.draw_enqueued":1541.487,"Graphics.Draw.draw_and_resource_release":1539.314},"trace_dropped":false,"trace":"aps5-trace-9bbb7f37c655-16277.json.gz"}Slowest frames (largest slices inside each, inclusive)
- present 2179: 2554.0 ms at 53732 ms: Driver.Packet (queue worker 0x48) 2553.9, Driver.Packet (queue worker 0x40) 2553.5, Driver.Packet (queue worker 0x0) 2548.0, Driver.Packet.memory_wait (queue worker 0x48) 2546.2
- present 2180: 2540.4 ms at 56286 ms: Driver.Packet (queue worker 0x40) 2539.9, Driver.Packet (queue worker 0x48) 2539.5, Driver.Packet (queue worker 0x0) 2535.0, Driver.Packet.memory_wait (queue worker 0x48) 2532.8
- present 2175: 2535.4 ms at 43933 ms: Driver.Packet (queue worker 0x40) 2534.8, Driver.Packet (queue worker 0x48) 2534.5, Driver.Packet (queue worker 0x0) 2529.7, Driver.Packet.memory_wait (queue worker 0x48) 2527.7
- present 2171: 2460.3 ms at 34456 ms: Driver.Packet (queue worker 0x40) 2459.5, Driver.Packet (queue worker 0x48) 2459.4, Driver.Packet (queue worker 0x0) 2454.5, Driver.Packet.memory_wait (queue worker 0x48) 2453.6
- present 2181: 2453.3 ms at 58827 ms: Driver.Packet (queue worker 0x0) 2447.8, Driver.Packet.draw (queue worker 0x0) 1759.9, Driver.Draw (queue worker 0x0) 1759.6, Driver.Draw.draw_enqueued (queue worker 0x0) 1733.2
Threads (ms per frame)
| thread | busy | wait | untraced | in slices < 20 us | largest |
|---|---|---|---|---|---|
| queue worker 0x0 | 2217.7 (98 %) | 46.6 (2 %) | 5.3 | 28.9 | Driver.Packet 2264.1, Driver.Completion 0.1 |
| title | 0.1 (0 %) | 0.0 (0 %) | 2269.5 | 0.1 | Shader.ResolveGraphicsStagesAbi 0.1, Shader.ResolveAbi 0.0 |
| title | 0.1 (0 %) | 0.0 (0 %) | 2269.5 | 0.1 | Shader.ResolveGraphicsStagesAbi 0.1, Shader.ResolveGraphicsAbi 0.0 |
| title | 0.1 (0 %) | 0.0 (0 %) | 2269.6 | 0.1 | Shader.ResolveAbi 0.0, Shader.ResolveGraphicsStagesAbi 0.0 |
| title | 0.0 (0 %) | 0.0 (0 %) | 2269.6 | 0.5 | Shader.ResolveGraphicsStagesAbi 0.0, Shader.ResolveAbi 0.0 |
| queue worker 0x40 | 11.3 (0 %) | 2172.8 (96 %) | 85.5 | 2.1 | Driver.Packet 2183.9, Recorder.Submit 0.1 |
| draw committer | 1591.7 (70 %) | 11.9 (1 %) | 666.1 | 3.5 | Graphics.Draw 1542.7, Recorder.Submit 46.9 |
| queue worker 0x48 | 3.5 (0 %) | 2175.6 (96 %) | 90.5 | 0.2 | Driver.Packet 2178.6, Driver.EndSubmission 0.5 |
| presenter | 3.0 (0 %) | 0.0 (0 %) | 2266.6 | 0.1 | VideoOut.Flip 2.9, Driver.Present 0.1 |
| title | 0.1 (0 %) | 0.0 (0 %) | 2269.6 | 0.0 | Shader.ResolveGraphicsStagesAbi 0.1 |
| gpu | 947.8 (42 %) | 0.0 (0 %) | 1321.8 | 0.0 | batch 947.8 |
Largest slices (ms per frame, inclusive, all threads): Driver.Packet 6626.6, Driver.Packet.memory_wait 4350.5, Resources.Complete 1641.9, Driver.Packet.draw 1565.1, Driver.Draw 1564.8, Graphics.Draw 1542.8, Driver.Draw.draw_enqueued 1540.1, Graphics.Draw.draw_and_resource_release 1539.1, batch 947.8, Driver.Packet.dispatch 206.4
Longest waits
- Driver.Packet.memory_wait (queue worker 0x48) 2546.2 ms at 53741 ms, present 2179
- Driver.Packet.memory_wait (queue worker 0x48) 2537.7 ms at 56295 ms, present 2180
- Driver.Packet.memory_wait (queue worker 0x48) 2527.8 ms at 43942 ms, present 2175
- Driver.Packet.memory_wait (queue worker 0x48) 2453.9 ms at 34464 ms, present 2171
- Driver.Packet.memory_wait (queue worker 0x48) 2442.2 ms at 51291 ms, present 2178
- Driver.Packet.memory_wait (queue worker 0x48) 2440.8 ms at 48844 ms, present 2177
- Driver.Packet.memory_wait (queue worker 0x40) 2397.6 ms at 53910 ms, present 2179
- Driver.Packet.memory_wait (queue worker 0x48) 2395.1 ms at 39230 ms, present 2173
- Driver.Packet.memory_wait (queue worker 0x40) 2390.1 ms at 56460 ms, present 2180
- Driver.Packet.memory_wait (queue worker 0x40) 2380.4 ms at 44107 ms, present 2175
Largest GPU batches (GPU ranges inside, and the CPU slices that recorded each, inclusive)
- batch 1373: 47.6 ms at 27621 ms, present 2167: GPU no ranges; recorded by Graphics.Draw (draw committer) 86.7, Graphics.Draw.draw_and_resource_release (draw committer) 86.4, Resources.Complete (draw committer) 83.5, Resources.Prepare (draw committer) 0.1
- batch 1917: 47.4 ms at 39051 ms, present 2172: GPU no ranges; recorded by Graphics.Draw (draw committer) 84.7, Graphics.Draw.draw_and_resource_release (draw committer) 84.4, Resources.Complete (draw committer) 81.4, Resources.Prepare (draw committer) 0.1
- batch 618: 47.4 ms at 11822 ms, present 2160: GPU no ranges; recorded by Graphics.Draw (draw committer) 85.9, Graphics.Draw.draw_and_resource_release (draw committer) 85.6, Resources.Complete (draw committer) 82.7, Resources.Prepare (draw committer) 0.1
- batch 1265: 47.1 ms at 25257 ms, present 2166: GPU no ranges; recorded by Graphics.Draw (draw committer) 78.9, Graphics.Draw.draw_and_resource_release (draw committer) 78.6, Resources.Complete (draw committer) 75.6, Resources.Prepare (draw committer) 0.1
- batch 1477: 47.0 ms at 29793 ms, present 2168: GPU no ranges; recorded by Graphics.Draw (draw committer) 87.5, Graphics.Draw.draw_and_resource_release (draw committer) 87.2, Resources.Complete (draw committer) 84.3, Resources.Prepare (draw committer) 0.1
Machine
- CPU: Intel Core i7-8700K (6 cores, 12 threads)
- GPU: NVIDIA GeForce RTX 2080, 8 GB, driver 615.78.08 (nvidia-open-dkms)
- RAM: 32 GB
- OS: Garuda Linux (Arch), kernel 7.3.0, KDE Plasma 6 on Wayland; the game window runs through XWayland (
SDL_VIDEODRIVER=x11, native Wayland stayed black on this setup) - Relinked with
--to-intel
Capture
- The caches were warm (the scene ran once and the title was restarted)
- No other APS5_TRACE_* or APS5_PROFILE_* switch was set and the log was not redirected - no other switch was set, but my launcher redirects stdout/stderr to a file
- Captures compared here come from the same machine, scene and settings
Activity
senjinthedragon commentedon Oct 26, 2026
aps5-trace-9bbb7f37c655-16277.json.gz
MarcZX10 commentedon Oct 26, 2026
I ran
tools/trace_digest.pyon the attached trace. The matching 60 s capture has 27 presents, frame p50 2,278 ms and GPU busy 939 ms/present (about 42%). Queue worker 0 is 99.97% busy;Driver.Packet.memory_waitaccounts for 4,351 ms/frame across threads andResources.Completefor 1,642 ms/frame. That points to CPU-side packet/resource work rather than shader compilation or a saturated GPU.One useful comparison target is open PR #9012, which gates repeated full
ShaderResourcesaudits on host-import-set changes; its author measured about 7,700 full walks per 10 s on an Astro Bot scene. That is an adjacent path, not an established cause for this report (the trace'sResources.Completecost is much larger).The attached capture is marked
dirtyand hasAPS5_NO_SNAPSHOT_CHECK=1(which skips the live snapshot comparison). Since the description says the issue also reproduces with defaults, a clean-tree/default-switch trace would make that reproduction easier to compare before attributing the regression tomain.senjinthedragon commentedon Oct 26, 2026
Thanks for running the digest. You are right about the switches: my launcher had
APS5_NO_SNAPSHOT_CHECK=1set in every run, so "reproduces with defaults" in the report was only true for my own two switches. Sorry for that.Here is a capture from a clean tree, nothing set except the trace window: unmodified
main9bbb7f3 (no local changes,dirty: false), noAPS5_*switch apart fromAPS5_TRACE_SECONDS=180:60, log printed to the terminal (not redirected), same scene and procedure as before (Continue pressed as soon as the title allowed it, warm caches). It reproduces the same way and the numbers are practically identical to the dirty capture:{"commit":"9bbb7f37c655","dirty":false,"env":{"APS5_TRACE_SECONDS":"180:60"},"gpu":"NVIDIA GeForce RTX 2080","driver":"NVIDIA 615.78.08","os":"Linux 7.3.0-2-wyrmix","cpu":"Intel(R) Core(TM) i7-8700K CPU @ 3.70GHz","cpu_threads":12,"memory_mib":31926,"title_id":"PPSA21567","title":"ASTRO BOT","content_version":"01.018.000","resolution":"3840x2160","window":{"spec":"seconds 180:60","first_present":2318,"ms":60605.474},"presents":27,"frame_ms":{"p50":2243.735,"p90":2558.932,"p99":2614.281,"max":2614.281},"gpu_busy_ms_per_present":939.890,"worker_busy_pct":{"queue worker 0x0":99.967,"queue worker 0x48":95.776,"queue worker 0x40":96.018,"queue worker 0x3a":0.000},"top_phases_ms_per_frame":{"Driver.Packet":6548.057,"Driver.Packet.memory_wait":4291.548,"Resources.Complete":1617.390,"Driver.Packet.draw":1551.543,"Driver.Draw":1551.289,"Driver.Draw.draw_enqueued":1526.657,"Graphics.Draw":1520.281,"Graphics.Draw.draw_and_resource_release":1516.714},"trace_dropped":false,"trace":"aps5-trace-9bbb7f37c655-33707.json.gz"}Digest of the clean trace (
aps5-trace-9bbb7f37c655-33707.json.gz, attached below):seconds 180:60 from present 2318: 27 presents, frame p50 2243.7 / p90 2558.9 / p99 2614.3 / max 2614.3 ms, GPU busy 939.9 ms per present
NVIDIA GeForce RTX 2080, NVIDIA 615.78.08, Linux 7.3.0-2-wyrmix, 3840x2160, commit 9bbb7f3, dropped: no
For comparison, the dirty capture had p50 2278 ms, GPU busy 939 ms per present, and the same split: queue worker 0x0 98 % busy, the draw committer 70 %, queue workers 0x40 and 0x48 96 % in
Driver.Packet.memory_wait.senjinthedragon commentedon Oct 26, 2026
aps5-trace-9bbb7f37c655-33707.json.gz
MarcZX10 commentedon Oct 26, 2026
I downloaded the clean trace and reran
python3 tools/trace_digest.pyagainst its matching summary line. It confirms the clean9bbb7f37c655capture: 27 presents, p50 2,243.7 ms, p99 2,614.3 ms, and 939.9 ms GPU busy per present. The trace breakdown also confirms about 4,291.5 ms/frame inDriver.Packet.memory_wait, 1,617.3 ms/frame inResources.Complete, and about 42% GPU busy. This independently verifies the slowdown without the extra environment switches or dirty-tree changes; it narrows the symptom to CPU-side packet/resource work but does not identify the precise cause. Thanks for adding the clean capture.seradavid commentedon Oct 26, 2026
Windows/AMD datapoint: sub-1 fps also outside the galaxy map
Same symptom on Windows on AMD, but in a different scene (the intro cutscene after New Game), so not
your repro — though this build sits inside the range you bisected:
main8a89c91cc2, and both329efe1bfand9bbb7f37care ancestors of it.Setup. ASTRO BOT PPSA21567 01.018.000, Windows 11 (10.0.26200), RX 9070 XT (AMD proprietary
driver 26.10.1, LLPC), Ryzen 7 9800X3D, 32 GB;
--windowsrelink from the same tree; 3840x2160 guestoutput presented at 2226x1252, HDR10; shader cache warm (1976 hits, 0 misses).
Before the cutscene: 35-37 fps, frame p50 26.9-28.5 ms. In it: 0.7 fps, frame p50 1482-1499 ms
(p99 1490-1503), 4 presents per ~6 s, p50 within 1.4 % of max — a fixed per-frame cost, not load.
The cost is one queue 0 submission held for the whole frame (
APS5_TRACE_GPU=1,executetodone):Inside it
Driver.Packet.drawis 1037 ms andResources.Complete1092 ms (nested), against 13.2 and10.4 ms before the cutscene. With
APS5_GPU_WAIT_TIMEOUT_MS=200noWAIT_REG_MEMexceeded 200 ms,so the cost is spread over the packet stream rather than one blocked wait. The GPU is idle
(
24-105 ms of GPU time per 10 s,untimed 664-783 ms), the shader cache has 0 misses and the hostimport budget is flat at 12 277 of 12 288 MiB through the slow phase.
Does your side see the same shape — one queue 0 submission per frame taking ~1.5 s with no single
wait over 200 ms? I can build
329efe1bfand repeat this cutscene for a same-machine A/B if useful.AI-assisted: yes.
MarcZX10 commentedon Oct 26, 2026
The Linux capture shows a similar high-level shape—long CPU-side
Driver.Packetwork with substantialResources.Completetime—but the title scene and GPU differ, so it does not establish that both reports have the same cause. Your Windows cutscene result is useful evidence that the slowdown is not confined to the galaxy-map scene or NVIDIA.If you have time, a same-machine cutscene comparison between
329efe1bfand8a89c91cc2would help establish whether this exact path regressed across the reported range. Matchingaps5-summary.jsonllines and traces for that scene would also let others compare the packet and resource phases directly.MarcZX10 commentedon Oct 26, 2026
Yes, the Linux capture has the same broad CPU-side shape: long
Driver.Packetwork, substantialResources.Complete, and low GPU busy time. The Windows cutscene trace has a different scene and GPU, so it does not establish a shared cause. Since you can reproduce on both revisions, that same-machine A/B (329efe1bfvs8a89c91cc2) would be especially useful; please keep the cutscene, settings, shader-cache state and trace window the same, and attach both summary lines and traces so the phase timings can be compared directly.seradavid commentedon Oct 26, 2026
Same-machine A/B:
329efe1bfvs8a89c91cc2on the cutsceneAs asked, I built both commits on one machine and ran the intro cutscene on each.
329efe1bfdoes notshow the stall.
Method. Each arm is its own install:
libsandrelinkerbuilt from that commit(
BUILD_TESTING=OFF, FFmpeg reused),app.exerelinked with that tree's relinker, identical runtimelayout. One warm-up run per arm to fill the shader cache, then the measured run. Identical switches on
both arms:
APS5_TRACE_SUMMARY_EVERY=5 APS5_TRACE_SECONDS=60:60 APS5_TRACE_EVENTS=1048576 APS5_HOST_IMPORT_MIB=12288 APS5_ADDRESS_COPY_MAX_MIB=4096Both measured runs reached
GAME: Level has started: intro_next(the cutscene after New Game) and wereplayed similarly. Machine and title: ASTRO BOT PPSA21567 01.018.000, Windows 11 (10.0.26200), RX 9070
XT (AMD proprietary 26.10.1, LLPC), Ryzen 7 9800X3D, 32 GB, 3840x2160 guest output presented at
2226x1252, HDR10.
329efe1bf8a89c91cc2Driver.PacketDriver.Packet.memory_waitResources.CompleteDriver.Packet.drawTrace digests (
tools/trace_digest.py), both over the same 60:60 window. These come from the firstrun of each arm; the later runs' windows were still open when the title exited, so they wrote no trace.
329efe1bf:seconds 60:60 from present 1522: 377 presents, frame p50 38.8 / p90 51.7 / p99 2855.9 / max 24556.1 ms, GPU busy 24.4 ms per present. The largest frames are pipeline creation, not the cutscene: one 24.5 s frame whose top slice isVulkan.GraphicsPipeline.create1080 ms, and a 10.8 s frame inWorkerWait. In the warm measured run the same scene has p99 556 ms / max 818 ms.8a89c91cc2:seconds 60:60 from present 2286: 831 presents, frame p50 48.0 / p90 55.0 / p99 1493.6 / max 1525.9 ms, GPU busy 34.1 ms per present. The slow frames are the cutscene ones described above, withDriver.Packet.memory_waitandResources.Completeas their largest slices.Reading. The sustained stall is not present at
329efe1bf: the same cutscene runs at 33-48 fpswith the draw path at 5.5 ms per frame. At
8a89c91cc2it locks to about 1.49 s per frame, with the1.5 s queue-0 submission span from my earlier comment. That is consistent with
329efe1bf..9bbb7f37ccontaining the change that causes it; I have not bisected further than these two endpoints.
Caveats: one measured run per arm, plus the warm-up; the measured
329efe1bfrun ended about 20 searlier than the
8a89c91cc2one, but the cutscene had already started and was running at 33-48 fps.The raw
aps5-summary.jsonllines for each arm follow in the next two comments.AI-assisted: yes.
seradavid commentedon Oct 26, 2026
329efe1bfrawaps5-summary.jsonllines (measured run, three consecutive intervals across the cutscene;65.396-70.880is where the scene is fully in, 167 presents at p50 22.8 ms){"commit":"329efe1bfdaf","dirty":null,"env":{"APS5_ADDRESS_COPY_MAX_MIB":"4096","APS5_HOST_IMPORT_MIB":"12288","APS5_TRACE_DIR":"<path>","APS5_TRACE_EVENTS":"1048576","APS5_TRACE_SECONDS":"60:60","APS5_TRACE_SUMMARY_EVERY":"5"},"gpu":"AMD Radeon RX 9070 XT","driver":"AMD proprietary driver 26.10.1 (LLPC)","os":"Windows 10.0.26200","cpu":"AMD Ryzen 7 9800X3D 8-Core Processor","cpu_threads":16,"memory_mib":31903,"title_id":"PPSA21567","title":"ASTRO BOT","content_version":"01.018.000","resolution":"3840x2160","window":{"spec":"summary_every 5","first_present":2038,"ms":5007.184},"interval_start_s":55.375,"interval_end_s":60.382,"presents":200,"frame_ms":{"p50":24.939,"p90":27.452,"p99":30.680,"max":31.440},"gpu_busy_ms_per_present":15.324,"worker_busy_pct":{"queue worker 0x0":98.079,"queue worker 0x48":99.023,"queue worker 0x40":99.805,"queue worker 0x3a":0.000,"queue worker 0x46":5.546},"top_phases_ms_per_frame":{"Driver.Packet":75.335,"Driver.Packet.memory_wait":46.576,"Driver.Packet.draw":8.450,"Driver.Draw":8.377,"Graphics.Draw":8.135,"Driver.Packet.dispatch":7.917,"Graphics.Draw.draw_and_resource_release":7.423,"Driver.Dispatch":6.551},"trace_dropped":false,"trace":""} {"commit":"329efe1bfdaf","dirty":null,"env":{"APS5_ADDRESS_COPY_MAX_MIB":"4096","APS5_HOST_IMPORT_MIB":"12288","APS5_TRACE_DIR":"<path>","APS5_TRACE_EVENTS":"1048576","APS5_TRACE_SECONDS":"60:60","APS5_TRACE_SUMMARY_EVERY":"5"},"gpu":"AMD Radeon RX 9070 XT","driver":"AMD proprietary driver 26.10.1 (LLPC)","os":"Windows 10.0.26200","cpu":"AMD Ryzen 7 9800X3D 8-Core Processor","cpu_threads":16,"memory_mib":31903,"title_id":"PPSA21567","title":"ASTRO BOT","content_version":"01.018.000","resolution":"3840x2160","window":{"spec":"summary_every 5","first_present":2238,"ms":5013.658},"interval_start_s":60.382,"interval_end_s":65.396,"presents":242,"frame_ms":{"p50":19.600,"p90":25.434,"p99":27.561,"max":27.720},"gpu_busy_ms_per_present":12.512,"worker_busy_pct":{"queue worker 0x0":97.784,"queue worker 0x48":98.581,"queue worker 0x40":99.802,"queue worker 0x3a":0.000,"queue worker 0x46":6.301},"top_phases_ms_per_frame":{"Driver.Packet":62.331,"Driver.Packet.memory_wait":37.991,"Driver.Packet.dispatch":6.653,"Driver.Packet.prepare_memory":6.343,"Driver.Packet.draw":5.545,"Driver.Draw":5.488,"Graphics.Draw":5.485,"Driver.Dispatch":5.253},"trace_dropped":false,"trace":""} {"commit":"329efe1bfdaf","dirty":null,"env":{"APS5_ADDRESS_COPY_MAX_MIB":"4096","APS5_HOST_IMPORT_MIB":"12288","APS5_TRACE_DIR":"<path>","APS5_TRACE_EVENTS":"1048576","APS5_TRACE_SECONDS":"60:60","APS5_TRACE_SUMMARY_EVERY":"5"},"gpu":"AMD Radeon RX 9070 XT","driver":"AMD proprietary driver 26.10.1 (LLPC)","os":"Windows 10.0.26200","cpu":"AMD Ryzen 7 9800X3D 8-Core Processor","cpu_threads":16,"memory_mib":31903,"title_id":"PPSA21567","title":"ASTRO BOT","content_version":"01.018.000","resolution":"3840x2160","window":{"spec":"summary_every 5","first_present":2480,"ms":5484.569},"interval_start_s":65.396,"interval_end_s":70.880,"presents":167,"frame_ms":{"p50":22.845,"p90":26.473,"p99":556.340,"max":818.223},"gpu_busy_ms_per_present":13.453,"worker_busy_pct":{"queue worker 0x0":98.478,"queue worker 0x48":78.497,"queue worker 0x40":85.293,"queue worker 0x3a":0.000,"queue worker 0x46":4.997},"top_phases_ms_per_frame":{"Driver.Packet":87.503,"Driver.Packet.memory_wait":49.915,"Graphics.Draw":16.460,"Graphics.Draw.draw_and_resource_release":15.755,"Driver.Packet.device_lock":11.190,"Vulkan.GraphicsPipeline":9.842,"Vulkan.GraphicsPipeline.create":9.572,"Vulkan.GraphicsPipelineLibrary":9.570},"trace_dropped":false,"trace":""}seradavid commentedon Oct 26, 2026
8a89c91cc2rawaps5-summary.jsonllines (measured run, four consecutive intervals; the cutscene is slow in all four, 4 presents per interval at p50 about 1.49 s){"commit":"8a89c91cc29d","dirty":false,"env":{"APS5_ADDRESS_COPY_MAX_MIB":"4096","APS5_HOST_IMPORT_MIB":"12288","APS5_TRACE_DIR":"<path>","APS5_TRACE_EVENTS":"1048576","APS5_TRACE_SECONDS":"60:60","APS5_TRACE_SUMMARY_EVERY":"5"},"gpu":"AMD Radeon RX 9070 XT","driver":"AMD proprietary driver 26.10.1 (LLPC)","os":"Windows 10.0.26200","cpu":"AMD Ryzen 7 9800X3D 8-Core Processor","cpu_threads":16,"memory_mib":31903,"title_id":"PPSA21567","title":"ASTRO BOT","content_version":"01.018.000","resolution":"3840x2160","window":{"spec":"summary_every 5","first_present":1781,"ms":5958.145},"interval_start_s":66.680,"interval_end_s":72.639,"presents":4,"frame_ms":{"p50":1488.348,"p90":1500.164,"p99":1500.164,"max":1500.164},"gpu_busy_ms_per_present":116.862,"worker_busy_pct":{"queue worker 0x0":99.963,"queue worker 0x40":100.413,"queue worker 0x48":100.425,"queue worker 0x3a":0.000,"queue worker 0x46":1.257},"top_phases_ms_per_frame":{"Driver.Packet":4497.963,"Driver.Packet.memory_wait":2977.421,"Resources.Complete":1095.968,"Driver.Packet.draw":1027.849,"Driver.Draw":1027.725,"Driver.Draw.draw_enqueued":1019.929,"Graphics.Draw":1013.645,"Graphics.Draw.draw_and_resource_release":1012.038},"trace_dropped":false,"trace":""} {"commit":"8a89c91cc29d","dirty":false,"env":{"APS5_ADDRESS_COPY_MAX_MIB":"4096","APS5_HOST_IMPORT_MIB":"12288","APS5_TRACE_DIR":"<path>","APS5_TRACE_EVENTS":"1048576","APS5_TRACE_SECONDS":"60:60","APS5_TRACE_SUMMARY_EVERY":"5"},"gpu":"AMD Radeon RX 9070 XT","driver":"AMD proprietary driver 26.10.1 (LLPC)","os":"Windows 10.0.26200","cpu":"AMD Ryzen 7 9800X3D 8-Core Processor","cpu_threads":16,"memory_mib":31903,"title_id":"PPSA21567","title":"ASTRO BOT","content_version":"01.018.000","resolution":"3840x2160","window":{"spec":"summary_every 5","first_present":1785,"ms":5931.600},"interval_start_s":72.639,"interval_end_s":78.570,"presents":4,"frame_ms":{"p50":1480.793,"p90":1494.971,"p99":1494.971,"max":1494.971},"gpu_busy_ms_per_present":157.160,"worker_busy_pct":{"queue worker 0x0":99.964,"queue worker 0x40":100.009,"queue worker 0x48":100.017,"queue worker 0x3a":0.000,"queue worker 0x46":0.968},"top_phases_ms_per_frame":{"Driver.Packet":4461.620,"Driver.Packet.memory_wait":2953.388,"Resources.Complete":1092.649,"Driver.Packet.draw":1030.391,"Driver.Draw":1030.279,"Driver.Draw.draw_enqueued":1021.139,"Graphics.Draw":1007.041,"Graphics.Draw.draw_and_resource_release":1005.389},"trace_dropped":false,"trace":""} {"commit":"8a89c91cc29d","dirty":false,"env":{"APS5_ADDRESS_COPY_MAX_MIB":"4096","APS5_HOST_IMPORT_MIB":"12288","APS5_TRACE_DIR":"<path>","APS5_TRACE_EVENTS":"1048576","APS5_TRACE_SECONDS":"60:60","APS5_TRACE_SUMMARY_EVERY":"5"},"gpu":"AMD Radeon RX 9070 XT","driver":"AMD proprietary driver 26.10.1 (LLPC)","os":"Windows 10.0.26200","cpu":"AMD Ryzen 7 9800X3D 8-Core Processor","cpu_threads":16,"memory_mib":31903,"title_id":"PPSA21567","title":"ASTRO BOT","content_version":"01.018.000","resolution":"3840x2160","window":{"spec":"summary_every 5","first_present":1789,"ms":5958.697},"interval_start_s":78.570,"interval_end_s":84.529,"presents":4,"frame_ms":{"p50":1494.074,"p90":1497.660,"p99":1497.660,"max":1497.660},"gpu_busy_ms_per_present":155.448,"worker_busy_pct":{"queue worker 0x0":99.960,"queue worker 0x40":99.861,"queue worker 0x48":99.881,"queue worker 0x3a":0.000,"queue worker 0x46":1.105},"top_phases_ms_per_frame":{"Driver.Packet":4479.337,"Driver.Packet.memory_wait":2960.942,"Resources.Complete":1096.762,"Driver.Packet.draw":1032.525,"Driver.Draw":1032.416,"Driver.Draw.draw_enqueued":1024.119,"Graphics.Draw":1010.455,"Graphics.Draw.draw_and_resource_release":1008.931},"trace_dropped":false,"trace":""} {"commit":"8a89c91cc29d","dirty":false,"env":{"APS5_ADDRESS_COPY_MAX_MIB":"4096","APS5_HOST_IMPORT_MIB":"12288","APS5_TRACE_DIR":"<path>","APS5_TRACE_EVENTS":"1048576","APS5_TRACE_SECONDS":"60:60","APS5_TRACE_SUMMARY_EVERY":"5"},"gpu":"AMD Radeon RX 9070 XT","driver":"AMD proprietary driver 26.10.1 (LLPC)","os":"Windows 10.0.26200","cpu":"AMD Ryzen 7 9800X3D 8-Core Processor","cpu_threads":16,"memory_mib":31903,"title_id":"PPSA21567","title":"ASTRO BOT","content_version":"01.018.000","resolution":"3840x2160","window":{"spec":"summary_every 5","first_present":1793,"ms":5987.951},"interval_start_s":84.529,"interval_end_s":90.517,"presents":4,"frame_ms":{"p50":1496.453,"p90":1515.676,"p99":1515.676,"max":1515.676},"gpu_busy_ms_per_present":154.188,"worker_busy_pct":{"queue worker 0x0":99.964,"queue worker 0x40":99.959,"queue worker 0x48":99.955,"queue worker 0x3a":0.000,"queue worker 0x46":1.978},"top_phases_ms_per_frame":{"Driver.Packet":4511.081,"Driver.Packet.memory_wait":2981.247,"Resources.Complete":1105.000,"Driver.Packet.draw":1037.453,"Driver.Draw":1037.342,"Driver.Draw.draw_enqueued":1028.280,"Graphics.Draw":1018.314,"Graphics.Draw.draw_and_resource_release":1016.702},"trace_dropped":false,"trace":""}MarcZX10 commentedon Oct 26, 2026
Thanks; this controlled same-machine comparison is strong evidence that the stall is reproducible on Windows/AMD in the intro cutscene across 329efe1 and 8a89c91. The measured intervals show 242 presents at 19.6 ms p50 on the earlier build versus 4 presents at 1,488 ms p50 on the later one. This broadens the regression evidence, while the different platform and scene still do not establish that it shares the Linux/NVIDIA galaxy-map cause or isolate the responsible change.
Could you attach the raw traces from the measured warm-cache intervals (or capture and attach a matching trace pair)? The digests described here come from separate first runs, and the earlier-build trace includes shader-pipeline compilation; traces matching the 19.6 ms and 1,488 ms summary intervals would let us compare the packet and resource-wait phases directly. The two summary-line comments are useful on their own, so this is only needed if the trace files are available.
seradavid commentedon Oct 26, 2026
Raw traces for the measured intervals — attached
aps5-traces-11461.zipOne run per arm, warm shader cache (1976 hits, 0 misses in both), identical switches
(
APS5_TRACE_SUMMARY_EVERY=5 APS5_TRACE_SECONDS=60:45 APS5_TRACE_EVENTS=1048576 APS5_HOST_IMPORT_MIB=12288 APS5_ADDRESS_COPY_MAX_MIB=4096), trace window 60-105 s. Both runs reachedGAME: Level has started: intro_next.The zip holds both traces, both
aps5-summary.jsonlfiles and a README. In each.jsonlthe lastblock is the run its trace belongs to; the trace window closes with a
"spec":"seconds 60:45"line inthe same file.
329efe1bf:seconds 60:45 from present 2282: 913 presents, frame p50 25.9 / p90 41.7 / p99 54.5 ms, GPU busy 16.6 ms per present8a89c91cc2:seconds 60:45 from present 1673: 273 presents, frame p50 41.8 / p90 45.4 / p99 1503.0 / max 1649.8 ms, GPU busy 38.2 ms per presentCorrection to my previous comment. "
329efe1bfdoes not show the stall" was too strong. It showsthe same signature, but on isolated frames: in the 45 s window there are 1.57 s, 1.69 s, 8.68 s and
20.08 s frames, the 8.68 s and 20.08 s ones dominated by
Driver.Packet.memory_wait(8.68 s and15.56 s), with
Graphics.Draw10.96 s inside the 20.08 s frame. The title recovers after each; thelast interval before the quit has 27 presents in 5 s at p50 65.5 ms.
8a89c91cc2never recovers: from 70.4 s to 124.3 s every 6 s summary interval has exactly 4 presentsat p50 1482-1507 ms, with
Driver.Packet.draw1.03 s andResources.Complete1.10 s per frame.So the same stall mechanism exists at
329efe1bfand fires on a handful of frames; the changebetween the two commits makes it fire on essentially every frame of this cutscene. That still points
at
329efe1bf..9bbb7f37c, but the distinction between "fires occasionally" and "fires always" is theone worth bisecting.
AI-assisted: yes.
aps5-traces-11461.zip
MarcZX10 commentedon Oct 26, 2026
I downloaded the attached pair and independently reran
tools/trace_digest.pyon both files. The digests match the posted summary lines, and neither trace reports dropped events. On329efe1bf, the 60:45 window has 913 presents, p50 25.9 ms, p99 54.5 ms and a 20,084.5 ms maximum; the trace shows a few isolated multi-secondDriver.Packet.memory_waitstalls. On8a89c91cc2, the same-machine/same-cutscene window has 273 presents, p50 41.8 ms, p99 1,503.0 ms and a 1,649.8 ms maximum;Driver.Packet.memory_wait, draw work andResources.Completeare sustained in the slow frames.\n\nThis verifies a severe Windows/AMD cutscene regression and supports the reported change from sporadic stalls to a sustained stall. It does not by itself identify the responsible commit in the range or prove the Linux/NVIDIA galaxy-map report has the same root cause.seradavid commentedon Oct 26, 2026
Bisected: PR #7705 (
cd0591c8f4), the sampled depth-plane copy budgetI bisected the first-parent chain between
329efe1bf(normal) and8a89c91cc2(stall) on thismachine, then confirmed the mechanism inside the offending build. The regression is introduced by
"fix(agc): bound the sampled depth-plane copies".
Bisect (Windows 11, RX 9070 XT, ASTRO BOT PPSA21567 01.018.000, same cutscene, each step built and
relinked from that commit):
329efe1bf8a89c91cc2e512cd51e88dcbc4e5c95e6ae6e3d0d962e7b9b468871895d4a5a2c946a31e20650e84f8b61a2ccacd0591c8f4b0f57be3c7cd0591c8f4is a direct child of the last good merge, so the introducing change is exactly #7705(
1f11b8ab9bbound the sampled depth-plane copies,3245a347e9test,c2b128b56dcount the stagingbuffer before evicting).
Mechanism. #7705 puts every sampled depth-plane copy in an LRU table with a 256 MiB budget
(
APS5_DEPTH_PLANE_COPY_MIB) and callsevictPlaneCopies(copyKey)after everyDepthSurfaceTexturelookup. The routine protects the copy it just refreshed but evicts every other copy until the total
fits:
HeldBytes()counts the depth image plus its staging buffer, so in this scene the copies togetherexceed the budget and every lookup discards all the others; each is re-created and re-copied the next
time it is sampled. That is visible in the driver counters as more per-present traffic:
storage-writeback51 ranges / 214.4 MiB against 24 / 83.5, andstorage-upload23 / 133.7 MiBagainst 11.2 / 78.7, with the GPU itself idle.
Confirmation. The same
cd0591c8f4build, with nothing changed butAPS5_DEPTH_PLANE_COPY_MIB=0(keep every copy):same machine, same build.
So the budget is the cause, not the recorder
Keepof the staging buffer and image that the samechange adds.
Workaround:
APS5_DEPTH_PLANE_COPY_MIB=0, or a value large enough for the scene.Fix directions for the author: don't evict on every lookup when a single copy plus the kept one
already exceeds the budget (the loop then throws away all the others every time); count the transient
staging buffer against a separate allowance rather than the reusable budget; and scale the default
budget with the device heap instead of a fixed 256 MiB.
This was measured in the intro cutscene after New Game on Windows/AMD, not in the galaxy map from the
report, so the scenes differ; the range and the cause are the same, and a fix here should carry
Fixes #11461.AI-assisted: yes.
MarcZX10 commentedon Oct 26, 2026
Thanks for the bisection and the controlled
APS5_DEPTH_PLANE_COPY_MIB=0run. The currentDepthSurfaceTexturepath refreshes the copy and then callsevictPlaneCopies; that routine totals the image plus staging buffer and protects only the copy used by that lookup. Your 288 MiB + 48 MiB working set therefore explains why alternating lookups keep evicting the copy needed next.Open #11307 already proposes retaining copies sampled in the current/previous present, which appears directly relevant and avoids duplicating that work. However, its current head
4b08a0542cis 581 commits behind currentmain(d891568dfc) and has not yet been validated against that base. Its added over-budget test covers two 1 MiB test copies, not this reported 288 MiB single-copy case. A current-main rebase and a regression case matching the over-budget alternating workload would establish whether that PR fixes this report.ponhei9502 commentedon Oct 27, 2026
Second title, Linux/NVIDIA: Demon's Souls shows the same depth-plane copy thrash; a larger
APS5_DEPTH_PLANE_COPY_MIBremoves most of itThis is data from a different game that supports the #7705 bisect above. Setup: Demon's Souls PPSA01341, Linux, RTX 3080 10 GB, NVIDIA 615.78.08, a fork based on
main74ac0e7 (which contains #7705). The scene is a dev-menu route to the 1-1 Boletarian Palace scene; the scene is GPU-light and CPU-bound on queue 0.Method. One boot, warm caches. The budget alternated between 256 MiB (the default) and 1024 MiB every 30 s through a runtime switch file, so both arms share the same boot, scene and cache state. Below are the per-arm totals over the boot's measured windows (game log counters):
vkAllocateMemoryOOM recoveries for depth plane copiesMechanism, as far as we can see. It matches the description above of
evictPlaneCopiesprotecting only the current lookup's copy. In this scene each plane copy is ~320 MiB, so under 256 MiB every lookup evicts the copy the next lookup needs. The remake is then allocated with VRAM near full (8.8 of 9.0 GB usable), so it often fails and recovers by reclaiming other memory. That recovery runs under the GPU mutex, and those long holds stall the draw thread.Caveats:
APS5_DEPTH_PLANE_COPY_MIB=1024(or higher, VRAM permitting) at launch today. It's an existing switch from fix(agc): bound the sampled depth-plane copies #7705.We'll add the multi-boot numbers here once the repeats finish.
AI-assisted: yes.
ponhei9502 commentedon Oct 27, 2026
Follow-up: 4 boots, Demon's Souls,
APS5_DEPTH_PLANE_COPY_MIB256 vs 1024 (same setup as my comment above)Here are the multi-boot numbers I promised. Same method: within each boot the budget alternated every 30 s through a runtime switch file. The counter is presents per 10 s from a uprobe on present. (My first comment used the game log's own counter, so its per-arm values differ a little.)
Reading it honestly:
AI-assisted: yes.
oneandonlydean commentedon Nov 11, 2026
@senjinthedragon @seradavid thanks to seradavid's bisect this traced to #7705 (the depth-plane copy budget evicting the copy the next lookup needs). #11307 keeps recently sampled copies and was merged on 2026-10-28, after the 9bbb7f3 build used in the Linux traces.
Could you retest on current main (it contains merge commit ccfb967) without APS5_DEPTH_PLANE_COPY_MIB set, same scene, and post the frame p50 from the trace summary line? If it is still slow, please attach the new summary line and I will reopen the investigation.
oneandonlydean commentedon Nov 11, 2026
The PPSA21567 slowdown caused by the depth plane copy budget (#7705) was fixed on main by #11307 (merged). If you still see it on a build that contains #11307, please reopen and post the commit and the trace summary line.