Repository navigation
perf(agc): drop three per-draw allocations on the draw and materialize paths - #9177
Conversation
|
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.
|
|
AMD/Linux data point, for the "Not tested: AMD" line. The result is neutral: no change and no regression. Setup
Means are 21.36 FPS for this PR and 21.41 for the base, within noise. Swapping the whole allocator for a preloaded jemalloc gained about 4 % on this scene (#357), so allocation cost is visible here, but the three allocations this PR removes are too small to show. AI-assisted: yes (Claude Code); results above were run on this machine. |
|
Thanks @JJenkx. A neutral result on RADV fits what this PR removes: three small allocations per draw, which only show on a frame bound by the draw path, as BO2's menu is here. I added your run to the Tested section and the GPU line. AI-assisted: yes (Claude Code) |
MarcZX10
left a comment
There was a problem hiding this comment.
Review
I did not find a correctness defect in the three allocation changes on this head. The move capture is valid for the local writable program vector, and the scoped reservations match the result-producing paths. I’m requesting changes for the performance evidence and the current overlap state.
Performance evidence
The CONTRIBUTING performance guidance asks for main and change summary lines from the same machine and scene, with traces attached per the issue form. The only paired traces in this PR are from the composite base 690fd731145a and the candidate. Your description explicitly says that base includes #8975, #8756, #8888, and #8928, and correctly warns that the +2.9% result is small and noisy.
I ran the repository comparator on those attached summaries and traces. With --require-matching-context, it rejects the pair because window.first_present differs (7848 vs 7836). Without that requirement, it warns that the measurements do not isolate the code change. Both traces also report dropped events, so the trace detail is incomplete even though the summary data is available. The PR mentions a separate main-alone 9.2 vs 9.2 result, but does not include its matching summary/trace evidence.
Please add a same-machine, same-scene comparison of current main and this change, with the matching summary lines and traces (or explain any unavoidable context mismatch in the report). Please keep the composite-base result clearly labeled as supporting context rather than evidence of the change against main. The current head is 599 commits behind current main, so please also refresh the base and rerun the focused validation after rebasing.
Overlap
The generated overlap report now lists #6946 and #9508 in addition to #6804, #7369, and newer #9387. These are not all duplicates, but the impact should be recorded:
- #6946’s current
Draw.cppstill unconditionally reservesresultsforprograms.size() + 2, which would erase this PR’s ordinary-draw allocation saving if that path is combined as written. Its draw-finisher also changes the ownership/capture flow, so the vector-capture optimization should be rechecked against the combined implementation. - #9508 is stacked on #6946 and inherits that interaction.
- #9387 changes the barycentric-emulation branch in the same draw function, which is one of the paths whose result reservation this PR moves.
Please add the relevant PRs to the overlap notes/checklist and coordinate the combined behavior with those authors as needed. The existing #6804 and #7369 intersections appear to be neighboring, distinct changes.
Checks I ran
git diff --check: passed.- Repository conventions against current
main: passed. - Three-way merge check against current
main: clean. - I did not run a local AGC build or title benchmark on this head; the submitted report contains extensive hardware testing, but the missing current-main paired evidence remains.
The code changes themselves look reasonable. I’ll revisit the review when the performance comparison and overlap notes are updated.
401aab0 to
07e9397
Compare
|
@MarcZX10 thanks. Rebase: onto Current
Overlap: recorded under Overlap in Tested.
@Raghav314 (#6946, #9508): do you have a preferred order? If #6946 goes first, I'll rebase this onto it and move the three reservations and the AI-assisted: yes (Claude Code) |
|
An Apple / MoltenVK data point, on a title whose frame is bound by the queue worker. A small gain there. Setup: Apple M4 Pro, macOS 27.0.1, MoltenVK 1.4.2, x86-64 Release under Rosetta 2.
In Lana every run of this PR is above the mean of the base runs, and the worker is busy about 3 points less. That fits the per-draw allocations this removes: Lana records about 650 draws a frame with the queue worker as the limit. God of War is limited by the GPU, so it shows no change, and no regression. AI-assisted: yes (Claude Code). The runs are from my M4 Pro. |
|
@imellag thanks for the M4 Pro runs. Planet of Lana, with about 650 draws a frame and the queue worker as the limit, is the kind of scene where these allocations should show. Every PR run was above the base mean, and the worker dropped about 3 points, which fits that. God of War being neutral is also useful, as it shows no regression in a GPU-bound case. Added to Tested. AI-assisted: yes (Claude Code) |
Since the draw finisher (boykopovar#6946), Driver::draw copies decode->programs into the draw tail for every draw: one outer vector, one userData vector per program and two shared_ptr reference bumps per program. Before it, the copy was made only when the draw writes user words (mesh index buffer words, indirect record words or relocated user patches), and every other draw read decode->programs in place. Keep the copy in DrawTail::writablePrograms and make DrawTail::programs a pointer to it or to decode->programs, as before. Every write goes through writablePrograms, and the draws that write are exactly the mesh, indirect and patched ones, so a const view of decode->programs can't be written. The queued commit closures now move writablePrograms. When it is empty the captured decode keeps decode->programs alive, and decode is only replaced (by the relocated copy) on draws with user patches, which take the copy. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Driver::draw reserved programs.size() + 2 RecompileResults for every draw, but `results` only receives elements on three paths: the rect-list tessellation pair (2), barycentric emulation (1 geometry shader or 2 tessellation shaders) and CPU-path indirect draws (one copy per compiled program). An ordinary direct draw never touches it, so the reservation was a sizeable heap allocation thrown away each draw. Move the reserve to just before the first push on each of those paths. Every site keeps the old programs.size() + 2 bound, which covers the largest combination (rect-list or barycentric emulation, then the indirect copies; rect-list and barycentric emulation exclude each other). The first reserve on a path therefore sets the same capacity as before, later ones are no-ops, and the &results[i] pointers kept in `stages` stay valid. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tion Three allocations ran on every stage materialization: - DescriptorBindingBuilder::Populate pushed one shaderDataUserWords entry per layout.userDataRegisters element without reserving, so the vector regrew through 1, 2, 4, ... Reserve the exact count first. - GuestSamplersDescriptor appended each sampler's dwords without a reserve. Samplers are four dwords (the table path forces 4, and Populate indexes the result as element * 4), matching the resources.size() * 4 reserve GuestBuffersDescriptor already uses. - ResolveImageTablesShared made a fresh shared ResolvedImageTables for every snapshot without image tables. With no tables, ResolveImageTables either throws (the shader expects tables) or returns a default-constructed result, so return one shared, immutable empty instance instead, still calling ResolveImageTables first so the mismatch keeps throwing. Its only caller reads the result through a const reference and never compares the pointer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
07e9397 to
9e6966b
Compare
|
@MarcZX10 #6946 has landed, so I rebased onto
AI-assisted: yes (Claude Code) |
|
@milescoviello confirmed from the #9049 side: the resolution is right. With #9049, Written by Claude (AI assistant) on a contributor's machine. |
|
@EdouardSence thanks for confirming from the #9049 side. I'll keep the reserve after your AI-assisted: yes (Claude Code) |
|
A Linux/RADV data point for 9e6966b in a scene where the committer is the wall: level within noise, and clean. Setup: ASTRO BOT (PPSA21567) Sky Garden (
The mean p50 is 206.5 against 205.3 ms (−0.6 %), and this PR won 2 of 3 rounds. Run-to-run spread here is about ±1.5 %, so this is level. The three allocations it drops don't show in this scene's committer, where preparation is spread over many smaller costs. No device loss, page fault or Measured and written by Claude (AI assistant) on a contributor's machine. |
|
@EdouardSence thanks. A scene where the committer is the wall is the right place to look, and level within ±1.5 % on RDNA 4 with no device loss, faults or VUIDs matches what BO2's menu shows on NVIDIA. I added the card to the description's GPU list. AI-assisted: yes (Claude Code) |
Dismissing a stale review: the requested changes were addressed after it (new head and/or updated description with the asked-for runs) and the merge queue blocks on it. Please request changes again if anything is still open.
|
Re-checked against current
No shader semantics change, so nothing to measure on the oracle; merged. |
What
Three allocations that ran on every draw or stage materialization, in three commits:
Driver::drawcopies the draw programs for every draw. Since the draw finisher (perf(agc): draw finisher pipeline (APS5_DRAW_PIPELINE) #6946), the draw tail takesprograms = decode->programson every draw: one allocation, plus oneuserDatavector and twoshared_ptrreference bumps per program. Before perf(agc): draw finisher pipeline (APS5_DRAW_PIPELINE) #6946, the copy was made only for draws that write user words (the mesh index buffer words, indirect record words or relocated user patches), and every other draw readdecode->programsin place.DrawTail::writableProgramsnow holds that copy, made on the same condition as before, andDrawTail::programspoints at it or atdecode->programs. Every write goes throughwritablePrograms, so a const view of the decode can't be written.writablePrograms. When it is empty, the captureddecodekeepsdecode->programsalive.decodeis only replaced (by the relocated copy) on draws with user patches, and those take the copy.Driver::drawreservesprograms.size() + 2RecompileResults for every draw. Only three paths fillresults: the rect-list pair, barycentric emulation and CPU-path indirect draws. The reserve now sits right before the first push on each of those paths, with the same bound, so&results[i]stays stable. An ordinary direct draw no longer allocates there.DescriptorBindingBuilder::Populatereserves its exactshaderDataUserWordscount.GuestSamplersDescriptorreserves four dwords per sampler, asGuestBuffersDescriptoralready does.ResolveImageTablesSharedreturns one shared emptyResolvedImageTableswhen there are no tables, still callingResolveImageTablesfirst so its mismatch check keeps throwing.Tested
Rebased onto
main1631964, after #6946's draw finisher, as9e6966b121. #6946 moved the end ofDriver::drawinto aDrawTailthat owns its own copy of the programs, and its commit closures move that copy. So the old first commit (capturingwritableProgramsinstead of copying a const vector) no longer applied, and the copy it avoided became one made on every draw. The new first commit makes that copy only for the draws that write user words, as before #6946. The other two commits are replayed onto the new structure. The second commit's removed reservation now sits in the tail setup.On that head, Ubuntu 26.04.1 (kernel 7.0), GCC 15.2, NVIDIA RTX 4070 Ti, driver 615.71.09, Release:
mesh_draw_relocation|draw_cache_relocation|pipelined_indirect_draw|indirect_patched_stage|rect_list_indirect|rect_list_corner|pixel_barycentric_emulation|image_table|shader_disk_cache|_draw_pipeline$|draw_finisher|draw_pipeline_trace|draw_data_hit_user_words|mesh|indirect|queued_raw_shaderpass 3 of 3. That's the earlier 15 plus perf(agc): draw finisher pipeline (APS5_DRAW_PIPELINE) #6946's draw finisher and pipelined-draw tests and the other mesh and indirect tests. Two of them,agc_driver_pipelined_metadata_pass_draw_pipelineandagc_driver_finisher_label_order_draw_pipeline, ran in a second pass after their executables were built.ANYPS5_REQUIRE_VULKAN=1: the 34 tests matchingmesh_draw_relocation|draw_cache_relocation|pipelined_indirect_draw|indirect_patched_stage|rect_list_indirect|rect_list_corner|pixel_barycentric_emulation|image_table|shader_disk_cache|draw_finisher|draw_pipeline_trace|draw_data_hit_user_words|draw_cache_reuse|draw_write_rangespass 3 of 3 onmain1631964 and 3 of 3 on this head.CoD Black Ops II (PPSA34502), war-room menu: current
mainagainst this head, same machine and scene.main0db47b2 plus fix(libSceVoice): report inactive input voice activity #9656 (f1a1b46987; itslibSceVoice.mddebt-file conflict resolved tomain's side, the code merged cleanly). Without fix(libSceVoice): report inactive input voice activity #9656,mainstops this title at 10 s (libSceVoice: Call of Duty Black Ops II (PPSA34502) stops at sceVoiceGetPortAttr voice activity (attr 1001) since #9137 #9601).dc10dbdc15).7270:10in every run.tools/performance_compare.py --require-matching-contextaccepts all three pairs.On current
mainthis still shows no measurable difference.mainalone went from 9.9 to 14.0 presents per 10 s, and the two usable pairs differ by -12 % and +21 %.Driver.Draw, mostlyGraphics.Draw.draw_and_resource_release. Three small allocations per draw don't show next to that.The summaries, traces and comparator reports of all six runs are in this release. Round 3's window lines:
Base:
{"commit":"f1a1b4698721","dirty":false,"env":{"APS5_PAD_INPUT_FILE":"<path>","APS5_TRACE_DIR":".","APS5_TRACE_FRAMES":"7270:10","APS5_TRACE_SUMMARY_EVERY":"10"},"gpu":"NVIDIA GeForce RTX 4070 Ti","driver":"NVIDIA 615.71.09","os":"Linux 7.0.0-38-generic","cpu":"13th Gen Intel(R) Core(TM) i7-13700K","cpu_threads":24,"memory_mib":30993,"title_id":"PPSA34502","title":"Call of Duty\u00c2\u00ae: Black Ops II","content_version":"01.010.000","resolution":"1920x1080","window":{"spec":"frames 7270:10","first_present":7270,"ms":7159.304},"presents":10,"frame_ms":{"p50":717.667,"p90":789.638,"p99":789.638,"max":789.638},"gpu_busy_ms_per_present":104.532,"worker_busy_pct":{"queue worker 0x0":87.774},"top_phases_ms_per_frame":{"Driver.Packet":600.534,"Graphics.Draw":579.031,"Graphics.Draw.draw_and_resource_release":573.217,"Driver.Packet.draw":568.397,"Driver.Draw":567.372,"Driver.Draw.draw_enqueued":502.342,"Shader.ResolveAbi":102.387,"Shader.ResolveGraphicsStagesAbi":79.292},"trace_dropped":false,"trace":"aps5-trace-f1a1b4698721-3.json.gz"}This PR:
{"commit":"dc10dbdc15d0","dirty":false,"env":{"APS5_PAD_INPUT_FILE":"<path>","APS5_TRACE_DIR":".","APS5_TRACE_FRAMES":"7270:10","APS5_TRACE_SUMMARY_EVERY":"10"},"gpu":"NVIDIA GeForce RTX 4070 Ti","driver":"NVIDIA 615.71.09","os":"Linux 7.0.0-38-generic","cpu":"13th Gen Intel(R) Core(TM) i7-13700K","cpu_threads":24,"memory_mib":30993,"title_id":"PPSA34502","title":"Call of Duty\u00c2\u00ae: Black Ops II","content_version":"01.010.000","resolution":"1920x1080","window":{"spec":"frames 7270:10","first_present":7270,"ms":8652.715},"presents":10,"frame_ms":{"p50":872.987,"p90":912.655,"p99":912.655,"max":912.655},"gpu_busy_ms_per_present":116.45,"worker_busy_pct":{"queue worker 0x0":89.515},"top_phases_ms_per_frame":{"Driver.Packet":739.23,"Graphics.Draw":713.162,"Graphics.Draw.draw_and_resource_release":707.611,"Driver.Packet.draw":703.764,"Driver.Draw":702.804,"Driver.Draw.draw_enqueued":639.762,"Shader.ResolveAbi":101.288,"Shader.ResolveGraphicsStagesAbi":75.025},"trace_dropped":false,"trace":"aps5-trace-dc10dbdc15d0-3.json.gz"}Before the rebase onto #6946.
Rebased onto
maincc00785 as07e939750f, with no conflicts.git range-diffshows the three commits unchanged. On that head, on Ubuntu 26.04.1 (kernel 7.0), GCC 15.2, NVIDIA RTX 4070 Ti, driver 615.71.09, Release: the 15 tests matchingmesh_draw_relocation|draw_cache_relocation|pipelined_indirect_draw|indirect_patched_stage|rect_list_indirect|rect_list_corner|pixel_barycentric_emulation|image_table|shader_disk_cachepass 3 of 3.CoD Black Ops II (PPSA34502), war-room menu:
main4777cac against the pre-rebase head, same machine and scene.main4777cac plus fix(libSceVoice): report inactive input voice activity #9656 (9d56f02254). Without fix(libSceVoice): report inactive input voice activity #9656,mainstops this title at 10 s onsceVoiceGetPortAttr(libSceVoice: Call of Duty Black Ops II (PPSA34502) stops at sceVoiceGetPortAttr voice activity (attr 1001) since #9137 #9601).5b24a5b8c3).APS5_TRACE_FRAMES=7270:10: the menu starts at about present 7246, after the title's 60 FPS intro. So both sides' windows start at the same present, with the same environment and nothing dropped, andtools/performance_compare.py --require-matching-contextaccepts all three pairs.On
mainthis shows no measurable difference. A frame takes about 0.9 to 1.1 s, and 690 to 890 ms of it isGraphics.Draw.draw_and_resource_release, the per-draw snapshot copies that #8756 removes. Three small allocations per draw don't show next to that, and round 2's gap is within this machine's run-to-run noise. The summaries, traces and comparator reports of all six runs are in this release. Round 3's window lines:Base:
{"commit":"9d56f02254da","dirty":false,"env":{"APS5_PAD_INPUT_FILE":"<path>","APS5_TRACE_DIR":".","APS5_TRACE_FRAMES":"7270:10","APS5_TRACE_SUMMARY_EVERY":"10"},"gpu":"NVIDIA GeForce RTX 4070 Ti","driver":"NVIDIA 615.71.09","os":"Linux 7.0.0-38-generic","cpu":"13th Gen Intel(R) Core(TM) i7-13700K","cpu_threads":24,"memory_mib":30993,"title_id":"PPSA34502","title":"Call of Duty\u00c2\u00ae: Black Ops II","content_version":"01.010.000","resolution":"1920x1080","window":{"spec":"frames 7270:10","first_present":7270,"ms":8718.58},"presents":10,"frame_ms":{"p50":879.643,"p90":914.046,"p99":914.046,"max":914.046},"gpu_busy_ms_per_present":118.379,"worker_busy_pct":{"queue worker 0x0":90.263},"top_phases_ms_per_frame":{"Driver.Packet":757.556,"Driver.Packet.draw":713.589,"Driver.Draw":712.425,"Graphics.Draw":694.609,"Graphics.Draw.draw_and_resource_release":688.25,"Driver.Draw.draw_enqueued":627.459,"Shader.ResolveAbi":94.793,"Shader.ResolveGraphicsStagesAbi":69.168},"trace_dropped":false,"trace":"aps5-trace-9d56f02254da-3.json.gz"}This PR:
{"commit":"5b24a5b8c3fb","dirty":false,"env":{"APS5_PAD_INPUT_FILE":"<path>","APS5_TRACE_DIR":".","APS5_TRACE_FRAMES":"7270:10","APS5_TRACE_SUMMARY_EVERY":"10"},"gpu":"NVIDIA GeForce RTX 4070 Ti","driver":"NVIDIA 615.71.09","os":"Linux 7.0.0-38-generic","cpu":"13th Gen Intel(R) Core(TM) i7-13700K","cpu_threads":24,"memory_mib":30993,"title_id":"PPSA34502","title":"Call of Duty\u00c2\u00ae: Black Ops II","content_version":"01.010.000","resolution":"1920x1080","window":{"spec":"frames 7270:10","first_present":7270,"ms":8732.553},"presents":10,"frame_ms":{"p50":889.031,"p90":912.664,"p99":912.664,"max":912.664},"gpu_busy_ms_per_present":116.286,"worker_busy_pct":{"queue worker 0x0":90.086},"top_phases_ms_per_frame":{"Driver.Packet":751.697,"Driver.Packet.draw":717.244,"Driver.Draw":715.92,"Graphics.Draw":706.998,"Graphics.Draw.draw_and_resource_release":699.975,"Driver.Draw.draw_enqueued":627.015,"Shader.ResolveAbi":86.669,"Driver.Draw.shader_compile_and_link":71.515},"trace_dropped":false,"trace":"aps5-trace-5b24a5b8c3fb-3.json.gz"}Supporting context only, not evidence against
main: the same menu on a faster composite base. The runs below are from before the rebase: Ubuntu 24.04, GCC 13.3, NVIDIA RTX 4070 Ti, driver 595.99.02, i7-13700K.Suites on
maine072e88:^agc_|^shader|^request_serializer$passes 866 of 869. The 3 failures are fix(agc): keep the guest's sample order where pixel (0,0)'s locations stand in for a 2x2 grid #6683's sample-order tests, which fail onmainon this card too; test(agc): read the sample order tests' depth through a sampled copy #9056 fixes them.mainand on this head, with no VUID on either.CoD Black Ops II (PPSA34502), war-room menu, on a composite base. Release libs, 12 GB cap, the scripted run, 10 s summaries from 140 s. On
mainalone the menu is bound by per-draw snapshot copies (about 9 presents per 10 s), and the three commits make no measurable difference there: 9.2 against 9.2 over three rounds. So the comparison runs onmainf894ba6 with #8975 (its pre-merge head), #8756, #8888 and #8928 merged (base690fd73114), and the same three commits on it, where the menu reaches about 60 presents per 10 s and these allocations are a visible part of the queue worker's time. Six alternating rounds, after one warm-up round each:The mean is 59.9 against 61.7, +2.9 %, and this PR is ahead in 4 of 6 rounds. That's small next to the run-to-run noise on this machine, which shares its CPU with other services. Treat it as a modest gain, not a proven one. Round 4's base run lost its first intervals to host load.
Captures of round 6, the last one (summary files, traces and
tools/trace_digest.pyoutput), are in this release. The 220:5 window lines:Base:
{"commit":"690fd731145a","dirty":false,"env":{"APS5_PAD_INPUT_FILE":"<path>","APS5_TRACE_DIR":".","APS5_TRACE_SECONDS":"220:5","APS5_TRACE_SUMMARY_EVERY":"10"},"gpu":"NVIDIA GeForce RTX 4070 Ti","driver":"NVIDIA 595.99.02","os":"Linux 6.8.0-147-generic","cpu":"13th Gen Intel(R) Core(TM) i7-13700K","cpu_threads":24,"memory_mib":32022,"title_id":"PPSA34502","title":"Call of Duty\u00c2\u00ae: Black Ops II","content_version":"01.010.000","resolution":"1920x1080","window":{"spec":"seconds 220:5","first_present":7848,"ms":5124.782},"presents":32,"frame_ms":{"p50":158.175,"p90":175.641,"p99":179.709,"max":179.709},"gpu_busy_ms_per_present":28.208,"worker_busy_pct":{"queue worker 0x0":77.066},"top_phases_ms_per_frame":{"Driver.Packet":122.550,"Driver.Packet.draw":101.710,"Driver.Draw":100.761,"Driver.Draw.shader_compile_and_link":65.929,"Graphics.Draw":60.745,"Graphics.Draw.draw_and_resource_release":54.655,"Shader.DrawStage":54.205,"Shader.ResolveGraphicsAbi":32.483},"trace_dropped":true,"trace_dropped_threads":{"queue worker 0x0":{"events_full_after_s":4.434,"events_lost":42081,"totals_full":false}},"trace":"aps5-trace-690fd731145a-3.json.gz"}This PR:
{"commit":"229a439d32e7","dirty":false,"env":{"APS5_PAD_INPUT_FILE":"<path>","APS5_TRACE_DIR":".","APS5_TRACE_SECONDS":"220:5","APS5_TRACE_SUMMARY_EVERY":"10"},"gpu":"NVIDIA GeForce RTX 4070 Ti","driver":"NVIDIA 595.99.02","os":"Linux 6.8.0-147-generic","cpu":"13th Gen Intel(R) Core(TM) i7-13700K","cpu_threads":24,"memory_mib":32022,"title_id":"PPSA34502","title":"Call of Duty\u00c2\u00ae: Black Ops II","content_version":"01.010.000","resolution":"1920x1080","window":{"spec":"seconds 220:5","first_present":7836,"ms":5156.383},"presents":31,"frame_ms":{"p50":166.949,"p90":194.986,"p99":201.887,"max":201.887},"gpu_busy_ms_per_present":30.604,"worker_busy_pct":{"queue worker 0x0":74.916},"top_phases_ms_per_frame":{"Driver.Packet":123.340,"Driver.Packet.draw":101.303,"Driver.Draw":100.314,"Driver.Draw.shader_compile_and_link":66.453,"Graphics.Draw":61.821,"Shader.DrawStage":56.791,"Graphics.Draw.draw_and_resource_release":55.914,"Shader.ResolveGraphicsAbi":33.164},"trace_dropped":true,"trace_dropped_threads":{"queue worker 0x0":{"events_full_after_s":4.932,"events_lost":12130,"totals_full":false}},"trace":"aps5-trace-229a439d32e7-3.json.gz"}macOS, a title bound by the queue worker: @imellag ran it on an Apple M4 Pro (macOS 27.0.1, MoltenVK 1.4.2, x86-64 Release under Rosetta 2).
maindoesn't build on macOS, so the base wasmaincecb540 plus the macOS port PRs, with this PR's three commits (pre-rebase head401aab07d9, the same commits) cherry-picked onto it. Arms alternated, scripted input.AMD, Linux: @JJenkx ran it on an RX 6650 XT (RADV, Mesa 26.2.4) with ASTRO BOT booted without input, the PR against its own base, alternated base, PR, PR, base. FPS 21.40, 21.42 on the base and 21.54, 21.18 with the PR: no change and no regression on that scene. Swapping in jemalloc gains about 4 % there, so allocation does show, but these three allocations are too small to.
Windows 11 Enterprise 26300, NVIDIA GeForce GT 1030 (driver 582.78), WinLibs GCC 15.2.0 r7 (UCRT), Release: the 28 AGC relocation, indirect, rect-list, barycentric, draw descriptor and pipelined tests pass 3 of 3 on
mainand 3 of 3 with this change. The pattern also matched 6 relinker relocation tests. They could not start on either side, because that run didn't build the relinker they launch.Not tested: Intel.
Overlap (the generated report on this head: a textual conflict with #9049; #6804, #7369, #9387 and #9508 also share
Draw.cppbut conflict withmain, so they weren't compared):DrawTail, and the reservations stay in the three paths that fillresults.GuestSamplersDescriptorinto a function that fills a reused vector (result.clear()), next to this PR'sresult.reserve(resources.size() * 4u). Whichever lands second keeps the reserve after theclear(). With a reused vector it costs nothing once the capacity is there.main. ItsDraw.cppchanges only readprograms, so the const view this PR gives that code is enough, and it doesn't touchresults' reservations.std::optionaland still appends at most the two tessellation results, which that branch's reservation covers. So the two only touch neighbouring lines.Draw.cpp; their changes are distinct.Checklist
main; no other open PR implements the same functions (a textual conflict with perf(shader): reuse an evicted memo result's bindings for the next miss #9049, and neighbouring lines of feat(agc): emulate mesh-fallback barycentrics through tessellation #9387, perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508, feat(agc): read sampler border colours from the border colour table #6804 and fix(agc): look up and attach draw recipes on the relocated donor entry #7369: see Overlap above)NotImplemented_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)🤖 Generated with Claude Code