Use Metal ICBs for multi-draw indirect count#9679
Draft
matthargett wants to merge 22 commits into
Draft
Conversation
Add Metal ICB generation for mesh multi-draw indirect and opt-in count-buffer variants. Wire the Chromium experimental multi-draw indirect API surface for CTS, add wgpu-owned readback tests for normal/indexed count-buffer draws and mesh MDI, and validate draw-count-buffer offset alignment.
8 tasks
|
One small correction - #9659 doesn't use CPU-side loop. It injects compute shader to fill temp buffer and then issues a single Other than that - thank you, I was looking for this feature for a long time I have Mac Mini M1, Mac Mini M4 Pro, iPhone 13 Pro Max and iPad Pro 12.9" (6th gen) if you need help with testing |
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.
Connections
Stacked on #9640, which adds the Metal ICB infrastructure for fixed-count multi-draw indirect.
Related alternative: #9659 implements
MULTI_DRAW_INDIRECT_COUNTby GPU-preprocessing into a temporary buffer followed by CPU-driven indirect draw loops. This PR instead keeps the command count GPU-resident and executes through Metal Indirect Command Buffers.Description
This exposes
Features::MULTI_DRAW_INDIRECT_COUNTon Metal when the adapter supports both render and compute Indirect Command Buffers, then routes non-indexed, indexed, and mesh count-buffer multi-draw calls through the existing ICB generation path.Metal does not have a Vulkan-style
draw_indirect_countentrypoint, but it can execute anMTLIndirectCommandBufferwith an indirect execution range. The implementation records up tomax_countICB commands on the GPU from the WebGPU indirect-argument buffer, runs a tiny compute kernel that clamps the guest-provided count buffer value tomax_count, and then callsexecuteCommandsInBuffer:indirectBuffer:indirectBufferOffset:. No CPU readback of the count buffer is needed.This PR also makes the ICB resume path restore active render bind groups before executing the ICB. Without that, count draws with material/uniform bind groups can hit the ICB path but render with missing inherited buffer state after the render pass is suspended and resumed. The restore reuses the existing Metal bind-group update code and keeps the existing immediates/query/resume gates in place.
Testing
Local M4 Max / Metal validation only; I do not have the iPhone XS/A12 device with me for this follow-up.
cargo fmt --checkgit diff --checkcargo check -p wgpu-hal --features metal --no-default-featuresWGPU_BACKEND=metal WGPU_METAL_REQUIRE_ICB_MDI=1 cargo test -p wgpu-test --test wgpu-gpu multi_draw_indirect_count -- --test-threads=1 --nocapture, 3 passed; diagnostics showed non-indexed count and mesh count executing through Metal ICB.WGPU_BACKEND=metal WGPU_METAL_REQUIRE_ICB_MDI=1 cargo test -p wgpu-test --test wgpu-gpu multi_draw_indexed_indirect_count -- --test-threads=1 --nocapture, 2 passed; diagnostics showed indexed count executing through Metal ICB.WGPU_BACKEND=metal WGPU_METAL_REQUIRE_ICB_MDI=1 cargo test -p wgpu-test --test wgpu-gpu multi_draw_indirect_bind_group -- --test-threads=1 --nocapture, 1 passed; diagnostics showed fixed-count bind-group MDI now executing through Metal ICB after bind-group restore.WGPU_BACKEND=metal cargo test -p wgpu-test --test wgpu-gpu draw_indirect -- --test-threads=1 --nocapture, 38 passed.cargo xtask cts 'webgpu:api,validation,encoding,cmds,render,indirect_multi_draw:*', 6 / 6 passed.Squash or Rebase?
Squash before merge. This is intentionally stacked on #9640; once #9640 lands, this should be rebased so the final diff is just the count-buffer support and tests.
Checklist
wgpumay be affected behaviorally on Metal when they requestMULTI_DRAW_INDIRECT_COUNT.CHANGELOG.mdentries for the user-facing effects of this change are present.