Copied to clipboard
v1.25.202 · Modular GPUI Architecture

GPUI.
Take a bite.

Stop forking. Start swapping.

Zed’s GPUI is fast, but tightly coupled. bite-gpui breaks the engine into five standalone crates. Tweak the frame pipeline, drop in BiDi text layout, or run headless tests. Your div() code stays 100% compatible.

Scroll to unstack the layers
gpui_platform Platform SPI
Hardware and OS bindings. One of macOS, Linux, Windows or Web compiles in via cfg(target_os).
gpui_engine Scene & Render
Scene intermediate representation (IR), text layout bindings, and renderer traits.
gpui_types Zero-dep Leaf
Pixels, Bounds, Point, and Rgba. Pure geometry primitives with zero GPUI dependencies.
gpui_authoring Reactive DSL
Reactive stores, div() builders, and a window split into render and event halves.
gpui_runtime Application Harness
App lifecycle, native OS event dispatch, and pluggable FramePipeline decorators.
Wrap · Swap · Shove · Serve

Four ways to bite.

Pace the frame, replace a seam, composite your own pixels, or run on a platform of your own. Every one keeps div() untouched.

01

Pace the frame.

Wrap

Implements FramePipeline and delegates. It is handed every pass of every frame it admits, forwards the ones it does not change, and decides the ones it does — including whether the frame runs at all.

  • decorates the frame pipeline
  • stacks in any order, any number
  • consumes a trait rather than freezing one
The wrap inventory →
02

Replace a seam.

Swap

Implements one of the algorithm seams and is installed at bootstrap in place of the default. One implementation per seam, chosen when the application is built.

  • replaces the algorithm
  • one per seam, never beside it
  • freezes the trait on publication
The swap shelf →
03

Composite your own.

Shove

Replaces no seam and decorates no pipeline. It builds on the published surface and pushes foreign pixels into the frame — a 3D viewport, a decoded video frame, or a texture you computed.

  • surface() and gpu_canvas()
  • same-device or exported handle
  • sits above the facade
Bring your own pixels →
04

Bring your own host.

Serve

Supplies the platform the application runs on: one of the four built-in backends compiled in by cfg, or a Platform implementation of your own.

  • Metal, Direct3D 11, X11/Wayland, WebGPU
  • one backend per build, by cfg
  • or a Platform of your own
Bring your own platform →
Combo Studio · Sides & Drinks

Build your combo.

Upstream GPUI gives you a fixed meal—take it or leave it. bite-gpui lets you customize every layer. Pick your add-on sides and sauces (Step 1), pair your platform drink (Step 2), and ship. Zero engine forks, and your UI views never recompile.

➔
Extra Sides & Sauces Stack as many pipeline add-ons as you want. They snap directly into your frame loop.
3 sides added Zero engine forks
Benchmarks · Reproducible data

Measured, not promised.

Every bar below maps directly to an executable benchmark in the repository. Tested on real hardware — an Intel i7-8750H laptop running rustc 1.98.1 under normal background desktop load (no synthetic CPU pinning). Clone bite-gpui/gpui_parley , run the commands, and verify the timings yourself.

Raster size lattice 3.3 ms → 41.1 µs per frame · 80× faster

The problem: transforming font size dynamically on 30 lines per frame constantly thrashes standard glyph atlases.

The fix: rounding raster sizes to a deterministic lattice drops atlas cache misses from 154 a frame to zero, shrinking the atlas footprint from 32,508 entries down to 644.

Verify:  $ cargo run --release --example raster_cost

Glyph hinting cache 3,480 → 30 instances per frame · 116× fewer

The problem: upstream GPUI runs a face's bytecode hinting program per glyph instance (~31 µs each).

The fix: keying the cache directly to (face, size) builds just 30 instances per frame where an uncached hinting run would execute 3,480 times.

Verify:  $ cargo run --release --example raster_cost

Text as vector geometry 26.7 ms → 0.69 ms per screenful · 39× CPU reduction

The problem: rasterizing dense text on every frame devours CPU cycles.

The fix: outlines are tessellated once (639 µs). Subsequent frames stream 218,322 pre-computed vertices straight to the GPU in 48 µs. You trade bus traffic for massive frame savings.

Verify:  $ cargo run --release --example vector_cost

Quickstart

Up and running in four lines.

Start with the facade, then peel off layers as you need them.

# The whole stack, behind one facade
cargo add bite-gpui

# …or cherry-pick individual tiers
cargo add bite-gp-platform bite-gp-engine bite-gp-types

# …then swap a seam for a published alternative
cargo add bite-gp-parley
use gpui::*;

fn main() {
    application().run(|cx: &mut App| {
        cx.open_window(WindowOptions::default(), |_, cx| {
            cx.new(|_| MyView)
        }).unwrap();
    });
}
use std::cell::RefCell;
use std::rc::Rc;
use gpui::*;
use gpui_parley::ParleyTextSystem;

fn main() {
    let metrics = Rc::new(RefCell::new(PhaseMetrics::default()));

    application()
        .with_text_system(ParleyTextSystem::new())
        .with_frame_pipeline({
            let metrics = metrics.clone();
            move |_window_id| {
                Box::new(
                    StandardImmediatePipeline
                        .max_fps(60)
                        .instrumented(metrics.clone())
                )
            }
        })
        .run(|cx: &mut App| { /* … */ });
}
#[gpui::test]
fn renders_without_a_display(cx: &mut TestAppContext) {
    let window = cx.update(|cx| {
        cx.open_window(Default::default(), |_, cx| cx.new(|_| MyView))
            .unwrap()
    });
    let mut cx = VisualTestContext::from_window(window.into(), cx);

    // The window is drawn in-process: no display server, no GPU.
    let bounds = cx.debug_bounds("submit").unwrap();
    assert_eq!(bounds.size.height, px(32.));
}