[RFC] Use RenderBundles on WebGPU
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 14.6k
- Forks
- 2.3k
- Avg merge
- 2d 9h
- Merged PRs (30d)
- 42
Description
Target Use Case
RFC: WebGPU render bundles for stable deck.gl draw plans
Status
Proposed
Summary
luma.gl 9.4 adds WebGPU-only RenderBundleEncoder support. Render bundles record reusable draw commands once and replay them from a later render pass.
Render bundles can reuse commands when buffer and texture contents change, but must be rebuilt when:
- draw commands change;
- layer/model order changes;
- pipeline state changes;
- bound buffer, texture, sampler, or bind-group identities change;
- draw counts or offsets change;
- attachment formats or sample counts change.
Reference: https://luma.gl/docs/api-reference/core/resources/render-bundle-encoder
deck.gl should investigate using render bundles for stable layer/view draw plans, potentially allowing all eligible layers in one view to be replayed from one or more cached bundles.
The proposal is feasible, but not by wrapping the existing LayersPass draw loop. deck.gl currently performs meaningful work during draw, including viewport activation, attribute transitions, shader-input updates, extension hooks, parameter changes, and model draws.
Motivation
deck.gl often redraws scenes where:
- visible layers and draw order are stable;
- buffers are unchanged or updated in place;
- only viewport uniforms, layer uniforms, animation values, or texture contents change;
- many models are drawn each frame.
Render bundles could reduce CPU-side WebGPU command recording and validation for these stable scenes. They will not reduce GPU draw cost.
Current constraints
LayersPass currently begins a render pass before resolving and drawing layers:
modules/core/src/passes/layers-pass.ts
It then:
- resolves layer visibility, filters, shader props, and parameters per viewport;
- updates viewport dynamic state;
- mutates project shader props per viewport/sub-viewport;
- calls
Layer._drawLayer()for each visible layer.
Layer._drawLayer() currently:
- advances attribute transitions;
- updates shader-module props;
- applies model parameters;
- invokes extension draw hooks;
- calls layer draw methods.
Viewport activation can also trigger layer updates during rendering:
modules/core/src/lib/layer.ts
Most built-in layers set shader inputs inside draw(). Some layers issue multiple model draws while changing uniforms between them, such as wrapped LineLayer.
Goals
- Add an experimental WebGPU-only render-bundle path.
- Reuse bundles when only already-bound buffer or texture contents change.
- Preserve existing WebGL behavior.
- Support direct-draw fallback for ineligible layers.
- Preserve layer ordering across bundled and direct draws.
- Expose metrics for bundle creation, reuse, invalidation, and fallback.
Non-goals for the first milestone
- WebGL support.
- Picking bundles.
- Public extension compatibility.
- Post-processing, terrain, masks, collision, or other multipass effects.
- Base-map interleaving.
- Multisampled render targets.
luma.gl 9.4 currently only supports render bundles with sampleCount: 1.
Reference: https://luma.gl/docs/api-guide/gpu/gpu-commands
Proposal
Introduce an internal draw-plan phase:
const drawPlan = layersPass.resolveDrawPlan(options);
drawPlan.prepare(commandEncoder);
const renderPass = device.beginRenderPass(...);
for (const segment of drawPlan.segments) {
renderPass.setParameters({viewport: segment.viewport});
if (segment.bundle) {
renderPass.executeBundles([segment.bundle]);
} else {
segment.drawDirect(renderPass);
}
}
renderPass.end();
### Proposal
See above
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading modules/core/src/passes/layers-pass.ts and modules/core/src/lib/layer.ts to trace draw-plan resolution, viewport activation, and layer updates. Compare that flow with the stated render-bundle constraints and determine the scope of an experimental WebGPU-only path, including direct-draw fallback and invalidation metrics; the issue is done when a concrete implementation plan addresses the listed goals and non-goals.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- computer-graphics, performance
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 30/100