Skip to content

perf(agc): run reads copy the missing blocks of a page mapped whole at once - #6471

Merged
adriadam10 merged 1 commit into
boykopovar:mainfrom
SleglJan:pr/readwords-lazy-blocks
Oct 19, 2026
Merged

adriadam10 merged 1 commit into
boykopovar:mainfrom
SleglJan:pr/readwords-lazy-blocks

Conversation

@SleglJan

@SleglJan SleglJan commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

What

ShaderMemory::readWords copied a run straight from its page only once every word of the page was valid. A page mapped whole (lazy) fills its 16-word blocks on first use and starts empty in every draw (one ShaderMemory per draw). So a run over it went through read() one word at a time, each word paying for:

  • the initial-region lookup (std::prev on the initial map);
  • the page lookup;
  • a block test.

Image-table columns are read this way on every capture.

readWords now copies the run's missing blocks of such a page with one memcpy per run of blocks. It then serves the words from the page and marks them read and recent, as the path for a fully valid page does.

  • The bytes, the blocks copied and the regions reported are those of the word-by-word path.
  • Pages read word by word (pending GPU writes, or mapped only in part) and the initial regions keep that path.

Before the change, in the scene under Tested (build A, which carries the column memo of #6440):

  • [capture] counted about 134k word reads per capture and a walk of 495 µs per capture. Of 6.15M pages fetched, 228 were read word by word.
  • On the draw worker (perf record -e cycles:u, 5 s), ShaderMemory::read took 1,007 of 2,604 samples per frame, ShaderMemory::page 133 and std::_Rb_tree_decrement 200.
  • A call-graph profile places read under readWords ← TableSnapshotter::Column.
  • With the change (build B), the worker takes 1,271 samples per frame: read 21, page 18, _Rb_tree_decrement 0.

Tested

Linux 7.2.10 (CachyOS), RTX 3080 with NVIDIA 615.78.08, Ryzen 9 7950X3D, GCC 16.2.1, Release.

  • ctest -R '^agc' on main 92e5041 with this change: 594 tests, 1 failure, 1 skip.
  • verifyImageTableBulkReads gains a table placed inside 16-word blocks. Through ShaderMemory it must give the same snapshot as the word-by-word reader, and the captured regions must be exactly its records. There is no behaviour change for a test to observe, so the check guards the equivalence; it also passes with main's ShaderMemory sources.
  • 007 First Light's menu, measured on frames 215-255 with the shader cache warm.
    • The scene needs local changes that are not on main, so every build carries them; B and D add only this commit to A and C.
    • A and B also carry the image-table column memo of perf(shader): reuse an image table column's records while its words are unchanged #6440. Its column reads go through readWords as well.
    • Each series alternated ABBAAB. The [capture] and [image-table] lines are from one extra pair per configuration with APS5_PROFILE_DRAW=1.
    • Every run had 0 guest faults.
  • With the memo, A without this change, B with it:
    • menu rate median 1.290 (1.307, 1.265, 1.290) → 2.185 (2.195, 1.843, 2.185); the profiled pair 1.233 → 2.158;
    • frame p50 774/793/781 → 455/450/462 ms; GPU busy 157-161 ms per present in both;
    • [capture] per capture: walk 494.6 → 131.9 µs, materialize 623.5 → 257.9 µs;
    • [image-table] per 10 s: 9,166 → 15,809 snapshots, 5.88 → 2.53 s (0.64 → 0.16 ms each).
    • B2 holds one 3,307 ms frame, which lowers its rate.
      • In it, five compute dispatches' descriptor builds took 139-640 ms (Resources.Complete, which reads no shader memory), and the other queue workers waited 3.1-3.25 s on guest memory.
      • None of the other 19 traced runs of these builds has a Resources.Complete over 70 ms.
  • Without the memo, C without this change, D with it:
    • menu rate median 0.688 (0.732, 0.684, 0.688) → 0.938 (0.883, 0.947, 0.938); the profiled pair 0.722 → 0.923;
    • frame p50 1374/1457/1458 → 1140/1062/1063 ms; GPU busy 153-161 ms per present in both;
    • [capture] per capture: walk 1178.5 → 801.1 µs, materialize 1309.6 → 936.2 µs;
    • draw worker samples per frame 5,298 → 3,864 (ShaderMemory::read 956 → 24);
    • [image-table] per 10 s: 5,179 → 6,807 snapshots, 7.66 → 7.01 s (1.48 → 1.03 ms each).
  • Attached in https://github.com/SleglJan/AnyPS5/releases/tag/perf-traces-readwords-lazy-blocks:
    • the traces A1-D3 (APS5_TRACE_FRAMES=200:40, no other switches);
    • their summary lines, one file in that order.
Summary lines A1-A3, B1-B3, C1-C3, D1-D3
{"commit":"699643f682cc","dirty":false,"env":{"APS5_TRACE_DIR":"<path>","APS5_TRACE_FRAMES":"200:40"},"gpu":"NVIDIA GeForce RTX 3080","driver":"NVIDIA 615.78.08","os":"Linux 7.2.10-1-cachyos","resolution":"3840x2160","window":{"spec":"frames 200:40","first_present":200,"ms":30715.216},"presents":40,"frame_ms":{"p50":773.566,"p90":790.559,"p99":815.017,"max":815.017},"gpu_busy_ms_per_present":160.61,"worker_busy_pct":{"queue worker 0x0":99.952,"queue worker 0x20":97.722,"queue worker 0x28":98.825,"queue worker 0x38":97.928,"queue worker 0x30":98.826},"top_phases_ms_per_frame":{"Driver.Packet":3781.916,"Driver.Packet.memory_wait":2827.553,"Driver.Packet.draw":668.275,"Driver.Draw":668.149,"Driver.Draw.shader_compile_and_link":634.844,"Shader.DrawStage":625.965,"Shader.DrawStage.capture_resources":497.583,"Driver.Packet.dispatch":276.778},"trace_dropped":false,"trace":"aps5-trace-699643f682cc-2.json.gz"}
{"commit":"699643f682cc","dirty":false,"env":{"APS5_TRACE_DIR":"<path>","APS5_TRACE_FRAMES":"200:40"},"gpu":"NVIDIA GeForce RTX 3080","driver":"NVIDIA 615.78.08","os":"Linux 7.2.10-1-cachyos","resolution":"3840x2160","window":{"spec":"frames 200:40","first_present":200,"ms":31826.763},"presents":40,"frame_ms":{"p50":792.927,"p90":828.756,"p99":838.09,"max":838.09},"gpu_busy_ms_per_present":157.366,"worker_busy_pct":{"queue worker 0x0":99.955,"queue worker 0x20":97.654,"queue worker 0x28":98.885,"queue worker 0x38":97.873,"queue worker 0x30":98.879},"top_phases_ms_per_frame":{"Driver.Packet":3918.927,"Driver.Packet.memory_wait":2917.908,"Driver.Packet.draw":688.67,"Driver.Draw":688.531,"Driver.Draw.shader_compile_and_link":660.452,"Shader.DrawStage":650.529,"Shader.DrawStage.capture_resources":512.707,"Driver.Packet.dispatch":303.639},"trace_dropped":false,"trace":"aps5-trace-699643f682cc-2.json.gz"}
{"commit":"699643f682cc","dirty":false,"env":{"APS5_TRACE_DIR":"<path>","APS5_TRACE_FRAMES":"200:40"},"gpu":"NVIDIA GeForce RTX 3080","driver":"NVIDIA 615.78.08","os":"Linux 7.2.10-1-cachyos","resolution":"3840x2160","window":{"spec":"frames 200:40","first_present":200,"ms":31288.231},"presents":40,"frame_ms":{"p50":780.634,"p90":806.104,"p99":827.955,"max":827.955},"gpu_busy_ms_per_present":160.534,"worker_busy_pct":{"queue worker 0x0":99.955,"queue worker 0x20":97.783,"queue worker 0x28":98.874,"queue worker 0x30":98.868,"queue worker 0x38":97.78},"top_phases_ms_per_frame":{"Driver.Packet":3855.212,"Driver.Packet.memory_wait":2878.872,"Driver.Packet.draw":686.073,"Driver.Draw":685.945,"Driver.Draw.shader_compile_and_link":650.014,"Shader.DrawStage":639.985,"Shader.DrawStage.capture_resources":505.957,"Driver.Packet.dispatch":282.301},"trace_dropped":false,"trace":"aps5-trace-699643f682cc-2.json.gz"}
{"commit":"04921851829d","dirty":false,"env":{"APS5_TRACE_DIR":"<path>","APS5_TRACE_FRAMES":"200:40"},"gpu":"NVIDIA GeForce RTX 3080","driver":"NVIDIA 615.78.08","os":"Linux 7.2.10-1-cachyos","resolution":"3840x2160","window":{"spec":"frames 200:40","first_present":200,"ms":18286.47},"presents":40,"frame_ms":{"p50":454.78,"p90":487.992,"p99":497.29,"max":497.29},"gpu_busy_ms_per_present":155.985,"worker_busy_pct":{"queue worker 0x0":99.925,"queue worker 0x20":98.217,"queue worker 0x28":98.815,"queue worker 0x30":98.807,"queue worker 0x38":98.228},"top_phases_ms_per_frame":{"Driver.Packet":2255.083,"Driver.Packet.memory_wait":1606.381,"Driver.Packet.draw":366.017,"Driver.Draw":365.893,"Driver.Draw.shader_compile_and_link":329.284,"Shader.DrawStage":313.629,"Driver.Packet.dispatch":275.791,"Driver.Dispatch":254.291},"trace_dropped":false,"trace":"aps5-trace-04921851829d-2.json.gz"}
{"commit":"04921851829d","dirty":false,"env":{"APS5_TRACE_DIR":"<path>","APS5_TRACE_FRAMES":"200:40"},"gpu":"NVIDIA GeForce RTX 3080","driver":"NVIDIA 615.78.08","os":"Linux 7.2.10-1-cachyos","resolution":"3840x2160","window":{"spec":"frames 200:40","first_present":200,"ms":21522.381},"presents":40,"frame_ms":{"p50":449.645,"p90":481.417,"p99":3307.154,"max":3307.154},"gpu_busy_ms_per_present":161.258,"worker_busy_pct":{"queue worker 0x0":99.938,"queue worker 0x20":98.243,"queue worker 0x28":99.064,"queue worker 0x30":99.057,"queue worker 0x38":98.244},"top_phases_ms_per_frame":{"Driver.Packet":2657.081,"Driver.Packet.memory_wait":1931.175,"Driver.Packet.draw":371.465,"Driver.Draw":371.341,"Driver.Packet.dispatch":347.149,"Driver.Draw.shader_compile_and_link":326.952,"Driver.Dispatch":314.605,"Shader.DrawStage":310.179},"trace_dropped":false,"trace":"aps5-trace-04921851829d-2.json.gz"}
{"commit":"04921851829d","dirty":false,"env":{"APS5_TRACE_DIR":"<path>","APS5_TRACE_FRAMES":"200:40"},"gpu":"NVIDIA GeForce RTX 3080","driver":"NVIDIA 615.78.08","os":"Linux 7.2.10-1-cachyos","resolution":"3840x2160","window":{"spec":"frames 200:40","first_present":200,"ms":18368.734},"presents":40,"frame_ms":{"p50":462.238,"p90":472.933,"p99":483.603,"max":483.603},"gpu_busy_ms_per_present":158.99,"worker_busy_pct":{"queue worker 0x0":99.927,"queue worker 0x20":97.598,"queue worker 0x28":98.456,"queue worker 0x38":97.849,"queue worker 0x30":98.451},"top_phases_ms_per_frame":{"Driver.Packet":2254.177,"Driver.Packet.memory_wait":1613.203,"Driver.Packet.draw":361.937,"Driver.Draw":361.814,"Driver.Draw.shader_compile_and_link":323.492,"Shader.DrawStage":314.649,"Driver.Packet.dispatch":273.196,"Driver.Dispatch":247.944},"trace_dropped":false,"trace":"aps5-trace-04921851829d-2.json.gz"}
{"commit":"17b7e9e8b233","dirty":false,"env":{"APS5_TRACE_DIR":"<path>","APS5_TRACE_FRAMES":"200:40"},"gpu":"NVIDIA GeForce RTX 3080","driver":"NVIDIA 615.78.08","os":"Linux 7.2.10-1-cachyos","resolution":"3840x2160","window":{"spec":"frames 200:40","first_present":200,"ms":55054.02},"presents":40,"frame_ms":{"p50":1373.683,"p90":1401.706,"p99":1431.62,"max":1431.62},"gpu_busy_ms_per_present":160.967,"worker_busy_pct":{"queue worker 0x0":99.973,"queue worker 0x20":97.678,"queue worker 0x28":98.752,"queue worker 0x38":97.679,"queue worker 0x30":98.753},"top_phases_ms_per_frame":{"Driver.Packet":6780.146,"Driver.Packet.memory_wait":5210.606,"Driver.Packet.draw":1268.792,"Driver.Draw":1268.652,"Driver.Draw.shader_compile_and_link":1244.293,"Shader.DrawStage":1234.749,"Shader.DrawStage.capture_resources":1105.682,"Driver.Packet.dispatch":291.876},"trace_dropped":false,"trace":"aps5-trace-17b7e9e8b233-2.json.gz"}
{"commit":"17b7e9e8b233","dirty":false,"env":{"APS5_TRACE_DIR":"<path>","APS5_TRACE_FRAMES":"200:40"},"gpu":"NVIDIA GeForce RTX 3080","driver":"NVIDIA 615.78.08","os":"Linux 7.2.10-1-cachyos","resolution":"3840x2160","window":{"spec":"frames 200:40","first_present":200,"ms":58429.823},"presents":40,"frame_ms":{"p50":1457.0,"p90":1490.7,"p99":1495.921,"max":1495.921},"gpu_busy_ms_per_present":160.668,"worker_busy_pct":{"queue worker 0x0":99.974,"queue worker 0x20":97.629,"queue worker 0x28":98.737,"queue worker 0x30":98.736,"queue worker 0x38":97.738},"top_phases_ms_per_frame":{"Driver.Packet":7195.855,"Driver.Packet.memory_wait":5537.931,"Driver.Packet.draw":1349.796,"Driver.Draw":1349.66,"Driver.Draw.shader_compile_and_link":1328.003,"Shader.DrawStage":1317.746,"Shader.DrawStage.capture_resources":1185.973,"Driver.Packet.dispatch":299.453},"trace_dropped":false,"trace":"aps5-trace-17b7e9e8b233-2.json.gz"}
{"commit":"17b7e9e8b233","dirty":false,"env":{"APS5_TRACE_DIR":"<path>","APS5_TRACE_FRAMES":"200:40"},"gpu":"NVIDIA GeForce RTX 3080","driver":"NVIDIA 615.78.08","os":"Linux 7.2.10-1-cachyos","resolution":"3840x2160","window":{"spec":"frames 200:40","first_present":200,"ms":58201.922},"presents":40,"frame_ms":{"p50":1458.159,"p90":1495.939,"p99":1504.213,"max":1504.213},"gpu_busy_ms_per_present":155.705,"worker_busy_pct":{"queue worker 0x0":99.975,"queue worker 0x20":97.68,"queue worker 0x38":97.681,"queue worker 0x30":98.733,"queue worker 0x28":98.729},"top_phases_ms_per_frame":{"Driver.Packet":7166.418,"Driver.Packet.memory_wait":5513.609,"Driver.Packet.draw":1347.506,"Driver.Draw":1347.351,"Driver.Draw.shader_compile_and_link":1325.933,"Shader.DrawStage":1313.879,"Shader.DrawStage.capture_resources":1182.471,"Driver.Packet.dispatch":298.805},"trace_dropped":false,"trace":"aps5-trace-17b7e9e8b233-2.json.gz"}
{"commit":"fd743b4f83c7","dirty":false,"env":{"APS5_TRACE_DIR":"<path>","APS5_TRACE_FRAMES":"200:40"},"gpu":"NVIDIA GeForce RTX 3080","driver":"NVIDIA 615.78.08","os":"Linux 7.2.10-1-cachyos","resolution":"3840x2160","window":{"spec":"frames 200:40","first_present":200,"ms":45631.223},"presents":40,"frame_ms":{"p50":1139.709,"p90":1172.662,"p99":1187.707,"max":1187.707},"gpu_busy_ms_per_present":153.983,"worker_busy_pct":{"queue worker 0x0":99.966,"queue worker 0x20":97.672,"queue worker 0x38":97.68,"queue worker 0x30":98.691,"queue worker 0x28":98.69},"top_phases_ms_per_frame":{"Driver.Packet":5617.915,"Driver.Packet.memory_wait":4265.127,"Driver.Packet.draw":1031.081,"Driver.Draw":1030.937,"Driver.Draw.shader_compile_and_link":1008.48,"Shader.DrawStage":997.948,"Shader.DrawStage.capture_resources":865.85,"Driver.Packet.dispatch":313.05},"trace_dropped":false,"trace":"aps5-trace-fd743b4f83c7-2.json.gz"}
{"commit":"fd743b4f83c7","dirty":false,"env":{"APS5_TRACE_DIR":"<path>","APS5_TRACE_FRAMES":"200:40"},"gpu":"NVIDIA GeForce RTX 3080","driver":"NVIDIA 615.78.08","os":"Linux 7.2.10-1-cachyos","resolution":"3840x2160","window":{"spec":"frames 200:40","first_present":200,"ms":42597.158},"presents":40,"frame_ms":{"p50":1062.113,"p90":1091.12,"p99":1109.578,"max":1109.578},"gpu_busy_ms_per_present":156.482,"worker_busy_pct":{"queue worker 0x0":99.965,"queue worker 0x20":97.648,"queue worker 0x28":98.666,"queue worker 0x38":97.79,"queue worker 0x30":98.667},"top_phases_ms_per_frame":{"Driver.Packet":5245.046,"Driver.Packet.memory_wait":3983.099,"Driver.Packet.draw":961.877,"Driver.Draw":961.746,"Driver.Draw.shader_compile_and_link":935.336,"Shader.DrawStage":922.906,"Shader.DrawStage.capture_resources":790.316,"Driver.Packet.dispatch":292.498},"trace_dropped":false,"trace":"aps5-trace-fd743b4f83c7-2.json.gz"}
{"commit":"fd743b4f83c7","dirty":false,"env":{"APS5_TRACE_DIR":"<path>","APS5_TRACE_FRAMES":"200:40"},"gpu":"NVIDIA GeForce RTX 3080","driver":"NVIDIA 615.78.08","os":"Linux 7.2.10-1-cachyos","resolution":"3840x2160","window":{"spec":"frames 200:40","first_present":200,"ms":42613.389},"presents":40,"frame_ms":{"p50":1063.404,"p90":1087.422,"p99":1124.034,"max":1124.034},"gpu_busy_ms_per_present":152.755,"worker_busy_pct":{"queue worker 0x0":99.965,"queue worker 0x20":97.736,"queue worker 0x28":98.69,"queue worker 0x38":97.835,"queue worker 0x30":98.691},"top_phases_ms_per_frame":{"Driver.Packet":5244.131,"Driver.Packet.memory_wait":3974.01,"Driver.Packet.draw":965.468,"Driver.Draw":965.325,"Driver.Draw.shader_compile_and_link":940.585,"Shader.DrawStage":926.701,"Shader.DrawStage.capture_resources":794.969,"Driver.Packet.dispatch":296.28},"trace_dropped":false,"trace":"aps5-trace-fd743b4f83c7-2.json.gz"}
  • Independent check by XairRrR on another title, Uncharted: Legacy of Thieves Collection (PPSA05684). Linux, RTX 4070 Ti SUPER, NVIDIA 615.78.08, i9-14900KF, main 2eb0c2b27 plus open PRs and local commits, with this head (726ef5f) the only difference between the two runs. Last 15 [image-table] lines (150 s) of APS5_PROFILE_DRAW=1 in a heavy scene, with the same workload in both runs (6,159 and 6,177 keys per snapshot):
    • snapshots per 10 s: 953 → 1,030;
    • ms per snapshot: 3.58 → 1.96;
    • image-table ms per 10 s: 3,408 → 2,022.
    • In his profile before the change (perf record -t, 25 s), ShaderMemory::read took 6-13 % self time, under readWords ← TableSnapshotter::Narrow, with key buffers of up to 262,144 positions per scan (APS5_IMAGE_TABLE_KEY_SCAN=262144; the default is 256).
    • The frame rate stayed within run-to-run noise (1.6-1.9 fps); he notes the queue threads there are bound by other work. ctest -R 'shader_memory|ShaderMemory|image_table' passes on that tree: perf(agc): run reads copy the missing blocks of a page mapped whole at once #6471 (comment)

Related

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; none added
  • Unimplemented paths throw; no stubs
  • No notes, investigation .md files or images added to the repository
  • New third-party code is a submodule built from source: n/a
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Unblocks: none
  • GPUs tested: NVIDIA GeForce RTX 3080, driver 615.78.08, Linux 7.2.10 (CachyOS)
  • AI-assisted: yes (Claude Code)

🤖 Generated with Claude Code

…t once

ShaderMemory::readWords copied a run straight from its page only once every word of the page was
valid. A page mapped whole fills its 16-word blocks on first use, so a run over a fresh page went
through read() one word at a time: the initial-region lookup, the page lookup and a block test
per word. Image-table columns are read this way on every capture.

readWords now copies the run's missing blocks of such a page with one memcpy per run of blocks
and serves the words from the page, marking them read and recent as before. The bytes, the blocks
copied and the regions reported are those of the word-by-word path. Pages read word by word
(pending GPU writes, partly mapped) and the initial regions keep that path.

In 007 First Light's menu the capture walk takes 801 instead of 1,179 us per capture, and 132
instead of 495 us with the image-table column memo.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 15, 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 1341 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 5371 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 5500 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 6177 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 6188 core/libs/prx/libSceAgcDriver/Execution/src/ShaderMemory.cpp
PR 6235 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 6488 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 6612 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 6645 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 6941 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 6946 core/libs/prx/libSceAgcDriver/Execution/src/ShaderMemory.cpp
PR 6947 core/libs/prx/libSceAgcDriver/Execution/src/ShaderMemory.cpp
core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 7332 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 7388 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 7642 core/libs/prx/libSceAgcDriver/Execution/src/ShaderMemory.cpp
core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp

@XairRrR

XairRrR commented Oct 16, 2026

Copy link
Copy Markdown
Contributor

Tested this head (726ef5f) on another title: Uncharted: Legacy of Thieves Collection (PPSA05684, #4001), Linux, RTX 4070 Ti SUPER, NVIDIA 615.78.08, i9-14900KF. Build: main 2eb0c2b27 + a few open PRs and local commits, with this PR applied as the only change between the two runs below.

Scene: the orphanage (Chapter 2), heavy phase ~8 min after loading. Numbers are the [image-table] lines of APS5_PROFILE_DRAW=1, last 15 lines (150 s) of each run; both runs have the same workload (6159 / 6177 keys per snapshot).

build snapshots per 10 s ms per snapshot image-table ms per 10 s
without this PR 953 3.58 3408
with this PR 1030 1.96 2022

A profile of the driver threads before the change (perf record -t, 25 s) matches your description: ShaderMemory::read was 6-13 % self time, reached from readWords under TableSnapshotter::Narrow, whose key buffers here hold up to 262144 positions per scan (APS5_IMAGE_TABLE_KEY_SCAN=262144). I had written the same change locally (copy a lazy page's missing blocks once, then serve the run with one memcpy) and it measured the same, so I'm dropping mine in favour of this PR. The frame rate of that scene moves within its run-to-run noise (1.6-1.9 fps); the queue threads there are bound by other work.

ctest -R 'shader_memory|ShaderMemory|image_table' passes on that tree, including your verifyImageTableBulkReads case.

AI-assisted: yes

@SleglJan

Copy link
Copy Markdown
Contributor Author

Thanks @XairRrR for the second title and the A/B with this head as the only difference, and for dropping your local copy of the same change. Your numbers are added under Tested.

AI-assisted: yes (Claude Code)

@github-actions github-actions Bot added the perf Performance change label Oct 18, 2026
@adriadam10 adriadam10 self-assigned this Oct 19, 2026
@adriadam10
adriadam10 merged commit c7892bf into boykopovar:main Oct 19, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agc libSceAgc* perf Performance change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants