Skip to content

perf(agc): rule out pending write overlaps from the published union - #6609

Merged
adriadam10 merged 1 commit into
boykopovar:mainfrom
meh7an:perf/agc-pending-writes-published-union
Oct 19, 2026
Merged

adriadam10 merged 1 commit into
boykopovar:mainfrom
meh7an:perf/agc-pending-writes-published-union

Conversation

@meh7an

@meh7an meh7an commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

What

Recorder::PendingWriteOverlaps answers whether a range overlaps a GPU write the recorder has noted for its open or in-flight batches. It walks every noted write of every batch, and the draw path asks it from 25 places (in-place draw inputs, texture refreshes, DCC keys, descriptor builds among them).

The recorder already merges those writes into the snapshot it publishes (publishPendingWrites). It now also keeps the union it last published, published, for as long as that union covers every write noted since:

  • publishPendingWrites sets it to the union it publishes;
  • noteWrite and noteWriteOn, which add every batch write, drop it when the new write falls outside it;
  • a recorder that is not active publishes nothing, so once one of its writes falls outside the old union it keeps none.

PendingWriteOverlaps answers no overlap from that union with one binary search when the range is clear of it, and walks the batches otherwise. The union may still hold the writes of batches that finished since it was built; that only sends a query to the walk. #4889's publishedWriteRanges is a weak reference that only lets the next publish extend the snapshot, and it is not dropped when a write falls outside it, so this keeps its own strong pointer.

On the S2 page of Sonic Origins Plus's main menu, PendingWriteOverlaps cost the queue worker (APS5 sampler, 15 s, samples per frame):

  • without this change, in three runs: 0.44, 0.42 and 0.24;
  • with it, in five runs: 0.06, 0.04, 0.07, 0.16 and 0.06.

That is about 1% of the worker's frame (34 to 37 samples), so the frame times below move within run-to-run noise.

Tested

Windows 11 (10.0.26300), WinLibs GCC 15.2.0 (UCRT), Release, NVIDIA GeForce RTX 2080 Ti, driver 617.14.

Metric Baseline This PR Change
frame_ms.p50 114.380 112.276 -1.8%
frame_ms.p90 131.070 115.733 -11.7%
mean_frame_ms 117.931 113.900 -3.4%
gpu_busy_ms_per_present 83.714 83.003 -0.8%
Driver.Packet (ms per frame) 115.666 111.728 -3.4%
Driver.Draw (ms per frame) 103.821 99.869 -3.8%

The FPS shown in the title went from 9.38 to 9.53 (median of six readings). The p90 gap comes from slower frames in the baseline's window; the median moved within noise.

I captured the baseline twice. The first window caught a stretch where the page's draws repeated exactly and the draw cache hit: frames of 74 ms, no shader_compile_and_link phase, and the GPU fence as the limit. The second, used above, shows the moving background like the change's window.

Note: measuring base. These numbers come from my fork's dev, on main 0a56aaa. The code this change touches is the same on main 5d9dcc4, except #4889's incremental snapshot extension, which dev does not have.

Both carry these commits from my fork:

The comparison tool marks the window's first present as a configuration difference: the window opens 200 s into each run. Both summaries set trace_dropped, because the worker filled its event buffer at about 2,700 draws per frame. The phase totals above stay complete.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Unblocks: none
  • GPUs tested: NVIDIA GeForce RTX 2080 Ti, driver 617.14, Windows 11
  • AI-assisted: yes

Traces and summary lines (baseline e3b8d1c, whose summary says a21a3ce; this change a0dd42c, whose summary says e3b8d1c):
union-traces.zip

@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 5609 core/libs/prx/libSceAgcDriver/Graphics/include/Recorder.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Recorder.cpp
PR 6185 core/libs/prx/libSceAgcDriver/Graphics/include/Recorder.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Recorder.cpp
PR 6186 core/libs/prx/libSceAgcDriver/Graphics/include/Recorder.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Recorder.cpp
PR 6188 core/libs/prx/libSceAgcDriver/Graphics/include/Recorder.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Recorder.cpp
PR 6539 core/libs/prx/libSceAgcDriver/Graphics/include/Recorder.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Recorder.cpp
PR 6946 core/libs/prx/libSceAgcDriver/Graphics/src/Recorder.cpp
PR 6947 core/libs/prx/libSceAgcDriver/Graphics/include/Recorder.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Recorder.cpp
PR 7340 core/libs/prx/libSceAgcDriver/Graphics/include/Recorder.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Recorder.cpp
PR 7622 core/libs/prx/libSceAgcDriver/Graphics/src/Recorder.cpp
PR 7642 core/libs/prx/libSceAgcDriver/Graphics/include/Recorder.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Recorder.cpp

@adriadam10

Copy link
Copy Markdown
Collaborator

Checked the published-union fast path against noteWrite, noteWriteOn and publishPendingWrites: the union always covers every noted write (full rebuild includes open, in-flight and finishing batches; a write outside it drops the pointer; an inactive recorder publishes nothing), and a union that still holds finished batches only sends the query to the old walk. Re-checked against current main: the new Recorder changes there (barrier batching) add no noted writes. Merging through the queue.

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

Labels

agc libSceAgc* 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.

2 participants