Skip to main content

Debugging GPU Command Graphs

Overview​

Use GPU Graph to inspect graph-level costs and node summaries, then GPU Trace to examine one encoding over time. Both consume collected diagnostics; neither needs to copy the source dataset back to JavaScript.

Explore the panels​

The live trace viewer below exposes graph diagnostics and the GPU Trace panel alongside a real GPU-resident workflow. Open its panel controls to inspect graph metrics and sampled execution. The trace dataset visualized by the example is separate from the execution trace of its own graph.

Loading interactive example…

Open the full trace viewer for more room. This example requires WebGPU; GPU timings also require timestamp-query support.

GPU Graph: find the expensive stage​

The GPU Graph tab uses the example-side GPUCommandGraphDebugPanel, which wraps GPUCommandGraphInspectorPanel and retains its snapshot when the tab is unmounted. These render snapshots from GPUCommandGraphInspector. Select a graph to inspect:

  • encoding count and retained CPU/GPU p50 and p95 duration summaries;
  • logical versus physical resource allocation and transient reuse;
  • nodes in compiled schedule order with per-node timing summaries;
  • application-supplied counters, such as candidates, matches, or overflow.

CPU time measures command encoding. GPU time measures sampled GPU work. A missing GPU sample is not a zero-duration result. Counter collection is explicit: the inspector stores supplied scalar values and does not read their buffers itself.

GPU Trace: inspect one encoding​

GPUTracePanel displays the latest report as CPU and GPU spans, preserving gaps between nodes. Hover or keyboard-focus a span for node details. Separate CPU and GPU clocks are the default; when correlation is available, Combined timeline (estimated) aligns them and shows uncertainty. That alignment is an estimate, not exact CPU/GPU clock synchronization.

Copy nodes remain CPU-timed. Skipped nodes have no GPU span. Enabling per-node GPU timestamps also changes compute-pass coalescing, so compare representative sampled and unprofiled runs.

Collect once, show in both panels​

The inspector belongs to the package; the DOM panels are reusable example helpers. In an example, import GPUCommandGraphInspectorPanel from examples/gpu-command-graph-inspector-panel.ts and GPUTracePanel from examples/gpu-trace-panel.ts. Include tracePanel.panel in the application's panel collection and give the graph panel its own host element.

import {GPUCommandGraphInspector} from '@luma.gl/gpgpu/gpu-core';

const inspector = new GPUCommandGraphInspector({maxSamples: 120});
const observation = inspector.observeGraph(compiled);

const commandEncoder = device.createCommandEncoder();
const encoding = observation.encode(commandEncoder, {parameters});
device.submit(commandEncoder.finish());

// graphPanel and tracePanel are the mounted example helpers.
graphPanel.update(inspector.getSnapshot(), compiled.id);
tracePanel.update(encoding.stats, compiled.id);

// Sample after submission, using an encoder configured for timestamp queries.
if (encoding.canReadGPUTimings) {
const report = await observation.recordGPUTimings(encoding);
graphPanel.update(inspector.getSnapshot(), compiled.id);
tracePanel.update(report, compiled.id);
}

Read timings at a chosen diagnostic cadence. Reuse the returned report for both views rather than requesting another read. Detach the observation when removing the graph; destroy the panel helpers and compiled graph according to their ownership.

Diagnose common symptoms​

SymptomInspectNext step
Compilation rejects a resource aliasDeclared reads, writes, views, and usagesCorrect overlapping writable bindings or separate stages
CPU p95 rises while GPU time is stableCompilation cadence and encoding node countCache compilation and inspect unnecessary per-frame setup
GPU time rises with sparse outputsCandidate counters and per-node spansReduce candidate work before compaction or expensive analysis
Transient memory is unexpectedly highLifetimes, compatibility, logical/physical countsShorten unnecessary lifetimes and review retained outputs
Results are stale after skipping workConditions and downstream readsCondition consumers or initialize/version retained output
Counts hit capacityDemand and overflow countersIncrease explicit capacity or process bounded steps

See the command graph instrumentation API for query setup and report semantics, and execution techniques for the allocation and scheduling rules behind the panels.