Skip to content

perf(agc): read committed guest pages directly on Windows - #14799

Merged
oneandonlydean merged 1 commit into
boykopovar:mainfrom
chitters2004:perf/guarded-committed-read
Nov 3, 2026
Merged

oneandonlydean merged 1 commit into
boykopovar:mainfrom
chitters2004:perf/guarded-committed-read

Conversation

@chitters2004

@chitters2004 chitters2004 commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor

What

On Windows every committed guest copy and compare goes through ReadProcessMemory, added in 4201b82 so that a page released during the read counts as uncommitted instead of faulting. Revalidation issues one system call per compare and then compares a second copy of the bytes. In GTA V (PPSA04263) ZwReadVirtualMemory was 12% of the committer thread's samples, and the committer is the thread that bounds the frame: it waited for only 12% of the steady window.

Ranges the guest arena owns, outside recorded host regions, are now read by leaf copy and compare routines in GuestArena.cpp. Hosts with AVX2 take 64 bytes per pass, with 16-byte and byte tails; other hosts keep the 16-byte loop. A fault on one of their source loads resumes at a failure return, and the read falls back to the existing page by page path, so released pages keep their behaviour: zero in a copy, left out of a compare. Host regions and addresses outside the arena keep ReadProcessMemory, which covers the host heap case of 4201b82. Linux is unchanged.

GuestArenaRecoverRead_nid_no_patch runs first in ReportCrash and ReturnBreakHandler. It takes only read access violations and in-page errors, at an exact source load, with the fault address inside the interval being read. A fault on the destination or expected buffer, or anywhere else, still reaches the crash path.

Guard pages are not recovered. Accessible and CommittedRanges exclude a guarded page on a fresh query, so a direct read only meets one through stale page state, which means a guard was set on arena memory without going through GuestAllocations. No non-test code sets PAGE_GUARD. OS stack guards are out of reach: a stack inside the arena bounds at startup is in _hostRegions, later stacks cannot land in the reserved placeholders, and guest threads run on _beginthreadex stacks. That relies on Windows honouring reservations. Such a guard ends as an unhandled exception; it may not print the usual FATAL report. The existing CommittedReadMapping case that set a raw guard now announces it through GuestAllocations::Mutation, the contract real code follows.

Tested

Windows 11, Ryzen 7 5800X, RTX 3080, GTA V (PPSA04263), save at the first autosave, standing still, 3840x2160. Main e0caf13600 and this PR 79ee45a6e2 each with #11580 applied, because main aborts at Story load without it (#11425), giving commits b9c59ab4094a and cfbd1938d453. Boots interleaved. Frame time is the median from videoout present stamps, +20 to +140 s after the player stands still.

Boot 1 Boot 2 Mean
main 177.6 180.1 178.9 ms
this PR 160.2 158.8 159.5 ms

About 19 ms, 10.8%, about 5.6 to 6.3 fps. GPU busy per present stayed at about 42 ms. No fatal in any boot. The previous head of this PR, without the wider loops and on f2d874c1fd, read 180.0 and 161.0 ms over four boots a side.

Warm captures as the form describes: the scene ran once, the title was restarted on that cache, same save and input, one extra boot a side after the timing boots, APS5_TRACE_SECONDS=240:20. These replace the previous captures: an input script left over from the earlier fix capture was still tapping during the earlier main capture, so that one should not be used. The four boots above are the claim.

# Performance comparison

| Capture | Commit | Trace | Presents | Window (ms) |
| --- | --- | --- | ---: | ---: |
| baseline | b9c59ab4094a | aps5-trace-b9c59ab4094a-15408.json.gz | 109 | 20174.690 |
| candidate | cfbd1938d453 | aps5-trace-cfbd1938d453-16724.json.gz | 128 | 20075.328 |

- Compare captures from the same machine, title, content version and scene; matching recorded metadata cannot verify the physical machine or scene.
- Changes are candidate minus baseline. A negative frame-time change means a shorter frame interval.
- A missing top phase is unreported, not zero; its change is unavailable.
- Worker busy changes are percentage points; change (%) is relative to the baseline. Workers are matched by their recorded names; a missing worker is unreported, not idle.
- baseline: trace events were dropped; the event trace omits some of the work included in phase totals.
- candidate: trace events were dropped; the event trace omits some of the work included in phase totals.

## Frame and GPU times (ms)

| Metric | Baseline | Candidate | Change | Change (%) |
| --- | ---: | ---: | ---: | ---: |
| frame_ms.p50 | 183.912 | 156.078 | -27.834 | -15.134 |
| frame_ms.p90 | 190.396 | 163.000 | -27.396 | -14.389 |
| frame_ms.p99 | 199.967 | 180.329 | -19.638 | -9.821 |
| frame_ms.max | 240.345 | 214.877 | -25.468 | -10.596 |
| mean_frame_ms | 185.089 | 156.839 | -28.250 | -15.263 |
| gpu_busy_ms_per_present | 41.690 | 41.470 | -0.220 | -0.528 |

## Top phases (ms per frame)

| Metric | Baseline | Candidate | Change | Change (%) |
| --- | ---: | ---: | ---: | ---: |
| Driver.Draw | 130.073 | 105.778 | -24.295 | -18.678 |
| Driver.Draw.draw_enqueued | 53.492 | 32.582 | -20.910 | -39.090 |
| Driver.Draw.shader_compile_and_link | 57.957 | 55.492 | -2.465 | -4.253 |
| Driver.Packet | 174.318 | 146.557 | -27.761 | -15.925 |
| Driver.Packet.draw | 131.167 | 106.732 | -24.435 | -18.629 |
| Graphics.Draw | 139.392 | 113.653 | -25.739 | -18.465 |
| Graphics.Draw.draw_and_resource_release | 113.566 | 88.372 | -25.194 | -22.184 |
| Shader.DrawStage | 44.767 | 42.977 | -1.790 | -3.998 |

## Worker busy time (%)

| Metric | Baseline | Candidate | Change (pp) | Change (%) |
| --- | ---: | ---: | ---: | ---: |
| queue worker 0x0 | 98.147 | 97.898 | -0.249 | -0.254 |

Deviations from the form: the log is redirected and frames are dumped on every run, because the script that drives the menus reads both, so the two sides pay the same cost. A d-pad tap every 15 s holds the normal camera, because the idle cinematic camera otherwise adds about 45 ms at +72 s. APS5_ADDRESS_COPY_MAX_MIB=512 is set on both sides. CPU and GPU utilisation loggers (typeperf, nvidia-smi) ran during every boot. The timing boots keep APS5_TRACE_SUMMARY_EVERY=10 and no trace. The order was a warm-up boot of this PR, then this PR, main, this PR, main; no run was thrown away. The first main boot waited about 50 s longer at the title because the menu script missed a press; the frame window starts when the player stands still, so it is unaffected. The game window had focus for the timing boots, but only 22 of 56 samples in the capture of this PR and 52 of 55 in the capture of main, which if anything favours main. Both traces report dropped events.

aps5-summary.jsonl lines, warm capture main and this PR, then one 10 s window of a timing boot of each:

{"commit":"b9c59ab4094a","dirty":false,"env":{"APS5_ADDRESS_COPY_MAX_MIB":"512","APS5_DUMP_FRAMES":"80","APS5_DUMP_FRAMES_EVERY":"300","APS5_LOG_TIMESTAMPS":"1","APS5_NO_PAD_INPUT":"1","APS5_PAD_INPUT_FILE":"<path>","APS5_TRACE_DIR":"<path>","APS5_TRACE_SECONDS":"240:20","APS5_TRACE_SUMMARY_EVERY":"10","APS5_VIDEOOUT_TELEMETRY_DIR":"<path>"},"gpu":"NVIDIA GeForce RTX 3080","driver":"NVIDIA 621.01","os":"Windows 10.0.26220","cpu":"AMD Ryzen 7 5800X 8-Core Processor","cpu_threads":16,"memory_mib":32676,"title_id":"PPSA04263","title":"Grand Theft Auto V","content_version":"01.011.001","resolution":"3840x2160","window":{"spec":"seconds 240:20","first_present":3925,"ms":20174.690},"presents":109,"frame_ms":{"p50":183.912,"p90":190.396,"p99":199.967,"max":240.345},"gpu_busy_ms_per_present":41.690,"worker_busy_pct":{"queue worker 0x0":98.147},"top_phases_ms_per_frame":{"Driver.Packet":174.318,"Graphics.Draw":139.392,"Driver.Packet.draw":131.167,"Driver.Draw":130.073,"Graphics.Draw.draw_and_resource_release":113.566,"Driver.Draw.shader_compile_and_link":57.957,"Driver.Draw.draw_enqueued":53.492,"Shader.DrawStage":44.767},"trace_dropped":true,"trace_dropped_threads":{"queue worker 0x0":{"events_full_after_s":5.325,"events_lost":729388,"totals_full":false},"draw committer":{"events_full_after_s":12.244,"events_lost":169351,"totals_full":false}},"trace":"aps5-trace-b9c59ab4094a-15408.json.gz"}
{"commit":"cfbd1938d453","dirty":false,"env":{"APS5_ADDRESS_COPY_MAX_MIB":"512","APS5_DUMP_FRAMES":"80","APS5_DUMP_FRAMES_EVERY":"300","APS5_LOG_TIMESTAMPS":"1","APS5_NO_PAD_INPUT":"1","APS5_PAD_INPUT_FILE":"<path>","APS5_TRACE_DIR":"<path>","APS5_TRACE_SECONDS":"240:20","APS5_TRACE_SUMMARY_EVERY":"10","APS5_VIDEOOUT_TELEMETRY_DIR":"<path>"},"gpu":"NVIDIA GeForce RTX 3080","driver":"NVIDIA 621.01","os":"Windows 10.0.26220","cpu":"AMD Ryzen 7 5800X 8-Core Processor","cpu_threads":16,"memory_mib":32676,"title_id":"PPSA04263","title":"Grand Theft Auto V","content_version":"01.011.001","resolution":"3840x2160","window":{"spec":"seconds 240:20","first_present":4009,"ms":20075.328},"presents":128,"frame_ms":{"p50":156.078,"p90":163.000,"p99":180.329,"max":214.877},"gpu_busy_ms_per_present":41.470,"worker_busy_pct":{"queue worker 0x0":97.898},"top_phases_ms_per_frame":{"Driver.Packet":146.557,"Graphics.Draw":113.653,"Driver.Packet.draw":106.732,"Driver.Draw":105.778,"Graphics.Draw.draw_and_resource_release":88.372,"Driver.Draw.shader_compile_and_link":55.492,"Shader.DrawStage":42.977,"Driver.Draw.draw_enqueued":32.582},"trace_dropped":true,"trace_dropped_threads":{"queue worker 0x0":{"events_full_after_s":4.682,"events_lost":853701,"totals_full":false},"draw committer":{"events_full_after_s":10.621,"events_lost":233960,"totals_full":false}},"trace":"aps5-trace-cfbd1938d453-16724.json.gz"}
{"commit":"b9c59ab4094a","dirty":false,"env":{"APS5_ADDRESS_COPY_MAX_MIB":"512","APS5_DUMP_FRAMES":"80","APS5_DUMP_FRAMES_EVERY":"300","APS5_LOG_TIMESTAMPS":"1","APS5_NO_PAD_INPUT":"1","APS5_PAD_INPUT_FILE":"<path>","APS5_TRACE_DIR":"<path>","APS5_TRACE_SUMMARY_EVERY":"10","APS5_VIDEOOUT_TELEMETRY_DIR":"<path>"},"gpu":"NVIDIA GeForce RTX 3080","driver":"NVIDIA 621.01","os":"Windows 10.0.26220","cpu":"AMD Ryzen 7 5800X 8-Core Processor","cpu_threads":16,"memory_mib":32676,"title_id":"PPSA04263","title":"Grand Theft Auto V","content_version":"01.011.001","resolution":"3840x2160","window":{"spec":"summary_every 10","first_present":3973,"ms":10038.433},"interval_start_s":251.526,"interval_end_s":261.564,"presents":55,"frame_ms":{"p50":179.600,"p90":195.494,"p99":221.940,"max":221.940},"gpu_busy_ms_per_present":41.926,"worker_busy_pct":{"queue worker 0x0":98.092},"top_phases_ms_per_frame":{"Driver.Packet":171.244,"Graphics.Draw":136.024,"Driver.Packet.draw":130.164,"Driver.Draw":129.147,"Graphics.Draw.draw_and_resource_release":110.092,"Driver.Draw.shader_compile_and_link":61.053,"Driver.Draw.draw_enqueued":49.263,"Shader.DrawStage":47.806},"trace_dropped":false,"trace":""}
{"commit":"cfbd1938d453","dirty":false,"env":{"APS5_ADDRESS_COPY_MAX_MIB":"512","APS5_DUMP_FRAMES":"80","APS5_DUMP_FRAMES_EVERY":"300","APS5_LOG_TIMESTAMPS":"1","APS5_NO_PAD_INPUT":"1","APS5_PAD_INPUT_FILE":"<path>","APS5_TRACE_DIR":"<path>","APS5_TRACE_SUMMARY_EVERY":"10","APS5_VIDEOOUT_TELEMETRY_DIR":"<path>"},"gpu":"NVIDIA GeForce RTX 3080","driver":"NVIDIA 621.01","os":"Windows 10.0.26220","cpu":"AMD Ryzen 7 5800X 8-Core Processor","cpu_threads":16,"memory_mib":32676,"title_id":"PPSA04263","title":"Grand Theft Auto V","content_version":"01.011.001","resolution":"3840x2160","window":{"spec":"summary_every 10","first_present":4109,"ms":10053.063},"interval_start_s":251.723,"interval_end_s":261.776,"presents":62,"frame_ms":{"p50":160.081,"p90":167.314,"p99":221.590,"max":221.590},"gpu_busy_ms_per_present":41.102,"worker_busy_pct":{"queue worker 0x0":97.897},"top_phases_ms_per_frame":{"Driver.Packet":151.573,"Graphics.Draw":117.322,"Driver.Packet.draw":110.083,"Driver.Draw":109.189,"Graphics.Draw.draw_and_resource_release":91.297,"Driver.Draw.shader_compile_and_link":57.744,"Shader.DrawStage":44.796,"Driver.Draw.draw_enqueued":33.035},"trace_dropped":false,"trace":""}

Traces: warm main, warm this PR. Raw files of every boot, digests, comparison and benchmark source and results: pr14799-evidence-v3.zip.

tools/trace_digest.py summaries:

seconds 240:20 from present 3925: 109 presents, frame p50 183.9 / p90 190.4 / p99 200.0 / max 240.3 ms, GPU busy 41.7 ms per present
NVIDIA GeForce RTX 3080, NVIDIA 621.01, Windows 10.0.26220, 3840x2160, commit b9c59ab4094a, dropped: yes

{"commit":"b9c59ab4094a","dirty":false,"env":{"APS5_ADDRESS_COPY_MAX_MIB":"512","APS5_DUMP_FRAMES":"80","APS5_DUMP_FRAMES_EVERY":"300","APS5_LOG_TIMESTAMPS":"1","APS5_NO_PAD_INPUT":"1","APS5_PAD_INPUT_FILE":"<path>","APS5_TRACE_DIR":"<path>","APS5_TRACE_SECONDS":"240:20","APS5_TRACE_SUMMARY_EVERY":"10","APS5_VIDEOOUT_TELEMETRY_DIR":"<path>"},"gpu":"NVIDIA GeForce RTX 3080","driver":"NVIDIA 621.01","os":"Windows 10.0.26220","cpu":"AMD Ryzen 7 5800X 8-Core Processor","cpu_threads":16,"memory_mib":32676,"title_id":"PPSA04263","title":"Grand Theft Auto V","content_version":"01.011.001","resolution":"3840x2160","window":{"spec":"seconds 240:20","first_present":3925,"ms":20174.69},"presents":109,"frame_ms":{"p50":183.912,"p90":190.396,"p99":199.967,"max":240.345},"gpu_busy_ms_per_present":41.69,"worker_busy_pct":{"queue worker 0x0":98.147},"top_phases_ms_per_frame":{"Driver.Packet":174.318,"Graphics.Draw":139.392,"Driver.Packet.draw":131.167,"Driver.Draw":130.073,"Graphics.Draw.draw_and_resource_release":113.566,"Driver.Draw.shader_compile_and_link":57.957,"Driver.Draw.draw_enqueued":53.492,"Shader.DrawStage":44.767},"trace_dropped":true,"trace_dropped_threads":{"queue worker 0x0":{"events_full_after_s":5.325,"events_lost":729388,"totals_full":false},"draw committer":{"events_full_after_s":12.244,"events_lost":169351,"totals_full":false}},"trace":"aps5-trace-b9c59ab4094a-15408.json.gz"}

Slowest frames (largest slices inside each, inclusive)

  • present 3986: 240.3 ms at 11325 ms: Graphics.Draw (draw committer) 122.1, Graphics.Draw.draw_and_resource_release (draw committer) 96.4, batch (gpu) 41.7, Recorder.Sync (draw committer) 14.7
  • present 4012: 200.0 ms at 16123 ms: batch (gpu) 41.9, VideoOut.Flip (presenter) 14.3, VideoOut.Flip.present (presenter) 14.2, Driver.Present (presenter) 14.2
  • present 3959: 196.8 ms at 6309 ms: Graphics.Draw (draw committer) 134.0, Graphics.Draw.draw_and_resource_release (draw committer) 107.5, batch (gpu) 41.7, Recorder.Sync (draw committer) 14.5
  • present 3962: 195.2 ms at 6876 ms: Graphics.Draw (draw committer) 132.5, Graphics.Draw.draw_and_resource_release (draw committer) 104.3, batch (gpu) 41.8, VideoOut.Flip (presenter) 14.4
  • present 3967: 194.7 ms at 7807 ms: Graphics.Draw (draw committer) 125.6, Graphics.Draw.draw_and_resource_release (draw committer) 100.3, batch (gpu) 42.6, Recorder.Sync (draw committer) 14.8

Threads (ms per frame)

thread busy wait untraced in slices < 20 us largest
title 0.0 (0 %) 0.0 (0 %) 185.1 0.0 Shader.ResolveGraphicsStagesAbi 0.0
queue worker 0x0 41.8 (23 %) 0.3 (0 %) 143.0 45.5 Driver.Packet 40.1, Driver.Rewind 1.1
draw committer 85.4 (46 %) 0.0 (0 %) 99.7 29.5 Graphics.Draw 74.9, Recorder.Sync 7.7
presenter 0.6 (0 %) 13.7 (7 %) 170.8 0.1 VideoOut.Flip 14.3
gpu 41.6 (22 %) 0.0 (0 %) 143.5 0.0 batch 41.6

Largest slices (ms per frame, inclusive, all threads): Graphics.Draw 75.4, Graphics.Draw.draw_and_resource_release 60.0, batch 41.6, Driver.Packet 40.1, Driver.Packet.draw 31.1, Driver.Draw 30.8, VideoOut.Flip 14.3, VideoOut.Flip.present 14.2, Driver.Present 14.2, Driver.Present.render_fence_wait 13.7

Longest waits

  • Driver.Present.render_fence_wait (presenter) 14.2 ms at 2423 ms, present 3938
  • Driver.Present.render_fence_wait (presenter) 14.1 ms at 7624 ms, present 3966
  • Driver.Present.render_fence_wait (presenter) 14.1 ms at 15393 ms, present 4008
  • Driver.Present.render_fence_wait (presenter) 14.1 ms at 15209 ms, present 4007
  • Driver.Present.render_fence_wait (presenter) 14.0 ms at 18901 ms, present 4027
  • Driver.Present.render_fence_wait (presenter) 14.0 ms at 11325 ms, present 3986
  • Driver.Present.render_fence_wait (presenter) 14.0 ms at 2608 ms, present 3939
  • Driver.Present.render_fence_wait (presenter) 14.0 ms at 8936 ms, present 3973
  • Driver.Present.render_fence_wait (presenter) 14.0 ms at 6689 ms, present 3961
  • Driver.Present.render_fence_wait (presenter) 14.0 ms at 13570 ms, present 3998

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

  • batch 132119: 15.4 ms at 2605 ms, present 3938: GPU no ranges; recorded by Graphics.Draw (draw committer) 0.5, Graphics.Draw.draw_and_resource_release (draw committer) 0.4, Recorder.Submit (draw committer) 0.0
  • batch 137008: 15.3 ms at 9122 ms, present 3973: GPU no ranges; recorded by Graphics.Draw (draw committer) 0.5, Graphics.Draw.draw_and_resource_release (draw committer) 0.5, Recorder.Submit (draw committer) 0.0
  • batch 131979: 15.2 ms at 2422 ms, present 3937: GPU no ranges; recorded by Graphics.Draw (draw committer) 0.5, Graphics.Draw.draw_and_resource_release (draw committer) 0.5, Recorder.Submit (draw committer) 0.0
  • batch 139803: 15.1 ms at 12837 ms, present 3993: GPU no ranges; recorded by no CPU slices
  • batch 144388: 15.1 ms at 18899 ms, present 4026: GPU no ranges; recorded by no CPU slices

seconds 240:20 from present 4009: 128 presents, frame p50 156.1 / p90 163.0 / p99 180.3 / max 214.9 ms, GPU busy 41.5 ms per present
NVIDIA GeForce RTX 3080, NVIDIA 621.01, Windows 10.0.26220, 3840x2160, commit cfbd1938d453, dropped: yes

{"commit":"cfbd1938d453","dirty":false,"env":{"APS5_ADDRESS_COPY_MAX_MIB":"512","APS5_DUMP_FRAMES":"80","APS5_DUMP_FRAMES_EVERY":"300","APS5_LOG_TIMESTAMPS":"1","APS5_NO_PAD_INPUT":"1","APS5_PAD_INPUT_FILE":"<path>","APS5_TRACE_DIR":"<path>","APS5_TRACE_SECONDS":"240:20","APS5_TRACE_SUMMARY_EVERY":"10","APS5_VIDEOOUT_TELEMETRY_DIR":"<path>"},"gpu":"NVIDIA GeForce RTX 3080","driver":"NVIDIA 621.01","os":"Windows 10.0.26220","cpu":"AMD Ryzen 7 5800X 8-Core Processor","cpu_threads":16,"memory_mib":32676,"title_id":"PPSA04263","title":"Grand Theft Auto V","content_version":"01.011.001","resolution":"3840x2160","window":{"spec":"seconds 240:20","first_present":4009,"ms":20075.328},"presents":128,"frame_ms":{"p50":156.078,"p90":163.0,"p99":180.329,"max":214.877},"gpu_busy_ms_per_present":41.47,"worker_busy_pct":{"queue worker 0x0":97.898},"top_phases_ms_per_frame":{"Driver.Packet":146.557,"Graphics.Draw":113.653,"Driver.Packet.draw":106.732,"Driver.Draw":105.778,"Graphics.Draw.draw_and_resource_release":88.372,"Driver.Draw.shader_compile_and_link":55.492,"Shader.DrawStage":42.977,"Driver.Draw.draw_enqueued":32.582},"trace_dropped":true,"trace_dropped_threads":{"queue worker 0x0":{"events_full_after_s":4.682,"events_lost":853701,"totals_full":false},"draw committer":{"events_full_after_s":10.621,"events_lost":233960,"totals_full":false}},"trace":"aps5-trace-cfbd1938d453-16724.json.gz"}

Slowest frames (largest slices inside each, inclusive)

  • present 4093: 214.9 ms at 13231 ms: batch (gpu) 41.3, VideoOut.Flip (presenter) 14.5, VideoOut.Flip.present (presenter) 14.3, Driver.Present (presenter) 14.3
  • present 4061: 180.3 ms at 8199 ms: Graphics.Draw (draw committer) 116.0, Graphics.Draw.draw_and_resource_release (draw committer) 86.8, batch (gpu) 42.5, VideoOut.Flip (presenter) 14.6
  • present 4045: 178.5 ms at 5658 ms: Graphics.Draw (draw committer) 117.5, Graphics.Draw.draw_and_resource_release (draw committer) 82.2, batch (gpu) 41.5, VideoOut.Flip (presenter) 14.8
  • present 4043: 172.4 ms at 5332 ms: Graphics.Draw (draw committer) 111.9, Graphics.Draw.draw_and_resource_release (draw committer) 79.0, batch (gpu) 41.6, VideoOut.Flip (presenter) 14.2
  • present 4049: 171.2 ms at 6306 ms: Graphics.Draw (draw committer) 108.5, Graphics.Draw.draw_and_resource_release (draw committer) 78.8, batch (gpu) 41.6, VideoOut.Flip (presenter) 14.1

Threads (ms per frame)

thread busy wait untraced in slices < 20 us largest
title 0.0 (0 %) 0.0 (0 %) 156.8 0.0 Shader.ResolveGraphicsStagesAbi 0.0
queue worker 0x0 30.3 (19 %) 0.2 (0 %) 126.3 40.5 Driver.Packet 29.1, Driver.Rewind 0.9
draw committer 60.2 (38 %) 0.0 (0 %) 96.6 26.8 Graphics.Draw 51.5, Recorder.Sync 6.4
presenter 0.6 (0 %) 13.6 (9 %) 142.6 0.1 VideoOut.Flip 14.2
gpu 41.3 (26 %) 0.0 (0 %) 115.5 0.0 batch 41.3

Largest slices (ms per frame, inclusive, all threads): Graphics.Draw 52.0, batch 41.3, Graphics.Draw.draw_and_resource_release 38.5, Driver.Packet 29.1, Driver.Packet.draw 21.8, Driver.Draw 21.6, VideoOut.Flip 14.2, VideoOut.Flip.present 14.1, Driver.Present 14.1, Driver.Present.render_fence_wait 13.6

Longest waits

  • Driver.Present.render_fence_wait (presenter) 14.0 ms at 16835 ms, present 4116
  • Driver.Present.render_fence_wait (presenter) 14.0 ms at 6477 ms, present 4050
  • Driver.Present.render_fence_wait (presenter) 14.0 ms at 16539 ms, present 4114
  • Driver.Present.render_fence_wait (presenter) 14.0 ms at 17601 ms, present 4121
  • Driver.Present.render_fence_wait (presenter) 13.9 ms at 10432 ms, present 4075
  • Driver.Present.render_fence_wait (presenter) 13.9 ms at 6632 ms, present 4051
  • Driver.Present.render_fence_wait (presenter) 13.9 ms at 16688 ms, present 4115
  • Driver.Present.render_fence_wait (presenter) 13.9 ms at 8200 ms, present 4061
  • Driver.Present.render_fence_wait (presenter) 13.9 ms at 9015 ms, present 4066
  • Driver.Present.render_fence_wait (presenter) 13.9 ms at 9967 ms, present 4072

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

  • batch 150075: 15.2 ms at 2529 ms, present 4024: GPU no ranges; recorded by Graphics.Draw (draw committer) 0.6, Graphics.Draw.draw_and_resource_release (draw committer) 0.5, Recorder.Submit (draw committer) 0.0
  • batch 159834: 15.2 ms at 13600 ms, present 4094: GPU no ranges; recorded by no CPU slices
  • batch 154810: 15.1 ms at 7882 ms, present 4058: GPU no ranges; recorded by Graphics.Draw (draw committer) 0.7, Graphics.Draw.draw_and_resource_release (draw committer) 0.6, Recorder.Submit (draw committer) 0.0
  • batch 155653: 15.1 ms at 8861 ms, present 4064: GPU no ranges; recorded by Graphics.Draw (draw committer) 0.5, Graphics.Draw.draw_and_resource_release (draw committer) 0.4, Recorder.Submit (draw committer) 0.0
  • batch 163383: 15.1 ms at 17599 ms, present 4120: GPU no ranges; recorded by no CPU slices

Benchmark, one pinned thread, median of 21, GB/s, equal data, 4 KiB / 256 KiB / 4 MiB / 64 MiB:

4 KiB 256 KiB 4 MiB 64 MiB
main path, ReadProcessMemory + memcmp 4.7 15 13 6.8
memcmp 45 34 26 19
SSE2 16-byte loop 32 36 29 20
this PR, AVX2 64-byte loop 68-111 58-69 44-59 21-22

The 4 KiB and 4 MiB results varied between runs, so ranges are given. Copy, ReadProcessMemory then this PR: 5.3 then 107-145, 27 then 60-67, 26-29 then 38-63, 11 then 14 GB/s. memcpy reaches about 21 GB/s at 64 MiB, ahead of this loop at that size only. Prefetching gave no gain and was left out.

Fault cost: a local counter build, not part of this PR, recorded 0 recovered faults in about 1.44 million guarded reads on this scene. There is no data from a streaming-heavy title. OwnedByGuest takes no lock: Contains is arithmetic and OverlapsHostRegion walks _hostRegions, which on Windows is only written at startup. It held 80 entries here, 46.6 ns a call in a standalone timing, about 0.03 ms a frame at about 720 calls a frame.

Tests: agc_driver_committed_read_mapping (released page, mismatch beside a released page, straddling copy and compare across the 64-byte, 16-byte and byte loops, concurrent decommit), windows_guarded_read_wild_destination, _expected, _outside, windows_backtrace_*, windows_crash_*, agc_driver_guest_memory_lifetime*: 16 of 16 pass. Red controls: with recovery disabled the mapping test segfaults; with the classifier's address and instruction checks removed, windows_guarded_read_wild_expected and _outside fail.

Paired gate on e0caf13600 and 79ee45a6e2 with ANYPS5_REQUIRE_VULKAN=1, ANYPS5_NO_SHADER_CACHE=1, VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation, ctest -R "committed_read_mapping|agc_driver_guest_memory_lifetime" -V: all pass on both, no missing-layer line, no VUID- on either side.

Not tested: Linux (no change there), the non-AVX2 path as the main loop on a host without AVX2, AMD or Intel GPUs locally, Demon's Souls or any title but GTA V, and the unannounced guard path at run time. Overlap: pr_overlap reports shared files only.

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
  • 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 GeForce RTX 3080, driver 621.01, Windows 10.0.26220
  • AI-assisted: yes

🤖 Generated with Claude Code

@github-actions github-actions Bot added the perf Performance change label Nov 1, 2026

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed — changes requested

The performance report is incomplete because the two required capture trace files are not attached to this PR.

What I ran

Reviewed head 63dce0027a2bea23047c800148ab20eaafe74c8c against base f2d874c1fdccf781c0fa5d86619bb5dd8894b958. The stack check found a clean merge preview. Environment: Linux x86_64, Python 3.11.2, GCC 12.2.0. I did not build or compile the Windows changes.

git diff --check f2d874c1fdccf781c0fa5d86619bb5dd8894b958...63dce0027a2bea23047c800148ab20eaafe74c8c
python3 tools/pr_precheck.py --repo boykopovar/AnyPS5 --pr 14799
python3 tools/pr_abi_audit.py --repo /marc/AnyPS5 --base f2d874c1fdccf781c0fa5d86619bb5dd8894b958 --head 63dce0027a2bea23047c800148ab20eaafe74c8c --json
python3 tools/pr_test_quality.py --root /marc/AnyPS5 --json core/libs/prx/libSceAgcDriver/tests/execution/CommittedReadMapping.cpp core/libs/tests/WindowsBacktraceReport.cpp
python3 tools/pr_stack_check.py 14799 --repo boykopovar/AnyPS5

Results

Check Result Note
Patch whitespace passed No diff errors.
Conventions and template passed Local repository check passed.
ABI source audit passed No findings; this is a lexical check only.
Test registration heuristic passed after inspection Heuristic flagged the CMake glob; both test paths are picked up by it.
Merge preview passed Clean against the PR base.
Windows runtime tests not run They require a Windows build and runtime.
Hosted CI not run to completion Required jobs were queued; earlier conventions runs were cancelled.
Performance trace artifacts failed Summary and digest text are present, but the two raw traces are absent.
Unedited local check output

git diff --check:

Conventions:

All conventions checks passed.

Precheck:

/tmp/anyps5-pr-precheck/boykopovar-AnyPS5-pr-14799-63dce0027a2b/report.md
/tmp/anyps5-pr-precheck/boykopovar-AnyPS5-pr-14799-63dce0027a2b/report.json
Conclusion: checks failed

The precheck's two helper launches failed because those local review-helper scripts are not part of the isolated PR checkout; I ran the ABI audit from the main workspace successfully. The test-quality warning was resolved by inspecting the CMake file(GLOB ... tests/execution/*.cpp) registration and the test target.

ABI audit:

{
  "status": "passed",
  "findings": [],
  "limitations": [
    "This lexical audit does not parse C++ fully, prove calling-convention or binary ABI correctness, verify runtime version tables, or replace compilation.",
    "An absent source declaration or explicit alias can be intentional for assembly exports, conditional platform code, or generated interfaces; inspect findings before treating them as defects."
  ]
}

Test-quality heuristic:

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

Stack check:

# PR stack check — fresh

Target: https://github.com/boykopovar/AnyPS5/pull/14799
Target branch tip: `f2d874c1fdccf781c0fa5d86619bb5dd8894b958`
All heads unchanged: **True**
Dependency order: #14799

## Individual merge previews

- PR #14799: **clean** against current base; head `63dce0027a2bea23047c800148ab20eaafe74c8c`; changed paths: none reported

## Dependency relationships

No declared PR dependencies were found in the target PR chain.

## Limits

Merge previews apply each exact PR head independently to the current base. A dependency head that is absent from its dependent is reported separately from merge conflicts; file overlap is only a signal and does not prove a conflict. This tool does not build, resolve conflicts, publish comments, or update branches.

Negative control

Not run. The tests are Windows-specific and their exact-head binaries are unavailable without building.

Findings

Blocking

  • The perf report says the two .json.gz traces “are not attached yet,” and no later PR comment contains them. The PR template requires the baseline and change traces, while the performance report form marks the trace attachments as required. Please attach the exact baseline and candidate traces so the captures and pasted digests can be checked against the reported commits.

Non-blocking

  • None found in the source review. The no-build checks do not establish that the Windows code compiles or that the reported runtime measurements reproduce.

Sources

Not verified

  • Windows compilation and CTest, Linux behavior, console behavior, and independent reproduction of the GPU performance data were not run. The hosted checks were still queued or cancelled at the final check.
  • Negative controls were not run.

To get this to a good state

Attach both capture trace files. I will check that they match the supplied summary lines and rerun the same no-build checks on the updated head.

@chitters2004

chitters2004 commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor Author

Traces and raw files attached:

The trace files carry no commit, so tools/trace_digest.py on a trace alone prints "no summary line found". The commits come from the file names and the aps5-summary.jsonl lines in the description. On these files the digest gives 94 and 106 frame intervals, which fits the 95 and 107 presents in the report.

AI-assisted: yes (Claude Code)

@chitters2004
chitters2004 requested a review from MarcZX10 November 1, 2026 18:33
@github-actions

github-actions Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

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 1835 core/libs/prx/libc/src/GuestArena.cpp
PR 4630 core/libs/prx/libkernel/System/src/Exception.cpp
PR 5021 core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp
core/libs/prx/libc/CMakeLists.txt
core/libs/prx/libc/src/GuestArena.cpp
core/libs/prx/libkernel/System/src/Exception.cpp
PR 6186 core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp
PR 6187 core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp
PR 6188 core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp
PR 6192 core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp
PR 6209 core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp
PR 6273 core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp
PR 6819 core/libs/prx/libc/CMakeLists.txt
PR 7081 core/libs/prx/libc/CMakeLists.txt
PR 7192 core/libs/prx/libc/src/specifics/windows/CrashReport.cpp
core/libs/prx/libkernel/System/src/Exception.cpp
PR 7447 core/libs/prx/libc/CMakeLists.txt
PR 7604 core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp
PR 7642 core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp
PR 7715 core/libs/prx/libc/CMakeLists.txt
PR 8150 core/libs/prx/libc/CMakeLists.txt
PR 8592 core/libs/prx/libkernel/System/src/Exception.cpp
PR 8965 core/libs/prx/libc/CMakeLists.txt
PR 9929 core/libs/prx/libc/CMakeLists.txt
PR 10025 core/libs/prx/libc/include/GuestArena.hpp
core/libs/prx/libc/src/GuestArena.cpp
PR 10193 core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp
PR 11831 core/libs/prx/libc/CMakeLists.txt
PR 12130 core/libs/prx/libkernel/System/src/Exception.cpp
PR 12642 core/libs/prx/libkernel/System/src/Exception.cpp
PR 12682 core/libs/prx/libc/CMakeLists.txt
core/libs/prx/libkernel/System/src/Exception.cpp
PR 12688 core/libs/prx/libc/CMakeLists.txt
core/libs/prx/libkernel/System/src/Exception.cpp
PR 12700 core/libs/prx/libc/CMakeLists.txt
core/libs/prx/libkernel/System/src/Exception.cpp
PR 12921 core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp
PR 12965 core/libs/prx/libc/CMakeLists.txt
core/libs/prx/libkernel/System/src/Exception.cpp
PR 13390 core/libs/prx/libc/CMakeLists.txt
PR 13928 core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp
PR 13929 core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp
PR 14261 core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp
PR 14262 core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp
PR 14585 core/libs/prx/libc/CMakeLists.txt

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-checked — traces verified, CI pending

The new evidence supplies both capture traces and reproducible digests; six macOS jobs remain pending, so I am holding approval.

What I ran

Re-checked the new evidence for unchanged PR head 63dce0027a2bea23047c800148ab20eaafe74c8c against base f2d874c1fdccf781c0fa5d86619bb5dd8894b958. Environment: Linux x86_64, Python 3.11.2; no compiler or build was used. The earlier source review still applies because the PR head is unchanged.

curl -fL --silent --show-error 'https://github.com/user-attachments/files/34245625/aps5-trace-a6111d1f071c-31820.json.gz' -o /tmp/pr14799-baseline.json.gz
curl -fL --silent --show-error 'https://github.com/user-attachments/files/34245642/aps5-trace-ee8448fc2ee5-29424.json.gz' -o /tmp/pr14799-candidate.json.gz
curl -fL --silent --show-error 'https://github.com/user-attachments/files/34245605/pr14799-evidence-v2.zip' -o /tmp/pr14799-evidence-v2.zip
gzip -t /tmp/pr14799-baseline.json.gz /tmp/pr14799-candidate.json.gz
unzip -t /tmp/pr14799-evidence-v2.zip | tail -1
unzip -oq /tmp/pr14799-evidence-v2.zip -d /tmp/pr14799-evidence
sha256sum /tmp/pr14799-baseline.json.gz /tmp/pr14799-evidence/aps5-trace-a6111d1f071c-31820.json.gz /tmp/pr14799-candidate.json.gz /tmp/pr14799-evidence/aps5-trace-ee8448fc2ee5-29424.json.gz
python3 tools/trace_digest.py /tmp/pr14799-evidence/aps5-trace-a6111d1f071c-31820.json.gz --summary /tmp/pr14799-evidence/cap-main.jsonl > /tmp/pr14799-run-main.txt
python3 tools/trace_digest.py /tmp/pr14799-evidence/aps5-trace-ee8448fc2ee5-29424.json.gz --summary /tmp/pr14799-evidence/cap-fix.jsonl > /tmp/pr14799-run-fix.txt
head -2 /tmp/pr14799-run-main.txt
head -2 /tmp/pr14799-run-fix.txt
diff -q --strip-trailing-cr /tmp/pr14799-evidence/digest-M3T-rl5.txt /tmp/pr14799-run-main.txt
diff -q --strip-trailing-cr /tmp/pr14799-evidence/digest-GnT-rl4.txt /tmp/pr14799-run-fix.txt
gh api repos/boykopovar/AnyPS5/pulls/14799 --jq '[.state, .head.sha, .base.sha] | @tsv'
gh pr checks 14799 --repo boykopovar/AnyPS5

Results

Check Result Note
Trace archive integrity passed Both gzip files and the evidence ZIP validate.
Attachment identity passed Downloaded traces match the archive copies by SHA-256.
Digest reproduction passed Both attached digests match local output after CRLF normalization.
Hosted CI not run Six macOS jobs are pending; other reported checks pass; Linux is skipped.
Commands and unedited output

unzip -t /tmp/pr14799-evidence-v2.zip | tail -1

No errors detected in compressed data of /tmp/pr14799-evidence-v2.zip.

sha256sum /tmp/pr14799-baseline.json.gz /tmp/pr14799-evidence/aps5-trace-a6111d1f071c-31820.json.gz /tmp/pr14799-candidate.json.gz /tmp/pr14799-evidence/aps5-trace-ee8448fc2ee5-29424.json.gz

a6c73cb6cc830ac46b051e7c881d19a3ef4c900864487e8463b01cd500ebba68  /tmp/pr14799-baseline.json.gz
a6c73cb6cc830ac46b051e7c881d19a3ef4c900864487e8463b01cd500ebba68  /tmp/pr14799-evidence/aps5-trace-a6111d1f071c-31820.json.gz
a86905ba5d1c8ba304e10b101a00366f511277f10d4c5d4fff64fe1932f7221d  /tmp/pr14799-candidate.json.gz
a86905ba5d1c8ba304e10b101a00366f511277f10d4c5d4fff64fe1932f7221d  /tmp/pr14799-evidence/aps5-trace-ee8448fc2ee5-29424.json.gz

Rerun digest output, baseline and candidate summary lines:

**seconds 240:20** from present 4999: 95 presents, frame p50 206.6 / p90 232.4 / p99 266.7 / max 266.7 ms, GPU busy 44.5 ms per present
NVIDIA GeForce RTX 3080, NVIDIA 621.01, Windows 10.0.26220, 3840x2160, commit a6111d1f071c, dropped: yes
**seconds 240:20** from present 3978: 107 presents, frame p50 183.2 / p90 217.5 / p99 245.0 / max 260.1 ms, GPU busy 43.2 ms per present
NVIDIA GeForce RTX 3080, NVIDIA 621.01, Windows 10.0.26220, 3840x2160, commit ee8448fc2ee5, dropped: yes

diff -q --strip-trailing-cr /tmp/pr14799-evidence/digest-M3T-rl5.txt /tmp/pr14799-run-main.txt

diff -q --strip-trailing-cr /tmp/pr14799-evidence/digest-GnT-rl4.txt /tmp/pr14799-run-fix.txt

Both commands produced no output and exited successfully.

gh api repos/boykopovar/AnyPS5/pulls/14799 --jq '[.state, .head.sha, .base.sha] | @tsv'

open\t63dce0027a2bea23047c800148ab20eaafe74c8c\tf2d874c1fdccf781c0fa5d86619bb5dd8894b958

gh pr checks 14799 --repo boykopovar/AnyPS5

linux\tskipping\t0\thttps://github.com/boykopovar/AnyPS5/actions/runs/41335477469/job/124937763412
report\tpass\t1m7s\thttps://github.com/boykopovar/AnyPS5/actions/runs/41335477343/job/124934280102
labels\tpass\t5s\thttps://github.com/boykopovar/AnyPS5/actions/runs/41335798022/job/124937696259
register-context (ubuntu-latest, Debug)\tpass\t31s\thttps://github.com/boykopovar/AnyPS5/actions/runs/41335477469/job/124937762076
relinker (ubuntu-latest, g++)\tpass\t4m20s\thttps://github.com/boykopovar/AnyPS5/actions/runs/41335477469/job/124937762066
relinker (windows-latest, g++)\tpass\t7m22s\thttps://github.com/boykopovar/AnyPS5/actions/runs/41335477469/job/124937762103
register-context (macos-15-intel, Debug)\tpending\t0\thttps://github.com/boykopovar/AnyPS5/actions/runs/41335477469/job/124937762008
conventions\tpass\t15s\thttps://github.com/boykopovar/AnyPS5/actions/runs/41335798015/job/124935236833
register-context (ubuntu-latest, Release)\tpass\t29s\thttps://github.com/boykopovar/AnyPS5/actions/runs/41335477469/job/124937762092
relinker-asan\tpass\t2m42s\thttps://github.com/boykopovar/AnyPS5/actions/runs/41335477469/job/124937762041
write-watch (macos-15)\tpending\t0\thttps://github.com/boykopovar/AnyPS5/actions/runs/41335477469/job/124937762002
write-watch (macos-15-intel)\tpending\t0\thttps://github.com/boykopovar/AnyPS5/actions/runs/41335477469/job/124937762054
relinker (macos-latest, clang++)\tpending\t0\thttps://github.com/boykopovar/AnyPS5/actions/runs/41335477469/job/124937762110
relinker (macos-latest, clang++, x86_64)\tpending\t0\thttps://github.com/boykopovar/AnyPS5/actions/runs/41335477469/job/124937762061
register-context (macos-15-intel, Release)\tpending\t0\thttps://github.com/boykopovar/AnyPS5/actions/runs/41335477469/job/124937762024
library-portability\tpass\t1m30s\thttps://github.com/boykopovar/AnyPS5/actions/runs/41335477353/job/124934279896
eligibility\tpass\t7s\thttps://github.com/boykopovar/AnyPS5/actions/runs/41335477469/job/124934281661
intake\tpass\t21s\thttps://github.com/boykopovar/AnyPS5/actions/runs/41335477261/job/124934281111
windows\tpass\t8m13s\thttps://github.com/boykopovar/AnyPS5/actions/runs/41335477469/job/124937762065

Negative control

Not applicable to this evidence-only follow-up: the source and tests did not change, and I did not run a build or modify the code under test.

Findings

Blocking

None found in the newly supplied trace and digest evidence. The missing-trace finding from my earlier review is resolved.

Non-blocking

Approval remains pending the six hosted macOS jobs. I did not independently reproduce the performance run on the stated PC or game scene.

Sources

Not verified

The physical PC, title scene, and timing boots were not reproduced here; those remain author-supplied measurements. Six hosted macOS checks are pending. Linux was skipped by CI.

To get this to a good state

No additional trace evidence is needed. Once the pending macOS checks finish, I will re-check the exact head and approve if they pass; if the head changes, I will rerun the same integrity and digest commands on the new evidence.

@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ AMD GPU test: passed

PR head 63dce00 merged onto main f2d874c · tested 2026-11-01 19:02 UTC · 22 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 ✅ 3,068 passed · 15 failed (0 new, 9 also fail on main, 6 unstable on main) · 58 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 3,141 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 (1240 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 121.6 s, ⚠️ agc_driver_graphics_maps_fallback 96.2 s, ⚠️ agc_driver_graphics 91.9 s, ⚠️ agc_driver_bda_device 54.3 s, ⚠️ public_headers 49.7 s
Unstable on main (6, these also failed in recent main runs on this machine; not counted against this PR)
agc_driver_array_layer_target_cpu: failed in 1 of the last 5 main runs
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_driver_submit_progress: 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
Passed on retry (1, failed in the parallel run, passed when re-run with a 360 s timeout; not counted against this PR)
agc_driver_depth_fast_clear_submit: Failed in the parallel run; also passed only on retry in 15 other runs in the last 7 days
Validated but not compared (2, not in the main baseline's validation pass)
guest_job_manager_worker_spin
guest_job_manager_worker_spin_scale_10
Validation IDs already present on main (5 IDs in 715 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (715 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_alias_copy_label, agc_driver_alpha_to_coverage, agc_driver_array_layer_target, and 707 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
VUID-VkShaderModuleCreateInfo-pCode-08737 (1 test): agc_driver_image_sample_derivatives
Skipped (58)
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_copied_writer_label_order_drain: 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_sparse_dma_buf_import: skipped, host imports are unavailable: /dev/udmabuf is not accessible
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_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_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: skipp
Reproduce
git fetch origin 63dce0027a2bea23047c800148ab20eaafe74c8c f2d874c1fdccf781c0fa5d86619bb5dd8894b958
git checkout f2d874c1fdccf781c0fa5d86619bb5dd8894b958 && git merge --no-ff 63dce0027a2bea23047c800148ab20eaafe74c8c
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.

@CnRJay CnRJay left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing a syscall per compare on the committer is the right target, and the recovery is scoped tightly: read faults only, exact source-load RIPs, fault address inside the interval. Three points on cost and coverage that the description does not address.

1. The loops are 16 bytes per iteration. GuardedCopy and GuardedCompare do one movdqu pair, one pcmpeqb/pmovmskb/cmp/jne, one add and one bound check per 16 bytes, with no unrolling and no prefetch. The path they replace was ReadProcessMemory into a staging copy plus the CRT memcmp, which uses AVX2 where available. The GTA V scene is dominated by the syscall, so the net is positive there. For a large compare (a 33–66 MB target, or the 256 MiB swept ranges), a loop at this width can be slower per byte than the old path, and the gain disappears once the syscall is amortized over many pages. Please unroll to 64 bytes per iteration (four independent pcmpeqb results OR-ed or AND-ed before the branch), and show a microbenchmark of GuardedCompare against memcmp for 4 KiB, 256 KiB and 64 MiB. The fault handler needs one more load label per width, which the RIP check already supports.

2. The cost of a hit is not measured. Every compare or copy that contains a released page now takes an access violation, runs the vectored handler, and then does the whole read again through the page-by-page ReadProcessMemory path. That is strictly slower than main for that range, by one exception dispatch (tens of microseconds on Windows) plus the discarded partial read. The test shows correctness with a thread decommitting a page in a loop, but not how often a title hits it. Please add a counter for the fallback after a fault, and report it for the GTA V scene and for a streaming-heavy title, so we know whether a heap that decommits and recommits pages makes this a regression. If the count is not negligible, remember that a range just recovered as released could be skipped for direct reads until its page state changes.

3. OwnedByGuest runs per call. Arena::Get().Contains and OverlapsHostRegion are on the fast path for every compare, and the description does not say whether the second takes a lock or walks a list. With 135k proofs per 10 s on this title (see #12921), please confirm it is lock-free and O(1), or state its cost.

Coverage. The guard-page case: after the first access to a PAGE_GUARD page the OS clears the guard bit and raises STATUS_GUARD_PAGE_VIOLATION. ReadProcessMemory only failed and left the bit set. The description says nothing in core sets a guard on arena memory, which is fine today. But a guest mprotect or stack-growth probe on arena memory would now be consumed by a CPU-side compare and produce an unhandled exception, where main returned a quiet failure. Please state which guest-visible calls can reach a guard bit, or make OwnedByGuest refuse ranges whose state has a guard.

The measurement itself is clear and reproducible. 8 boots at 180.0 vs 161.0 ms with non-overlapping ranges, and the traces are attached.

Every committed copy and compare on Windows went through
ReadProcessMemory, so a page released during the read counts as
uncommitted instead of faulting. Revalidation issues that system call
for each compare, and it dominates the committer thread.

Ranges the guest arena owns are now read by leaf copy and compare
routines. A fault on one of their source loads resumes at a failure
return, and the read falls back to the existing page by page path, so
the result for released pages is unchanged. Host regions and addresses
outside the arena keep ReadProcessMemory.

Hosts with AVX2 take 64 bytes per pass, with 16-byte and byte tails;
others keep the 16-byte loop.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chitters2004
chitters2004 force-pushed the perf/guarded-committed-read branch from 63dce00 to 79ee45a Compare November 1, 2026 21:33
@chitters2004

Copy link
Copy Markdown
Contributor Author

@CnRJay thanks, this was useful. The head is now 79ee45a6e2, rebased on e0caf13600. Full numbers are in the description.

  1. Loop width. I had the wider loop planned as a follow-up PR, and it is now included here. Hosts with AVX2 take 64 bytes per pass, with one more load label per width. Other hosts keep the 16-byte loop. The fair baseline is main's path, ReadProcessMemory into a copy and then memcmp, and the old 16-byte loop already beat it at every size: 32 against 4.7 GB/s at 4 KiB, 36 against 15 at 256 KiB, 20 against 6.8 at 64 MiB. The new loop reaches 68-111, 58-69 and 21-22 at those sizes. At 64 MiB memory speed is the limit. memcpy is faster than our copy at that size only (about 21 against 14 GB/s). I left that alone, because a third routine for it has no evidence behind it yet. Prefetching gave nothing.

  2. Cost of a hit. On this scene a local counter build recorded 0 recovered faults in about 1.44 million guarded reads. The counter is not in this PR. I have no data from a streaming-heavy title, so that case is unmeasured. If one turns up a real rate, your idea of skipping recently recovered ranges is the right next step.

  3. OwnedByGuest. It takes no lock, but it is not O(1). Contains is arithmetic and OverlapsHostRegion walks _hostRegions, which on Windows is only written at startup. It held 80 entries here, 46.6 ns a call in a standalone timing, about 0.03 ms a frame at about 720 calls a frame.

  4. Guards. Stack guards are out of reach. A stack inside the arena bounds at startup is in _hostRegions, later stacks cannot land in the reserved placeholders, and guest threads use _beginthreadex stacks. No non-test code sets PAGE_GUARD, and no guest call reaches one on arena memory. A direct read can only meet one if something sets a raw guard without GuestAllocations after the page state was cached. Refusing guarded ranges per call would need a VirtualQuery, the kind of system call this PR removes. This rests on Windows honouring reservations, and the unannounced guard path was not run.

The earlier main capture had a stray input script tapping during it, so please use the new traces. The result is the same: 178.9 against 159.5 ms over two boots a side.

AI-assisted: yes (Claude Code)

@chitters2004
chitters2004 requested a review from MarcZX10 November 1, 2026 21:35
@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head 79ee45a merged onto main 93dbd0f · tested 2026-11-02 08:50 UTC · 45 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 ✅ 3,080 passed · 7 failed (0 new, 3 also fail on main, 4 unstable on main) · 51 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 3,138 of 3,165 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 (1233 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 120.1 s, ⚠️ agc_driver_bda_device 58.4 s, ⚠️ agc_driver_interpolation_modes 42.2 s, ⚠️ agc_driver_lookup_log_fits_build 41.8 s, ⚠️ agc_driver_image_table 30.1 s
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 (4, these also failed in recent main runs on this machine; not counted against this PR)
agc_driver_depth_clear_hle: failed in 1 of the last 10 main runs
agc_driver_pipeline_journal: failed in 1 of the last 10 main runs
agc_driver_submit_progress: failed in 7 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 715 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (715 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_alias_copy_label, agc_driver_alpha_to_coverage, agc_driver_array_layer_target, and 707 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
VUID-VkShaderModuleCreateInfo-pCode-08737 (1 test): agc_driver_image_sample_derivatives
Skipped (51)
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_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 pla
Reproduce
git fetch origin 79ee45a6e2a60846373a1e03708b26f5214ab35a 93dbd0f82aea684e95f15f06e7d42c0064af18cf
git checkout 93dbd0f82aea684e95f15f06e7d42c0064af18cf && git merge --no-ff 79ee45a6e2a60846373a1e03708b26f5214ab35a
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.

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed — looks good

At head 79ee45a6e2a60846373a1e03708b26f5214ab35a, the Windows guarded-read path, fallback behavior, regression coverage, and attached performance evidence are consistent with the reviewed change.

What I ran

Reviewed all eight changed files against base b2a47847651b0c1281241c5f6da51b4bdf1c83ae. Environment: Debian Linux 6.1, Python 3.11.2, GCC 12.2.0. No local build or CTest was run. Hosted Windows, relinker, sanitizer, register-context, and write-watch checks passed on this head; Linux was skipped. The performance captures and GPU results were supplied by the author.

python3 tools/pr_precheck.py --repo boykopovar/AnyPS5 --pr 14799 --output-dir /tmp/review-14799
git diff --check b2a47847651b0c1281241c5f6da51b4bdf1c83ae...79ee45a6e2a60846373a1e03708b26f5214ab35a
gh pr checks 14799 --repo boykopovar/AnyPS5

Results

Check Result Note
Diff and conventions passed No whitespace or convention errors
Merge preview passed Clean against current main
Windows and relinker CI passed Required Windows and relinker matrix completed
Focused runtime and performance passed Author-provided Windows/GTA V results and matched captures
Local build and CTest not run Not run locally
Linux hosted checks not run Workflow skipped Linux for this PR
Precheck table and relevant raw output
Check Status Note
build_and_compile not_applicable Precheck does not build or compile
diff_check passed git diff --check b2a47847651b0c1281241c5f6da51b4bdf1c83ae...79ee45a6e2a60846373a1e03708b26f5214ab35a
conventions_and_pr_template passed Repository convention and template check
changed_export_abi_audit failed Workspace helper absent from isolated PR snapshot; no public exports changed
Python checks not_applicable No changed Python files
live_dependency_and_mergeability_check passed Current-base merge preview clean
build_dependent_cpp_tests not_applicable Requires a build
test_quality_heuristics failed Workspace helper absent from isolated PR snapshot; test registration inspected directly
negative_controls not_applicable No supported no-build control
All conventions checks passed.

/usr/bin/python3: can't open file '/tmp/review-14799/head-79ee45a6e2a6-26ce0555/tools/pr_abi_audit.py': [Errno 2] No such file or directory
/usr/bin/python3: can't open file '/tmp/review-14799/head-79ee45a6e2a6-26ce0555/tools/pr_test_quality.py': [Errno 2] No such file or directory

The heuristic's suspected missing test registration is a false positive: CommittedReadMapping.cpp is included by the test target, and the changed Windows cases are registered from libc/CMakeLists.txt.

Negative control

Assertion Change to code under test Did the new test fail?
Released pages are zeroed or skipped, while wild destination/expected faults remain fatal Not changed locally Not run locally; author supplied focused test results

Findings

Blocking

None found in the reviewed diff.

Non-blocking

  • Both attached traces report dropped detailed events, while their summary totals are marked complete. The author also provides repeated timing boots; this limits trace-level diagnosis but does not invalidate the reported summary measurements.
  • Linux was skipped, and I did not run a local build or CTest.

Sources

Not verified

  • I did not independently reproduce Windows runtime tests, the GTA V measurements, or GPU behavior.
  • Linux CI was skipped; no physical console test was run.

To get this to a good state

No changes are required from this review. The Windows and relinker checks passed; Linux coverage remains unverified here.

@JJenkx

JJenkx commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

Windows check of exact head 79ee45a6e2 (base e0caf13600) on an AMD Zen 3 CPU, which takes the AVX2 copy and compare path.

Setup: Windows 11 Enterprise 10.0.22621, Ryzen 9 5950X (AVX2), Radeon RX 6700 XT, AMD proprietary driver 26.10.1, WinLibs GCC 15.2.0 UCRT r7, Release. The full CTest suite ran once through the shared GPU queue with VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation, ANYPS5_NO_SHADER_CACHE=1 and ANYPS5_REQUIRE_VULKAN=1.

  • 3,288 tests: 3,241 pass and 19 skip. The validation layer was inserted 1,099 times.
  • The 28 failures are exactly the set main 0cc3899f69 fails on this machine: 26 video_out_flip_* that need a display (it was off), agc_driver_sample_order_grid_reference (fix(agc): bind the sample order depth set after its pipeline #9503) and ngs2_pitchshift (fix(libSceNgs2): compute the PitchShift ratio with libc's msun exp2f #12864). The PR adds no failure.
  • The VUIDs are the same three main reports here. None comes from the tests this PR touches.
  • The changed and nearby tests pass, including:
    • agc_driver_committed_read_mapping and the agc_driver_guest_memory_lifetime* set;
    • windows_backtrace_report, windows_backtrace_failure_report, windows_backtrace_failure_report_once, windows_crash_stack_words and windows_crash_without_stack_words;
    • windows_crash_text, undeliverable_host_exception, windows_write_watch and windows_write_watch_verify_direct.

No performance measurement here: my display was off, so no title ran.

🤖 Generated with Claude Code

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

Labels

agc libSceAgc* build libc libkernel perf Performance change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants