Rendering Pipeline
The GPU rendering stage is the final step in the pipeline. It consumes a DisplayList (from lui-display-list) and produces a frame via any RenderBackend implementation.
Architecture
The rendering layer is split into three crates:
lui-display-list— backend-agnostic IR (DisplayList,Quad,GlyphQuad,ImageQuad,ClipRange,Rect,Color,FrameOutcome)lui-render-api— theRenderBackendtrait that every GPU renderer implementslui-renderer-wgpu— the wgpu reference backend
Renderer Setup (wgpu)
The wgpu backend (renderers/lui-renderer-wgpu/src/lib.rs) is created with:
use lui_renderer_wgpu::Renderer;
let renderer = pollster::block_on(Renderer::new(window, width, height));
This acquires a wgpu Instance, Adapter, Device, Queue, and Surface, then initializes the three GPU pipelines.
Three GPU Pipelines
Quad Pipeline (quad_pipeline.rs)
Instanced rectangle rendering with SDF (Signed Distance Field) shading:
- Background fills — solid colors, with optional rounded corners via SDF
- Borders — solid, dashed, and dotted stroke patterns per side
- Selection highlights — text selection background quads
- Scrollbars — track and thumb rectangles
The WGSL shader (quad.wgsl) computes per-pixel SDF distance for rounded rectangles, enabling smooth anti-aliased corners and borders.
Glyph Pipeline (glyph_pipeline.rs)
Text rendering from the glyph atlas:
- Instanced glyph quads — one instance per glyph, carrying UV coords, position, and color
- Alpha-tested — discards fragments below a coverage threshold from the atlas texture
- Dynamic offset — per-draw uniform buffer for clip rect and radii
Image Pipeline (image_pipeline.rs)
Textured rectangle rendering:
<img>elements — decoded images uploaded as GPU textures- Background images — CSS
background-image(URLs and gradients) - Animated GIF/WebP — frame selection driven by a process-wide clock
DisplayList Consumption
Renderer::render(&DisplayList) walks the display list and issues draw commands:
- Iterate
DisplayList::quadsfor background/fill commands - Iterate
DisplayList::glyphsfor text commands - Iterate
DisplayList::imagesfor image commands - For each clip range, pre-compute scissor rects
Clipping System
Overflow clipping uses a two-level approach:
- CPU scissor pre-pass —
set_scissor_rectclips to rectangular bounds - GPU SDF discard — fragment shader discards pixels outside rounded masks for
border-radiusclipping - Clip ranges — quad/glyph instances are partitioned into ranges, each tagged with a clip index
Screen Capture
renderer.capture_to(vec); // Capture full surface
renderer.capture_rect_to(vec, r); // Capture a region
Outputs RGBA8 pixel data as a Vec<u8>. The winit harness uses this for F12 screenshots.
Performance Notes
- Instance buffers grow in powers of two, avoiding per-frame allocation
- Uniform buffers use dynamic offsets to pack multiple draw calls into one binding
- Draw calls are batched by pipeline (quad → glyph → image) within each clip range