Skip to main content

Rendering Pipeline Overview

The renderer (wgpu-html-renderer) converts a DisplayList into GPU draw calls. It owns the wgpu device, surface, and three GPU pipelines.

DisplayList

pub enum DisplayCommandKind {
Quad(Quad),
Glyph(GlyphQuad),
Image(ImageQuad),
}

pub struct DisplayList {
commands: Vec<DisplayCommand>,
clips: Vec<ClipSlot>,
glyph_range: Option<(usize, usize)>,
quad_range: Option<(usize, usize)>,
image_range: Option<(usize, usize)>,
}

Each DisplayCommand carries:

  • A DisplayCommandKind (Quad, Glyph, or Image).
  • A clip_index — which scissor/clip slot constrains it.
  • The absolute z-order (push-order through paint traversal).

Three GPU Pipelines

PipelineShaderWhat it draws
Quad (quad.wgsl)Instanced SDF quadsBackgrounds, borders, scrollbars, decorations
Glyph (glyph.wgsl)Instanced textured quadsText glyphs from the R8 atlas
ImageInstanced textured quads<img> elements, background-image

Single Render Pass

Each frame renders in one pass (within the same command encoder):

1. Clear render target to clear_color
2. Quad pipeline → draw all quads
3. Image pipeline → draw all images
4. Glyph pipeline → draw all glyphs

Drawing order preserves the DisplayList's z-order within each command range. The render pass is structured so text appears on top of backgrounds/borders.

sRGB Surface

The surface texture uses an sRGB format by default (selected from wgpu::SurfaceCapabilities). This means:

  • Colors written by the quad pipeline are stored in sRGB-encoded bytes.
  • The glyph pass uses a non-sRGB view of the same texture for gamma-correct display-space blending — anti-aliased text multiplies coverage × color in linear space, then the GPU's sRGB encode on write (or lack thereof, for the glyph view) produces correct visual results.

Vsync

present_mode: wgpu::PresentMode::AutoVsync,

The surface uses VSync by default. This can be changed by the host before calling surface.configure().

Screenshot Capabilities

The renderer supports off-screen capture:

renderer.capture_to(&display_list, width, height, "frame.png")?;
renderer.capture_rect_to(&display_list, region, "region.png")?;

Captures allocate an off-screen render target, replay the entire display list into it, and write the result as a PNG. This works even for regions outside the visible viewport.