Repository navigation
perf(agc): draw stages use their shared compiled result instead of a copy - #5687
Conversation
…copy Driver::draw copied every stage's compiled result (RecompileResult, with its binding, push-constant and attribute vectors) out of the shared result the capture materialized, once per stage per draw. The stages now point at the shared result. Only the CPU path of an indirect draw rewrites a stage (each record's patched user data is materialized again), so that path copies the stages it may rewrite first, on a cache hit or a miss. agc_driver_indirect_patched_stage draws through that path: a record that patches the user data word a vertex stage writes as its depth must draw with the record's value, not the register's. Co-Authored-By: Claude Opus 5.5 <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.
|
|
Runs for this PR at head
No difference between the two GPUs. AI-assisted (Claude Code). |
|
Checked the diff (shared result lifetime via |
Conflicts kept our shared stage results in the draw path (upstream's boykopovar#5687 is the same change), our clean-range skip beside upstream's collectable-range memo and ordered view lookup in WindowsMappings, and our single-sample MSAA mode, under which upstream's dithered alpha-to-coverage emulation stays off. Nonzero constant dword fills (boykopovar#5380) do not mark the images over their keys as filled, as for the source fill kernel: they were dispatches before. Our SSL connect, read and write keep returning the network error. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
What
materializeDrawStagereturned a copy of the compiled result it had just materialized (RecompileResult result = *stageCapture.compiled), so every stage of every draw that is not a draw-cache hit copied a wholeRecompileResult(its bindings, push constants and vertex attributes) intoDriver::draw'sresults, and freed it again at the end of the draw. The shared result stays alive instageCapturesfor the whole draw anyway.materializeDrawStagereturns the shared result, andDriver::drawkeeps it incompiledStages; the stages point at it.results, as before.resultskeeps its reserve ofprograms.size() + 2, which still covers the most it holds (two rect-list stages and a copy of each program).The shared draw-stage result was in an earlier version of #1202 and left out in its rebase because
mainrewrites stage results; this keeps the copies for the one path that rewrites them.PPSA36082
Standing in the hub, the queue worker is 99% busy, and a profile of it showed about 3.4% of its time copying and freeing these results (inside
malloc/free). Two hub runs in one sitting, one after the other (traces attached):mainf74ec63:dirty):The stage path this changes takes less of the frame:
Shader.DrawStage9.13 to 8.57 ms per frame andDriver.Draw.shader_compile_and_link11.19 to 10.61 ms. The frame time p50 went from 28.3 to 27.6 ms, but an earliermainrun on the same machine gave 500 presents and p50 29.677, so whole-frame numbers vary by about as much as this difference. The picture in the hub is unchanged.aps5-trace-f74ec639c457-742938.json.gz - This PR
aps5-trace-f74ec639c457-743649.json.gz - Main
Tested
Linux (CachyOS), x86-64, GCC, 7800X3D / RTX 4090, NVIDIA 615.78.08.
agc_driver_indirect_patched_stage: a non-indexedDRAW_INDIRECTwhose base vertex location is the vertex stage's user data word 0 takes the CPU path (the stage does not fold that word). The vertex stage writes that word as its depth. A record with 0 over a register value of 2.0 must draw the same pixels as a direct draw with 0, and a record with 2.0 over a register value of 0 must draw nothing (clipped). It passes onmainand with this change. It fails when the copy before the rewrite is skipped on a miss (segmentation fault) and when the patched stage is not materialized again (the draw keeps the register's depth).build.ymlrun locally on this branch (rebased onmaind8888df): configure with SPIRV tools on, test registration check, build, libs, ctest 1115/1115,check_skips.pyclean (7 expected skips).APS5_HOST_IMPORT_MIB=6784 APS5_TRACE_SECONDS=120:15, hub standing still, shader cache warmed for each build.Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file.mdfiles or images added to the repository (attach them to this PR)