Renderer · interface

PassDefinition

Explained in Hello world.

interface PassDefinition
import type { PassDefinition } from '@driftengine/core';

Properties

NameTypeDescription
labelreadonlystringFor diagnostics, and for the label a backend gives the work.
readsreadonlyoptionalreadonly FrameResource[]Attachments this pass samples.
More

Reads only, and that asymmetry is deliberate. What a pass writes is wherever the caller is drawing, and is not negotiable: every built-in verb writes the current target and the executor replays a flush's nodes into one open pass, so a node declaring some other write-set schedules as a separate pass that nothing opens. Letting a package name its writes would hand it the single declaration nothing can enforce, whose failure mode is a scene quietly losing draws.

A read, by contrast, is exactly what the scheduler needs from outside: declare mirrorColor and the frame stops deriving a discard for an attachment this pass is about to sample.

Methods

prepareoptional

prepare?(ctx: PrepareContext): void

Fill a target the pass owns, once a frame, before anything opens the frame's own.

ParameterTypeDescription
ctxPrepareContext
More

Shipped 2026-08-27, to the design this comment used to carry as a plan. A package's own shadow map, blur pyramid or picking buffer: rendered here, sampled from draw. What a pass writes into the frame stays refused for the reason reads gives above, and a pass-owned target is outside that set by construction, which is what makes this declarable when a write to the frame is not. createPassAttachment builds one from the PassDevice this pass was handed at init; the pass releases it in its own dispose.

Called at one fixed point, for every pass that declares it, in registration order — which must not become dependency ordering. Gate 1.2 withdrew that with a reason on record and this does not reintroduce it: registration order is an order, not a dependency graph, and a pass that needs another's output has to be registered after it and know that it does.

It costs nothing for a pass that does not declare it. Both renderers keep a count of the passes that do and skip the whole step at zero, rather than walking the registry every frame to find out that nobody wants it.

Allocates nothing, like draw. On WebGL2, leaves the default framebuffer bound — see PrepareContext, which is where that contract is written out.

initoptional

init?(device: PassDevice): void

Build pipelines, buffers and textures. Called once, when the pass is registered.

ParameterTypeDescription
devicePassDevice

draw

draw(ctx: PassContext): void

Draw. Called once a frame, at the point the caller invoked drawPass.

ParameterTypeDescription
ctxPassContext
More

Allocates nothing. This is a per-frame hot path and the engine's own rule about them binds a contributor exactly as it binds the renderer.

Leaves the context as it found it. On WebGL2 that means the program, the bound vertex array, the blend and depth state and the viewport; the renderer's own verbs assume what they left. On WebGPU the pass encoder's pipeline and bind groups are set by every verb before it draws, so only the viewport and the scissor persist and only those two matter.

disposeoptional

dispose?(device: PassDevice): void

Release what init built. Called on unregisterPass and when the renderer is disposed.

ParameterTypeDescription
devicePassDevice