visgl / visgl/deck.gl

[RFC] Use RenderBundles on WebGPU

Open
#10,440 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

feature
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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.