Repository navigation
perf(agc): pipeline queue-0 draw commits behind the packet worker - #1201
Conversation
…rror Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Keeping it made evictOldest read the front of an empty deque (agc_buffer_pool aborted with a double free) and stopped Take at an empty class instead of trying the next size. Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
… stages alive The commit lambda held raw pointers into the draw's stage-data hits and compiled stages, which were freed when the worker returned (agc_driver_draw_cache_reuse with APS5_PIPELINED_DRAWS=1). Co-Authored-By: Claude <noreply@anthropic.com>
…draws, pin CMASK write ranges Co-Authored-By: Claude <noreply@anthropic.com>
… now that it cannot be moved Co-Authored-By: Claude <noreply@anthropic.com>
31c9a0f to
43d7c11
Compare
|
Rebased onto main (no merge commits; backup of 31c9a0f at Picked from the threads (cherry-picked with
Found here and fixed:
New tests (each check proven by mutating the fix and seeing it fail): Local results (Linux, Radeon 660M, RADV,
The only failure, |
|
Thanks @adriadam10 for rebasing, folding in the predicate and deferred-label fixes, and chasing down the pipelined-commit lifetime and failure-path bugs, and to everyone whose fixes went in. I'll keep testing the pipeline on Hades II and report back on #1202. |
Brings the series onto main 4e9a2a8 (boykopovar#1193, boykopovar#1201, boykopovar#1202, boykopovar#6060, boykopovar#6333 and the descriptor word tracking of 682b07e). Resolutions: - ShaderMemory: the column memo's supplied and spilled blocks now sit on boykopovar#1193's page vector, page pool and word masks. Pages are found by binary search, since a spilled block can add many pages, and a block placed into a lazily read page fills the rest of the 16-word blocks it touches, so a later lazy read never overwrites placed words. - ResourceMaterializer and SharedValues: the selected-record path and the words index carry availableDwordMask, as the snapshot hash does. A selected record's dwords past the end of its buffer count as read zeros, which is what a scalar buffer load returns there, so a key past the heap still selects a null image without reading the heap. - DescriptorCache: kept table sets live beside boykopovar#1201's recycled sets. - Tests and CMake: both sides' tests are kept.
Upstream main now carries the final versions of PRs boykopovar#1193, boykopovar#1201, boykopovar#1202, boykopovar#5216 and boykopovar#4465, so their draft copies on this branch give way to main's: the snapshot ring, the pipeline identity memo, the code-hash memo and APS5_RESIDENT_LINEAR_TARGETS are gone with them. The port of boykopovar#4943 (draw-cache relocation across moved user-data pointers, not merged upstream) is dropped: the draw prefetch replaces it. Kept on top of main: the arm64 FEXCore runner and macOS libraries, the MoltenVK settings, rect-list clip and cull distances, GPU-ordered in-place vertex inputs, the draw pipeline's spin-first locks and lock-free overlap check, SharedVector binding flags, the result-memo admission, the draw prefetch (APS5_DRAW_PREFETCH) and the 1D T# sample modes. New for arm64: fegetenv from the runner's guest control words, and the direct-memory reuse map on macOS. On macOS the guest buffers keep one descriptor array (no buffers_coherent or buffers_u8 aliases): MoltenVK aliases a descriptor array only through Metal argument buffers, which the driver turns off, and Vampire Crawlers' first compute pipeline failed to compile.
|
@MichonGoddijn231849 @oneandonlydean a question about where this goes next, so nobody does the same work twice. On Windows (RTX 5070 Ti / 7800X3D), with #6763 (draw inputs copied instead of bound in place: the GPU time of the draws went 164 -> 45 ms per frame) and #6188, Astro Bot's Crash Site (~2200 draws per frame) is now bound by this PR's committer: it holds the GPU mutex 68% of the time at ~34 us per draw, and the packet worker spends 22.6 of its 33 us per packet waiting for it. Per draw: snapshots and descriptor sets ~7.6 us, pipeline/resource lookup ~8, vertex copies ~5, target refresh ~3, the Vulkan commands themselves ~3. We are trimming those pieces one by one, but past that the single committer is the ceiling. Is anyone working on, or planning, recording draws on more than one thread (for example secondary command buffers per render pass, committed in order)? If it is on your list we will stay out of it and measure your branch on Windows; if not, we would like to know whether you would take it in that form before we start. |
Brings the series onto main 4e9a2a8 (#1193, #1201, #1202, #6060, #6333 and the descriptor word tracking of 682b07e). Resolutions: - ShaderMemory: the column memo's supplied and spilled blocks now sit on #1193's page vector, page pool and word masks. Pages are found by binary search, since a spilled block can add many pages, and a block placed into a lazily read page fills the rest of the 16-word blocks it touches, so a later lazy read never overwrites placed words. - ResourceMaterializer and SharedValues: the selected-record path and the words index carry availableDwordMask, as the snapshot hash does. A selected record's dwords past the end of its buffer count as read zeros, which is what a scalar buffer load returns there, so a key past the heap still selects a null image without reading the heap. - DescriptorCache: kept table sets live beside #1201's recycled sets. - Tests and CMake: both sides' tests are kept.
What
With
APS5_PIPELINED_DRAWS=1, queue 0's worker decodes, captures and recompiles a draw, and hands it to a committer thread that records it (Graphics::Drawunder the GPU lock). The two now run in parallel instead of one after the other. Work the committer has not reached yet is tracked by the guest ranges it will write. A later packet that reads or writes those ranges, or one the pipeline cannot order, drains it.These are ordered as commit items instead of drains:
APS5_PIPELINE_DRAIN_LABELS=1drains instead);APS5_PIPELINE_DRAIN_SUBMISSIONS=1drains);APS5_PIPELINE_DRAIN_FILLS=1drains);APS5_PIPELINE_DMA=1).A draw's write ranges include the storage images it writes and its exact color and depth target ranges (
APS5_EXACT_DRAW_WRITES=1), not estimates.Draw-path costs the pipeline exposed:
ShaderMemorymoves, so a commit owns its capture's pages.APS5_SUBMISSION_EPOCH_EACH=1bumps at every submission). A thread remembers the ranges it walked for the whole epoch.std::mutex(winpthreads contention showed up as kernel events).ScanPendingskips the registry walk when no pending image can overlap.The pipeline is off by default in this PR; the next one in the series turns it on.
A predicated packet is left to the normal path while predication is active, so a false predicate still skips it.
Two fixes since the rebase, each its own commit: a null storage image in a draw's written set is skipped before it is decoded (gjonn and SleglJan's report, PPSA01317), and a pipelined
RELEASE_MEMwithINT_SEL3 raises no interrupt, as onmain(TheAggie's report).Note for #374 and #419: they note HTILE and CMASK fills in the DMA_DATA path. Whichever lands second also has to call
NoteDepthMetadataFillandNoteColorMetadataFillin the pipelined DMA commit (commitDmaStore).Tested
Windows 11 Pro, AMD Ryzen 5 7600, NVIDIA GeForce RTX 5080 (driver 32.0.16.1074), 32 GB, MinGW-w64 GCC 15.2.0.
gta-v/testingbranch (Performance mode, the prologue). GTA V Performance mode, the prologue's bank interior: about 11.7 to 20 fps together with the cheaper captures below it.ctestpasses. Not run here: the relinker's Python tests (my local Python does not find their helper modules) andguest_gameupdate.maina56c905 (2026-10-13), starting from gjonn's rebase of this series onto 6ac63bf (thanks). On Windows (MinGW GCC 15.2, RTX 5080) the wholeagc_*suite passes on the top of the series: 483 tests, 1 skipped (agc_driver_stencil_ref_export).APS5_PIPELINED_DRAWS=1the same suite passes exceptagc_driver_pm4_failure, which expects a synchronous rejection (perf(agc): pipelined draws on by default #1202 runs it with the pipeline off).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