Skip to main content

GPU Core

From v10ExperimentalWebGPU required

Overview

GPU Core is the experimental WebGPU dataflow and scheduling layer in @luma.gl/gpgpu/gpu-core. Applications and reusable contributors declare resources, compute/copy/render nodes, dependencies, conditions, and work estimates. A compiled graph allocates compatible transient resources, orders read/write hazards (resource conflicts), and records work into a caller-owned command encoder.

GPU Core does not own command submission or the application frame loop. This makes it suitable for GPU-resident workflows that combine analysis, culling, indirect rendering, and bounded readback without synchronizing the source dataset through JavaScript.

The small WebGPU leap behind GPU Core

note

For a WebGL developer, the architecture can look more exotic than it is. A handful of WebGPU capabilities supply the missing links:

  • Compute shaders and storage buffers let one stage produce general-purpose data that another stage consumes without encoding the data as textures or returning it to JavaScript.
  • GPU-writable indirect draw and dispatch arguments let a later stage consume a GPU-produced count without waiting for a CPU readback.
  • Explicit resource uses and command encoding make the reads, writes, and execution boundaries concrete enough for GPU Core to derive hazards, allocations, and a reusable schedule.

WebGL can approximate individual pieces with textures or transform feedback. What it lacks is the straightforward, general chain from compute-produced data to data-dependent compute and rendering.

GPU-resident source data

selection and transformation

scan, compaction, sorting, or aggregation

bounded output and indirect commands

rendering, picking, or small readback

When to use it

Use GPU Core when an application needs several GPU operations to share resources and execute as one repeatable plan. It is especially useful when intermediate data should remain GPU-resident, output sizes are bounded but data-dependent, later work consumes indirect counts, or work must be conditional, measured, or spread across frames.

Prefer direct luma.gl commands for a small fixed pass sequence that does not benefit from shared allocation, hazard analysis, work planning, or graph inspection.

Choose a learning path

You do not need to read the complete API reference before building a graph. Start with the path closest to the problem you are solving; each one is deliberately three short stops.

Live example

This small interactive pipeline exposes the intermediate values normally kept inside GPU buffers. Click source rows, then inspect how mask, exclusive scan, stable scatter, and an indirect draw fit together.

Interactive dataflow

From a sparse decision to one indirect draw

Select source rows, then follow the GPU-resident values through mask, exclusive scan, stable scatter, and the final indirect command.

OperationApplication compute node or GPUMask

One flag per source row records a keep or discard decision. Click a source value to change this stage.

Publishesone canonical 0/1 flag per source row
Source valueClick to keep or discard
Keep mask0 discards · 1 keeps
10101001
Exclusive scanselected rows before this row
01122333
Packed output4 valid rows
#08#25#49#74
vertexCount6
instanceCount4GPU-written
firstVertex0
firstInstance0
drawIndirect(buffer, 0)

Continue with the complete tutorial and WebGPU comparison →

Quick start

import {GPUCommandGraph, GPUScan} from '@luma.gl/gpgpu/gpu-core';

const graph = new GPUCommandGraph(device, {id: 'prefix-sum'});
const input = graph.importBuffer(
{id: 'input', byteLength: inputBuffer.byteLength, usage: inputBuffer.usage},
inputBuffer
);
const output = graph.importBuffer(
{id: 'output', byteLength: outputBuffer.byteLength, usage: outputBuffer.usage},
outputBuffer
);
const values = graph.createDataView(input, {format: 'uint32', length});
const prefixes = graph.createDataView(output, {format: 'uint32', length});

graph.add(new GPUScan({id: 'scan', input: values, output: prefixes}));

const compiledGraph = graph.compile();
const commandEncoder = device.createCommandEncoder();
compiledGraph.encode(commandEncoder, {parameters: undefined});
device.submit(commandEncoder.finish());

Contributors add resources and nodes but do not compile or submit the graph. The application retains control of synchronization, frame pacing, readback, cancellation, and publication.

Core concepts and data model

  • Logical resources describe buffers, textures, views, ownership, and intended uses.
  • Nodes declare compute, copy, or render work plus every resource range they read or write.
  • Contributors add reusable operations without taking over graph lifecycle.
  • Compilation derives hazards, execution order, physical allocation, and diagnostics.
  • Encoding records the immutable compiled plan using current parameters and imported resources.
  • Bounded outputs combine fixed-capacity storage with counts or indirect command records.

See Execution and composition for resource ownership, hazard scheduling, conditions, resumable execution, budgeting, instrumentation, and autotuning. See GPUCommandGraph for the construction, compilation, and encoding API. The GPU Core cookbook maps common application outcomes to the operations that compose them.

GPU Core feature card

CapabilityWhat it enablesPublic surface
Declarative graphOne schedule for GPU preparation, analysis, indirect drawing, and pickingGPUCommandGraph and graph contributors
Composable primitivesMasks, scans, sorting, traversal, BVHs, binning, reductions, histograms, FFTs, picking, and readbackGPU* contributors from @luma.gl/experimental
GPU-driven outputBounded counts, compacted IDs, and indirect commands without source-data readbackGPUScan, GPUCompaction, DrawCommandBuffer
Batch-preserving executionOrdered GPUVector chunks without silently repacking a datasetGraphVectorView and chunk-aware contributors
Conditional executionCPU-known work can be omitted and GPU-known empty work can resolve through indirect dispatchCPU predicates and GPU indirect conditions
Multi-frame executionLarge immutable plans can advance in bounded resumable stepsplanExecution() and resumable execution
Adaptive budgetsMeasured queue time can tune bounded step sizesGPUCommandGraphExecutionBudgetController
Kernel autotuningEquivalent supported kernels can be selected per adapter and workloadGPUCommandGraphAutotuner
InstrumentationEncode time, GPU timing, work estimates, allocations, dispatches, draws, and custom countersGPUCommandGraphInspector and timing reports
Hazard schedulingRAW, WAR, and WAW dependencies derive from resource usesCompiled schedule diagnostics
Transient reuseCompatible resources share allocations when lifetimes do not overlapAllocation plan and reuse statistics
ValidationBinding aliases, device limits, unsupported features, and incomplete estimates fail before submissionCompilation and preflight reports
Explicit ownershipApplications retain submission, readback cadence, cancellation, and UI publicationCompile-and-encode lifecycle

Examples

  • GPU Sort compares graph-native segmented and unsegmented GPU sorting while reporting the selected execution path and measured throughput.
  • GPU Trace Viewer combines hierarchy, selection, indexing, aggregation, dependency traversal, picking, and indirect rendering while preserving canonical span identity.
  • GPU Data Analysis composes reductions, histograms, filtered aggregations, and grid bins.
  • GPU Frustum Culling compacts visible scene instances and writes an indirect draw count.
  • Vector Field Lab composes analytic volume sampling with 3D gradient, divergence, curl, and Laplacian nodes and ray marches their outputs directly.

Operations and API index

FamilyOperations
Graph executionGPUCommandGraph, CompiledGPUCommandGraph, GPUCommandGraphExecution, GPUCommandGraphExecutionBudgetController, GPUCommandGraphAutotuner, GPUCommandGraphInspector, GraphExternalTextureHandle, GPUTextureHistory, GPUReadbackRing, DrawCommandBuffer
Data movementGPUUint32Gather selects or reorders packed uint32 rows; GPUByteRangeGather concatenates variable byte ranges; GPULZByteDecompressor resolves literal and backreference spans for one format-specific LZ stream; GPULZByteBatchDecompressor expands many independently described LZ streams in one dispatch. These contribute bounded graph-native compute operations.
Selection and compactionGPUScan, GPUScanUint64 for exceptional split-word inclusive 64-bit prefixes, GPUGallopingSearch, GPUCompaction, GPUFlagOffsets, GPUSegmentOffsets, GPUSegmentedLayout, GPUIndexedRangeCompaction, GPUPartitionedIndexedRangeCompaction, GPUChunkedIndexedScatter, GPUTextSelection, GPUMask, GPUVisibilityWorkflow, GPUVirtualGeometrySelection
Hierarchies and traversalGPUHierarchyLayout, GPUGraphTraversal, GPUAncestorProjection
Sorting and aggregationGPUSort, GPUBatchSort, GPUSegmentedSort, GPUFFT2D, GPUReduction, GPUHistogram, GPUGroupAggregation
Sampled fieldsGPUFiniteDifference2D and GPUFiniteDifference3D for gradient, divergence, curl, and Laplacian evaluation with explicit spacing, boundary policy, and independent input/output partitions
Spatial indexingGPUGridBinning, GPUGridAggregation, GPUGridIndex, GPUGridIndexQuery, GPUPointSpatialFilter, GPUBVH, GPUSegmentedBVH, GPUBVHQuery
GPU scenesGPUScene, scene adapters, draw generation, resource groups, GPUIndexPickingTarget
Hash indexes and joinsGPUHashIndex, GPUBatchHashIndex, GPUHashJoin, GPUBatchHashJoin

Trace-domain algorithms are indexed from the @luma.gl/experimental/gpu-trace overview.

Limits and compatibility

  • GPU Core is experimental and requires WebGPU.
  • Compiled graph topology and capacities are immutable; parameters and compatible imports may vary.
  • Capacity-dependent outputs report truncation or incomplete results instead of reallocating.
  • Device features and limits are checked during construction, compilation, or explicit preflight.
  • Readback and queue submission remain explicit application responsibilities.