Repository navigation
perf(agc): fewer heap allocations per recorded draw - #6566
Merged
adriadam10 merged 1 commit intoOct 19, 2026
Merged
Conversation
The committer built a recorded draw's resource key through two temporaries a shader, took the in-place and device read lists by value, and in PrepareDrawBindings built two layout-binding vectors only to test them for emptiness, a std::map of pool sizes a set, and copies of the descriptor buffer and write lists, all on every draw. The key is now built in place with its size reserved, the read lists fill a caller's vector, and the per-draw bookkeeping lives in the thread's scratch (ThreadOwned), as the selected-slot list already did. The queue worker's program list and memory snapshots reserve their size up front. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
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.
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.
|
This was referenced Oct 15, 2026
9 tasks done
12 tasks done
This was referenced Oct 16, 2026
Contributor
|
Diablo II: Resurrected in gameplay: +6% with this PR stacked with #6312, #6617 and #6733 (Linux) Setup: Presents per 10 s, runs alternated:
AI-assisted: yes (Claude Code) |
EagleBearerYS
added a commit
to EagleBearerYS/AnyPS5
that referenced
this pull request
Oct 17, 2026
The scan tests' includes now sit before <array>, where boykopovar#6706 and boykopovar#5859 add theirs after it, and the pass counter's address flag is set after the read-only check instead of next to the pass reads boykopovar#6566 rewrites. No behaviour change.
9 tasks done
12 tasks done
This was referenced Oct 19, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
On a title whose draws all hit the draw cache, the committer's time per draw is mostly small costs that repeat for every draw. Counting heap allocations with a hook on the driver's
operator newimports showed about 135 per draw (with the relocation PRs' own share already pooled) on Ratchet & Clank under RetroArch's PCSX2 core, at roughly 0.1 µs each on two threads sharing one heap. This PR removes the ones in the committer's draw path that need no change of behaviour:DrawResourceKeybuilds the key in place, reserving its size:ShaderResources::AppendContentKeywrites a shader's content key into a caller's vector, andContentKeykeeps its by-value form on top of it.GuestBufferMemory::InPlaceReadsandDeviceReadsget overloads that fill a caller's vector; the by-value forms stay. The committer's pass reads andPrepareDrawBindings' in-place reads come from the thread's scratch.PrepareDrawBindingsbuilt twoVkDescriptorSetLayoutBindingvectors a draw only to test them for emptiness, astd::mapof descriptor counts a set, two pool-size vectors, and copies of the descriptor buffer and write lists. The emptiness is a flag, the counts are a small sorted vector in thread scratch, and the buffer and write copies and the snapshot index list reuse thread scratch (ShaderRecompiler::ThreadOwned, as the selected-slot list there already did). The copies are still copies: the writes are patched per draw beforevkUpdateDescriptorSets.Related: #6312 cuts other allocations of the same draw path (the decode's program copy, the validation key, the moved words, the decode reads,
ShaderMemory's regions, and reserves inDriver::draw). This PR is the committer's resource key, read lists and descriptor bookkeeping, which #6312 leaves as they are; the two meet only textually, in neighbouring lines ofPrepareDrawBindings, and whichever lands second rebases.No pointer into the scratch outlives the call that fills it: the pass reads are consumed by
StartDrawPass/LeaveRenderPassOpen(PassHazardscopies what it keeps), and the descriptor writes byvkUpdateDescriptorSets.Tested
Windows 11, NVIDIA GeForce RTX 5070 Ti, MinGW-w64 GCC 15.2.0, on main
ce991f1ec.ctest: 1278 of 1297 pass, 14 skipped.guest_call_trace_abortandwindows_backtrace_reportfail, and fail the same way on plain main here;agc_driver_prepared_graphics_prebuild_0/_1andundeliverable_host_exceptionfail under my test runner because it skips their environment changes and pass pattern, and pass run with those.agc_driver_gpu_indirect_arguments_misaligned_writer_ahead, new on this main, does not compile with MinGW (alignas(65536)exceeds the object file maximum of 8192) and was left out of the run.Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed in TechnicalDebt.mdfiles or images added to the repository (attach them to this PR)🤖 Generated with Claude Code