Skip to main content

Rendering pipeline

This page describes the runtime pipeline that turns authored widgets into a presented frame.

Use it when you need to confirm what each stage consumes, what it produces, and where a bug likely belongs.

Pipeline stages

StageInputOutputWhy it exists
build()Widget, BuildCtx, Viewauthored Node treeGives the runtime a deterministic user interface description for the current inputs
loweringauthored Node treeCore intermediate representationConverts author-friendly structure into a smaller, stable internal contract
layoutCore intermediate representation plus viewport constraintsLayoutSnapshotComputes sizes, positions, and related geometry
semantics derivationruntime structure plus layout meaningsemantics treeExposes roles, labels, values, focus structure, and accessibility meaning
paint compilationvisible structure plus layoutdisplay listProduces ordered drawing commands for the renderer
shell presentationrender output plus host surfacepresented frameConnects the shared runtime to a real desktop, browser, or mobile host

Authored build output

The pipeline begins when Widget::build() returns a Node tree.

This tree is the authoring-layer description of the user interface. It is where ordinary widget composition, branching, action binding, resource declaration, portal registration, and runtime wiring are expressed.

The authored tree is not yet the runtime's final internal form. It is optimized for authoring clarity, not for downstream processing.

Lowering and the Core intermediate representation

Lowering is the step that translates the authored Node tree into the smaller internal contract used by later runtime stages.

That contract is commonly described as the Core intermediate representation, or Core IR.

The purpose of Core IR is architectural stability. Layout, semantics, testing, and rendering should not have to understand every authoring convenience widget directly. They consume a more stable internal representation instead.

Custom lowerers such as LowerDyn fit into this stage when a widget needs direct control over what internal structure it emits.

Layout and LayoutSnapshot

The layout stage resolves constraints and computes geometry.

The public geometry result is LayoutSnapshot, which records the computed rectangles and related layout data for the frame. LayoutRect, LayoutSize, and constraint-related helpers are part of this surface.

This explicit geometry stage is why layout can be inspected directly in tests and diagnostics. It is also why widgets can read prior-frame geometry through View when they need anchor information.

Semantics output

Semantics are the runtime's description of interface meaning rather than pixels.

That includes roles, labels, values, focus-relevant structure, and other accessibility-oriented meaning derived from the shared runtime. The shell then adapts that meaning to platform accessibility APIs.

Semantics are part of the pipeline because they are a first-class runtime output, not an afterthought layered on top of pixels.

Paint compilation and display list output

Once structure and geometry are known, the runtime compiles visible content into a display list.

A display list is the ordered sequence of drawing operations consumed by the renderer. Keeping this stage explicit is important for performance, determinism, and debugging. Paint order can be inspected, compared, and validated without collapsing all rendering questions into final pixels alone.

Shell presentation

The renderer and shell host consume the frame output and present it on a real surface.

This is the last step in the pipeline. The shell is responsible for surface creation and presentation, but it should not redefine the meaning already established by earlier stages.

Public types worth knowing

The most commonly referenced public types in this area are:

  • Node, CustomNode, and LowerDyn for authoring and custom lowering,
  • LoweringContext and NodeBuilder for lower-level custom emission,
  • NodeId and WidgetNodeId for runtime identity,
  • LayoutSnapshot, LayoutRect, and LayoutSize for geometry.

Debugging guidance

This page is often most useful when you ask which stage first became wrong.

If the wrong branch or text is present, inspect state or build().

If the structure is right but the geometry is wrong, inspect layout.

If layout is right but the visual output is wrong, inspect paint, theme, or media behavior.

If the shared runtime output looks correct but one host still behaves differently, inspect the shell boundary.

For the widget contract that starts this pipeline, see Widget trait. For the teaching version of the same staged model, see Rendering pipeline. For stage-level investigation tools, continue to Testing and diagnostics.