Skip to content

perf(libSceAgcDriver): bypass the draw cache while its hit rate is under 5% - #5407

Closed
bcortezf wants to merge 1 commit into
boykopovar:mainfrom
bcortezf:perf/draw-cache-adaptive-bypass-main
Closed

bcortezf wants to merge 1 commit into
boykopovar:mainfrom
bcortezf:perf/draw-cache-adaptive-bypass-main

Conversation

@bcortezf

Copy link
Copy Markdown

What

The draw cache (APS5_DRAW_CACHE_ENTRIES, 4096 entries) misses on almost every draw in scenes whose user-data words change every frame: in Red Dead Redemption gameplay it hits 0 to 6% of 120k to 130k lookups per 10 s and spends the time inserting and evicting entries (131k inserts and 300k to 730k evictions per 10 s).

Count the lookups in windows of 2,048. When fewer than 5% of a window hit, draws skip the cache (no register key, no lookup, no insert, the same path as APS5_NO_DRAW_SRT_ENTRIES) for the next 16,384 draws, then the cache is probed again. Scenes that hit (menus and cutscenes, 98 to 100%) are not bypassed. APS5_NO_DRAW_CACHE_BYPASS=1 restores the previous behaviour, and [draw-cache] bypassed N draws is printed with APS5_PROFILE_DRAW.

Related: #5345 (report), #5364 (miss breakdown; independent, may need a rebase in Draw.cpp).

Tested

Windows 11, RTX 4070 SUPER (driver 616.64), Ryzen 7 7800X3D, 3840x2160. PPSA30528, Armadillo after the intro, APS5_TRACE_SECONDS=100:5, caches warm, same session. The base is APS5_NO_DRAW_CACHE_BYPASS=1 on the same binary.

frame p50 FPS
bypass off (main behaviour) 392 ms 2.55
bypass on 362 ms 2.76

Two earlier rounds on the same machine: 2.63 / 2.61 FPS off, 2.80 / 2.83 FPS on. The queue worker stays at 98.8% busy; the gain is per-draw cost, not a different bottleneck. trace_dropped is true in these captures (the worker buffer fills within 5 s).

Summary lines (off, then on):

{"commit": "981acf21ed70", "dirty": true, "env": {"APS5_NO_DRAW_CACHE_BYPASS": "1", "APS5_PAD_INPUT_FILE": "<path>", "APS5_TRACE_SECONDS": "100:5"}, "gpu": "NVIDIA GeForce RTX 4070 SUPER", "driver": "NVIDIA 616.64", "os": "Windows 10.0.26200", "resolution": "3840x2160", "window": {"spec": "seconds 100:5", "first_present": 1791, "ms": 5097.913}, "presents": 13, "frame_ms": {"p50": 392.154, "p90": 406.612, "p99": 413.368, "max": 413.368}, "gpu_busy_ms_per_present": 133.99, "worker_busy_pct": {"queue worker 0x0": 98.886}, "top_phases_ms_per_frame": {"Driver.Packet": 387.509, "Driver.Packet.draw": 360.408, "Driver.Draw": 358.815, "Driver.Draw.draw_and_resource_release": 181.247, "Graphics.Draw": 179.59, "Graphics.Draw.draw_and_resource_release": 154.663, "Driver.Draw.shader_compile_and_link": 126.894, "Shader.DrawStage": 95.646}, "trace_dropped": true, "trace": "aps5-trace-981acf21ed70-20260.json.gz"}
{"commit": "981acf21ed70", "dirty": true, "env": {"APS5_PAD_INPUT_FILE": "<path>", "APS5_TRACE_SECONDS": "100:5"}, "gpu": "NVIDIA GeForce RTX 4070 SUPER", "driver": "NVIDIA 616.64", "os": "Windows 10.0.26200", "resolution": "3840x2160", "window": {"spec": "seconds 100:5", "first_present": 1673, "ms": 5053.279}, "presents": 14, "frame_ms": {"p50": 362.483, "p90": 371.102, "p99": 373.611, "max": 373.611}, "gpu_busy_ms_per_present": 145.365, "worker_busy_pct": {"queue worker 0x0": 98.813}, "top_phases_ms_per_frame": {"Driver.Packet": 356.413, "Driver.Packet.draw": 329.475, "Driver.Draw": 327.91, "Driver.Draw.draw_and_resource_release": 174.267, "Graphics.Draw": 172.722, "Graphics.Draw.draw_and_resource_release": 148.854, "Driver.Draw.shader_compile_and_link": 106.221, "Shader.DrawStage": 91.167}, "trace_dropped": true, "trace": "aps5-trace-981acf21ed70-6036.json.gz"}

python3 tools/check_conventions.py --base origin/main: passed. Not built or run on Linux or macOS.

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; no silent stubs
  • No notes, investigation .md files or images added to the repository
  • No new third-party code
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Unblocks: none
  • AI-assisted: yes

…der 5%

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

github-actions Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.

Pull request Conflicting files (lines on main) Same exports Same new files
#5431 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/Draw.cpp L172

@github-actions github-actions Bot added the agc libSceAgc* label Oct 13, 2026
@mrfelek

mrfelek commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

Data point from another title: Diablo II: Resurrected (PPSA03912, 01.039.000), Linux, RTX 3080 Ti (NVIDIA 615.71.09), in game in the Rogue Encampment.

Without this PR the draw cache almost never hits there: [draw-cache] 46087 lookups (10 s): 46044 no entry, 43 validated, and 53897 lookups: 53845 no entry, 52 validated in the next window (about 0.1%). The queue worker is pinned at about 90% of a core.

With this PR (merged on top of #5216 and #4947 on main of 2026-10-13, so the effect of this one alone is not isolated) the bypass fires from the first window (bypassed 16384 draws, then 65536 and 81920 per 10 s), no abort. The window-title FPS in the same area went from about 2.4 to about 3.6 on average (readings 4.4, 5.6, 4.4, 2.2, 0.2, 4.9). That is noisy: memory is near full and the run swaps, and the scene differed between the two runs, so treat it as a direction and not a measurement. The queue worker is still at about 79% of a core, so the per-draw evaluation and descriptor work is the remaining cost.

AI-assisted; the runs are from my machine.

@bcortezf

Copy link
Copy Markdown
Author

Closing: #5216 merged and covers this problem with per-key admission instead of a global bypass; it measured at least as well on my RDR runs (isolated and on top of #494). Thanks @mrfelek for the Diablo II data.

@bcortezf bcortezf closed this Oct 13, 2026
@oneandonlydean oneandonlydean self-assigned this Oct 13, 2026
@JAB-dev

JAB-dev commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

Besiege (PPSA20313), main at a0f5916 against main plus this commit, Windows 11, RTX 4070 SUPER, 1080p, three runs each:

  • 17.0, 16.9, 16.7 FPS -> 17.8, 17.7, 17.0 FPS (+4%)
  • median frame time 57.8 ms -> 55.3 ms

On this title the draw cache hits 2.5% of its lookups (about 80,000 lookups in 10 s, 95% with no entry), so it is exactly the case the bypass targets.

@bcortezf bcortezf reopened this Oct 22, 2026
@github-actions github-actions Bot added perf Performance change perf numbers missing perf pull request without a before and after summary line labels Oct 22, 2026
@github-actions

Copy link
Copy Markdown

This pull request is labeled perf, so it needs the summary line of a capture on main and one with the change, from the same title, scene and machine, as the Performance report form asks. Please paste both aps5-summary.jsonl lines, attach the two traces and add the output of tools/trace_digest.py.

@github-actions github-actions Bot added the open PR limit Closed over the open PR limit: 1 without merged PRs, 20 with at least 1, none from 20 label Oct 22, 2026
@github-actions

Copy link
Copy Markdown

Thank you for your contribution! Authors with no pull requests merged into main can have 1 open pull request at a time, authors with at least 1 merged can have 20, and from 20 merged there is no limit. This PR has been automatically closed and labeled "open PR limit" because that limit was reached. This is not a judgment of the quality of your changes: reopen it once one of your open pull requests is merged or closed.

@github-actions github-actions Bot closed this Oct 22, 2026
@bcortezf

Copy link
Copy Markdown
Author

@oneandonlydean can you re-open this? since @JAB-dev perf analysis, i'm going to update this PR and do another perf run. to check performance on RDR1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agc libSceAgc* open PR limit Closed over the open PR limit: 1 without merged PRs, 20 with at least 1, none from 20 perf numbers missing perf pull request without a before and after summary line perf Performance change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants