← Extensions to GPUI

Experimental spatial canvas. Camera, retained scenes and clipped procedural grids.

Open spatial card canvas ↗Demo source

Open Mandelbrot explorer ↗Demo source

Spatial canvas

xgpui-canvas adds a spatial viewport to GPUI: an f64 pan/zoom camera, retained scenes with BVH culling and hit testing, LOD hints, alignment snapping, and a procedural line/dot grid. Native and browser labs show the same camera driving cards and fractals. The native fractal uses coherent viewport images; the browser companion uses bounded CPU rendering.

Try it

Both support WebGPU and WebGL2. Run the native labs from the repository root:

just canvas-lab
just canvas-lab --mandelbrot
ActionCardsMandelbrot
PanScroll, middle drag or Space-dragLeft drag
ZoomPinch; browser also supports Ctrl/Cmd+wheelPinch; browser also supports wheel
Select/moveClick or Shift-drag; drag selected cards—
Bypass snapping / cancelAlt/Option / Escape—
ResetR or browser Reset buttonR or browser Reset button

Click/drag the card minimap to navigate. Native T switches minimap/live preview; M toggles the panel. Browser buttons change scene size and grid style.

Use it

For development against this checkout:

xgpui-canvas = { path = "path/to/extensions/crates/xgpui-canvas", features = ["gpui"] }

Retain a Camera2D, Scene<T> and GridPainter in view state. Cull before building children, then place them using the returned screen bounds:

for entry in scene.visible(camera, viewport_size) {
    // entry.item: your data and world bounds
    // entry.screen_bounds: viewport-local position and size
    // entry.detail: Point, Bounds or Full
}

Canvas::with_grid_options(camera, &grid, GridOptions {
    spacing: 40.,
    major_interval: 4,
    ..Default::default()
}).size_full().children(children)

Canvas clips and paints the grid. Project child positions, sizes and fonts explicitly. GridOptions also controls line/dot style and RGBA color.

Subtract the viewport origin from pointer coordinates before calling screen_to_world or zoom_at. Feed PanGesture deltas to camera.pan_by; end the gesture on release, Escape or focus loss. Use scene.hit_test for selection, scene.snap_translation for alignment, and scene.cache_key() to invalidate geometry caches.

See the crate API, browser implementation and native lab controls and benchmarks.

Scope and performance

The native fractal presents complete buffered viewport images, reprojecting the last completed image during navigation. Shallow Metal views use GPU calculation with linear P3 float textures at a steady resolution; deep views use f64 CPU calculation, retain sharper completed images where possible, and blend in detail after settling. GPU deep-zoom perturbation is not implemented. The browser retains bounded CPU slices, refining a coarse image to at most 480×360; f64 precision and a 2,048-iteration cap limit deep detail. The native live preview uses GPU readback; the default minimap avoids that cost.

Local macOS measurements averaged 16.7 ms/frame in normal card views and 23.3 ms in the dense 100k overview. These are observations, not guarantees. xgpui-canvas has 19 unit tests (camera, scene/BVH, snapping, overview, input and grid). The canvas-lab binary adds 13 tests covering navigation, launch validation, CPU Mandelbrot scheduling/precision and, on macOS, Metal pixel comparison with the f64 reference; a manual GPU timing test is ignored by default. Run them with:

cargo test --manifest-path extensions/crates/xgpui-canvas/Cargo.toml --all-features
cargo test --manifest-path apps/xgpui-ext-lab/Cargo.toml --bin canvas-lab

Both browser demos were checked in Chromium with WebGPU and WebGL2. Native runtime acceptance: macOS arm64 smoke and visual checks recorded; Windows native labs and just lab-test owner-confirmed on 2026-11-04. Linux runtime acceptance is deferred until a Linux environment is available.

Rotation, isometric grids, general subtree transforms, reusable selection/map widgets and large-scene indexing/rendering improvements remain follow-ups in issue #54.

GPUI public API changes: additions and compatibility

Canvas uses existing GPUI containers, clipping and the shader pipeline, with no new GPUI signatures or fields. See integration compatibility.