← Overview Stage 7 / Rendering Pipeline
Stage 7 of 7

Rendering Pipeline

From cx.notify() to photons: GPUI calls each view's render(), performs layout, calls paint() which emits GPU primitives into a Scene, then gpui_wgpu submits batched draw calls to the GPU driver.

Frame Lifecycle
1
cx.notify() — schedule redraw
Any entity update (buffer edit, LSP result, cursor move) calls cx.notify(). GPUI queues a redraw for the affected window. Multiple notifies within the same event coalesce into one frame.
2
Render phase — build element tree
GPUI calls Workspace::render(window, cx) which recursively calls child views' render(). Each view returns an element tree — plain Rust data structures implementing the Element / RenderOnce traits. No drawing happens yet.
3
Layout phase — flexbox pass
GPUI performs a top-down flexbox layout, computing the pixel Bounds for every element. The layout algorithm runs entirely on the CPU in one pass over the tree.
4
Paint phase — emit primitives
Each element's paint(bounds, scene, cx) is called in tree order. Elements push draw commands (quads, glyphs, underlines, paths) into the Scene. EditorElement::paint() is the heaviest step — see below.
5
GPU submission (gpui_wgpu)
The completed Scene is handed to gpui_wgpu, which sorts draw commands by layer/depth, batches them into WebGPU render passes, and submits to the platform GPU (Metal on macOS, Vulkan on Linux, DX12 on Windows).
6
Present
The swap chain presents the completed framebuffer to the display. On macOS this syncs to the display's vsync via CAMetalLayer.
EditorElement::paint — What It Draws

element.rs:9786 implements the Element trait for the editor. Its paint() method is called once per frame with the editor's computed bounds.

It begins by taking a DisplaySnapshot — an immutable copy of all buffer, display-map, and diagnostic state — then works line by line through the visible rows:

line background
Highlighted current line, search matches, selection backgrounds — quads behind text
gutter
Line numbers, git diff bars, breakpoint icons — left column quads + sprites
text glyphs
Shaped glyphs from TextSystem, syntax-highlighted by token colour from the theme
inlay hints
LSP virtual text in a dimmer colour, interleaved between buffer characters
cursors
Blinking or steady cursor quads; multiple cursors drawn in the theme's cursor colour
underlines
Error/warning squiggles from diagnostics; link underlines on hover
fold indicators
Chevron icons in the gutter over foldable ranges
diff hunks
Green/red bars and inline added/deleted text from git diff
Scene — Accumulated GPU Primitives
Scene scene.rs:27
pub struct Scene { paint_operations: Vec<PaintOperation>, quads: Vec<Quad>, // filled rectangles (backgrounds, borders) paths: Vec<Path<ScaledPixels>>, // vector paths underlines: Vec<Underline>, monochrome_sprites: Vec<MonochromeSprite>, // icon/glyph atlas lookups polychrome_sprites: Vec<PolychromeSprite>, // colour images surfaces: Vec<Surface>, // media surfaces (video frames) }

Primitives are added to the scene in paint order (back to front). The WGPU layer re-sorts by z-order and merges adjacent primitives of the same type into batched draw calls, minimising GPU state changes.

WGPU Rendering Stack

All rendering goes through gpui_wgpu, which abstracts over platform-specific GPU APIs:

Scene (GPUI) Platform-agnostic primitives
gpui_wgpu renderer Translates Scene → WebGPU commands, manages glyph atlas
wgpu crate Safe Rust GPU API abstraction layer
Metal / Vulkan / DX12 Native GPU driver on macOS / Linux / Windows
Glyph atlas: text glyphs are rasterized once into a shared GPU texture atlas. Each MonochromeSprite primitive is just a UV rectangle pointing into this atlas — no per-frame font rasterization unless the atlas overflows or the DPI changes.
Code References