ComputePass runs one dispatch per rendered frame. PingPongComputePass runs one or more iterations while the renderer alternates two private texture allocations. Both run before the base material. Every buffer, texture, and sampler used by compute is declared in the pass-local resources map.
Use PingPongShaderPass when a fullscreen simulation only samples the previous color and writes the next color. Compute is a better fit for storage buffers, storage textures, explicit workgroups, and data layouts that do not map to fragments.
Shader contract
Compute source must contain:
- numeric
@workgroup_size(...)dimensions from 1 through 65535; - a function named
computewith the@computeattribute; @builtin(global_invocation_id)in that function’s parameters.
The constructor and setCompute(...) validate this contract. Resource topology is fixed by the constructor. setCompute(...) may replace the shader, but the replacement must use the same bindings.
Resource descriptors
Map keys are exact WGSL variable names. A descriptor points to a material resource or a borrowed WebGPU object.
A ComputePass without resources has only frame and material uniforms. Material textures and storage buffers are never injected automatically. Aliases must be valid WGSL identifiers and cannot use motiongpuFrame or motiongpuUniforms.
Bindings are sorted by alias. Group 0 contains frame and material uniforms. A non-empty resource map becomes group 1. The same resolved list drives WGSL generation, bind-group layout, resource validation, and dependency scheduling.
Resource versions
Read-only texture and buffer descriptors accept version: 'current' | 'initial':
currentis the default. If the resource has a writer in this frame, the reader runs after it.initialreads the value imported at the start of the frame and runs before the writer.
initial does not copy the resource. If an algorithm must preserve an old value after overwriting the same allocation, use separate resources or PingPongComputePass.
Texture views and formats
Texture descriptors accept { baseMipLevel?, mipLevelCount?, baseArrayLayer?, arrayLayerCount?: 1 }. Sampled bindings default to the remaining mip range; storage writes expose one mip level. Motion GPU supports 2D color views in compute descriptors and rejects invalid ranges before dispatch.
Sampled declarations follow the actual format class. Float, unsigned-integer, and signed-integer textures generate texture_2d<f32>, texture_2d<u32>, and texture_2d<i32> respectively. Storage declarations keep their exact storage format.
textureLoad needs no sampler. Filtering requires a sampler descriptor and an explicit LOD:
Filtering samplers are valid only with filterable float textures. Integer and unfilterable-float textures require non-filtering samplers.
Dispatch
Dispatch counts and resource binding counts are checked against the active WebGPU device limits before commands are encoded.
Dependency scheduling
Consecutive compute passes form a dependency graph. Descriptors provide the read and write sets, so declaration order is only a stable tie-break for independent passes.
- A
currentreader runs after the resource’s writer. - An
initialreader runs before the writer. - One logical resource can have at most one writer in a graph segment.
- Cycles and overlapping read/write aliases in one dispatch are rejected.
- A fragment-feedback pass is an opaque barrier; compute work is not moved across it.
All dispatches are encoded in topological order on one command encoder. No CPU wait or intermediate readback is required.
Interactive examples
Use the playground to run and edit the complete examples in Svelte, React, or Vue:
- Data Mosh streams real video into GPU motion estimation and temporal feedback passes to produce data moshing without CPU readback.
- Liquid Simulation samples a filtered propagation medium, iterates a damped wave state through private A/B textures, and publishes it to a downstream caustic renderer.
Each example exposes its application, runtime, and WGSL files in the editor. Switch frameworks from the playground header without changing the resource contract.
Borrowed WebGPU resources
Advanced integrations may replace a material key with a typed external reference:
External texture, view, buffer, and sampler references are borrowed. Motion GPU never destroys them. Providers run once per pass per rendered frame and receive { device, width, height, time, delta }; the returned object is captured for graph validation and binding. resourceId must remain the same for the same logical allocation, including aliases and views. A provider must return a resource created for the current device after device recovery.
Metadata is part of the contract: textures declare format and usage, views add dimension and mip count, buffers add WGSL type and size, and samplers add binding type. Object changes refresh a bind group but do not rebuild a pipeline while topology and metadata remain unchanged.
Frame integration and caching
Compute and fragment-feedback passes are pre-scene. Render passes remain post-scene. Pipelines are cached by shader and resource topology, not material keys or current GPU object identities. A stable frame creates no pipeline, layout, bind group, or texture view.
Compilation failures use COMPUTE_COMPILATION_FAILED with source mapping. Descriptor, graph, and external-resource failures have separate stable codes listed in Error Handling.
The Particle Icosahedron demo shows a storage-texture writer; the Rubik’s Cube demo uses explicit storage-buffer access; the TanStack demo composes independent compute producers. See Storage Buffers, Textures, and Passes API.