Skip to main content

GPU Trace Exploration

Overview

@luma.gl/experimental/lutrace is an optional GPU-native execution-trace module. It owns canonical span schemas, process/thread relationships, hierarchy parents, dependency links, filtering policies, linked-span focus, and trace-specific timeline picking without adding those concepts to the generic command graph or flat GPU scene API.

Use lutrace when an application needs to navigate a distributed system trace, inspect a browser performance recording, understand a GPU capture, explore a build-system schedule, or analyze a scientific workflow with both hierarchical ownership and explicit cross-task dependencies. Source data remains GPU-resident while time windows, expansion state, selected spans, and visibility change interactively.

The scene-backed explorer below combines canonical trace ingestion, process/thread collapse, linked-span selection, stable indirect drawing, and trace-aware GPU picking. Expand or collapse a process, change the classification filters, and click a span to see the same compiled GPU graph respond to small control-buffer updates.

GitHub

Concepts

A trace is an application domain, not a command-graph feature

The generic GPUCommandGraph knows about buffers, textures, compute passes, render passes, hazards, and encoding. It does not need processes, threads, spans, or dependency edges to schedule a particle simulation, culling renderer, image filter, or GPU analytics pipeline.

lutrace depends on those reusable scheduling and rendering primitives, but the generic primitives do not depend on lutrace. Applications that never display execution timelines therefore do not import trace-domain schemas or interaction policies.

import {GPUCommandGraph} from '@luma.gl/experimental';
import {
GPUTraceInteraction,
GPUTraceScene,
getGPUTracePickingShader
} from '@luma.gl/experimental/lutrace';

GPUTraceScene accepts packed eight-word span records and four-word dependency links. Span records describe time, duration, lane, render group, process, thread, stable object identity, and classification bits. Separate parent references represent structural nesting, while incoming and outgoing adjacency represent arbitrary cross-process dependencies.

The module exports GPU_TRACE_SPAN_RECORD_WORD_LENGTH and GPU_TRACE_LINK_RECORD_WORD_LENGTH so producers, demonstration datasets, and consumers agree on one canonical memory layout. Empty and uneven source partitions remain visible; a compacted display position never replaces the stable canonical row or application object ID.

Each trace span also projects into a normal GPUScene record. Generic visibility, renderer-owned resource groups, and indirect draw commands can therefore render a trace without adding trace-specific fields to the scene database.

For example, a distributed request can retain canonical row 417, application object ID 9021, and compacted visible position 12 simultaneously. Dependencies and picking resolve row 417; application inspection resolves object 9021; a compacted label pass consumes position 12. Treating these identities as interchangeable would attach selections or dependency endpoints to the wrong operation whenever filtering changes.

Interactive policies change control state, not graph topology

GPUTraceInteraction combines reusable graph operations into a fixed trace workflow:

  1. Process and thread expansion determine visible timeline lanes.
  2. A scanned hierarchy layout updates effective row offsets.
  3. Time, minimum-duration, and classification policies reject irrelevant spans.
  4. Selected spans expand over bounded incoming, outgoing, or bidirectional dependency links.
  5. Hidden children project onto their nearest visible ancestors.
  6. Stable compaction and scene draw generation publish GPU-resident indirect commands.

Panning, collapsing a thread, focusing on a critical path, or changing an error filter updates small caller-owned GPU control buffers. The application re-encodes its existing compiled graph; it does not rebuild a JavaScript span list, perform CPU draw selection, or hand submission ownership to lutrace.

The hierarchy-first trace viewer below demonstrates the same underlying generic layout, dependency traversal, filtering, and stable row identity from a different application composition. Collapse a process or isolate linked spans to compare its direct primitive orchestration with the scene-backed workflow above.

GitHub

Trace picking is separate from generic picking infrastructure

getGPUTracePickingShader produces a compute shader for a timeline coordinate. It considers only spans marked visible by the current interaction policy, reconstructs effective display lanes from GPU-scanned thread offsets, and atomically publishes the lowest matching canonical source-row identity.

const pickingSource = getGPUTracePickingShader(trace.stats.spanCount, lanesPerThread);

Applications still own the pick request, result buffer, command graph, readback, and highlighting. General-purpose picking targets remain available separately; this helper adds only the trace-specific time/lane interpretation.

Choose the right level of composition

RequirementRecommended APIReason
Schedule arbitrary compute and render passesGPUCommandGraphNo trace assumptions or domain-specific schemas
Upload canonical spans, ownership, hierarchy, and dependenciesGPUTraceScenePreserves source identity and projects into a generic GPUScene
Apply reusable timeline controls without rebuilding graph topologyGPUTraceInteractionComposes hierarchy, focus, visibility, ancestors, and indirect drawing
Resolve a timeline coordinate to its visible canonical spangetGPUTracePickingShaderUnderstands trace timing, scanned lanes, and interaction visibility
Control queue submission, asynchronous readback, or UI stateApplication-owned codeKeeps scheduling, resource lifetime, and presentation policies explicit

The first embedded explorer uses all four GPU layers together. The hierarchy-first explorer shows that applications can also compose the generic primitives directly when they need a different rendering model or interaction policy.

Public API

ExportResponsibility
GPUTraceSceneCanonical GPU-resident spans, process/thread ownership, parents, links, partitions, and generic scene projection
GPUTraceInteractionReusable GPU hierarchy, time filtering, classification, dependency focus, ancestor retention, visibility, and indirect draws
GPU_TRACE_SPAN_RECORD_WORD_LENGTHNumber of 32-bit words in one canonical trace span
GPU_TRACE_LINK_RECORD_WORD_LENGTHNumber of 32-bit words in one dependency record
getGPUTracePickingShaderCapacity-bounded, visible-span-aware timeline picking shader

Trace-specific classes, constants, helpers, and types are exported only from @luma.gl/experimental/lutrace; they are intentionally absent from the root @luma.gl/experimental namespace.