Open Asterune
Frame pipeline and resources

Frame pipeline and resources

Trace CPU preparation, ordered GPU passes, frame attachments, history ownership, and submission in Asterune.

Asterune turns a prepared world view into an ordered command buffer. CPU preparation chooses visible draws and uploads their state. Graphics and compute passes then produce high-dynamic-range (HDR) scene color, reconstruct the image, and compose the interface. The acquired surface texture receives the final picture.

A simulation update, a rendered view, and a presented frame are distinct units. A server advances simulation without drawing. A headset draws 2 views for one stereo frame. A SceneFrame can request another camera view without advancing particles or exposure again.

CPU preparation and frame acquisition

Frame preparation first finishes any outstanding submission handoff. The main view checks device health, collects completed probe work, and uploads terrain appearance. The renderer then builds draw lists using the camera frustum, draw distance, visibility masks, material transmission, and render layers. Shadow-caster lists remain separate from the camera-visible lists.

Before batching opaque meshes, the renderer settles transforms that moved on the preceding frame. A stationary mesh must report zero object motion even when a batch removes that mesh from the individual draw list. Otherwise, temporal anti-aliasing (TAA) continues reprojecting a movement that already ended.

Multi-draw preparation and dynamic instancing remove eligible meshes from the individual opaque list. Their instance data still carries the state needed by depth, surface shading, and motion output. The remaining mesh list supplies cached render bundles.

The renderer acquires an output target after this preparation. An offscreen target supplies its existing texture. A detached surface returns without recording a frame. A lost or outdated surface triggers reconfiguration and another acquisition attempt. Timeout and occlusion results skip the frame; validation failure returns an error.

Once acquisition succeeds, the renderer creates the frame command encoder. Pending GPU skinning runs before the scheduled passes, so every subsequent draw reads the posed vertices. A headset hidden-area mesh, when present, establishes depth coverage for regions outside the usable lens image.

Pass dependencies and execution

The frame schedule is a dependency table of named passes. The engine computes a topological order once, then invokes each pass in that order. The table expresses prerequisites; individual pass functions decide whether to record work for the active mode.

ShadowsLocal shadowsSun shadows
EnvironmentAtmosphere and cloudsEnvironment captureReflection probes and fog
Culling and depthGPU cullingDepth prepassDepth pyramid
Screen lightingOcclusion and indirect light
Opaque shadingHDR scene colorSurface dataMotion vectors
Scene completionReflectionsWorld-space interfacesSky and translucencyViewmodel
Image processingGlowTemporal resolveLens and display effectsInterface

Shadow maps, environment resources, and screen-space lighting are prerequisites of opaque shading. Screen-space lighting follows culling and the depth prepass. Opaque shading precedes reflections, translucency, and the viewmodel, which precede glow, temporal resolve, and the lens and display passes.

Arrows show prerequisites between pass groups. A pass also follows everything that its prerequisites follow.

The following groups describe the main resource dependencies:

Pass groupInputs and results
Local and sun shadowsScene casters produce depth maps for light visibility.
Atmosphere, clouds, environment capture, and probesEnvironment state produces resources for world shading.
Culling and depth prepassVisible geometry produces scene depth and indirect draw lists.
Depth reduction and screen lightingDepth and earlier scene data produce occlusion and indirect light.
Opaque shadingGeometry, materials, lights, shadows, and environment data produce HDR color and auxiliary surface data.
Reflections and scene surfacesScreen-space reflection tracing modifies opaque color; world-space interfaces follow.
Sky, translucency, and viewmodelBackground and later geometry complete the scene.
Glow and temporal resolveEmission contributes glow; motion and history reconstruct the scene image.
Lens, exposure, and HDR effectsImage and depth drive blur, luminance adaptation, bloom, and sun rays.
Tone mapping and display effectsHDR color becomes display color, followed by fast approximate anti-aliasing (FXAA) and place or custom effects.
Scene frames, interface, and accessibilityInterface composition finishes before the accessibility filter.

An entry's position in the source table is not sufficient to establish its execution order. For example, HDR effects depend on exposure, so exposure runs before bloom even though its declaration follows HDR effects. Tone mapping depends on both results.

The table does not allocate or alias textures automatically. Target creation, load operations, store operations, copies, and resolve destinations are explicit in the renderer. An inactive pass still has a position in the schedule but can return without issuing GPU commands.

Scene attachments and their readers

The single-sample desktop path writes multiple render targets during opaque shading. The main targets use the following formats:

ResourceFormatConsumers
HDR scene colorRgba16FloatReflections, refraction copies, temporal resolve, exposure, and later image processing
Scene depthDepth32FloatDepth testing, depth reduction, reconstruction, and lens effects
Viewmodel depthDepth32FloatSeparate depth testing for viewmodel draws
Surface dataRgba16UintPacked surface inputs for screen-space reflection tracing
Motion vectorsRgba16FloatTemporal resolve and motion blur
Reflection contributionRgba16FloatReflection replacement and reactive information
Screen depthR32FloatScreen-space lighting, tracing, and particle work

These targets have different meanings even when their dimensions match. The integer surface target stores packed attributes rather than a displayable color. Motion data carries reprojection information rather than the final surface color. The HDR scene can contain values above the display range.

The multisample anti-aliasing (MSAA) path changes this layout. It draws into multisampled HDR color and depth, then resolves color into the single-sample HDR scene. It omits the desktop surface, motion, and reflection outputs. Unused traced targets use small placeholders. See Anti-aliasing and resolution for resolve boundaries and mode selection.

Attachment continuity between passes

Opaque shading clears scene color to the selected world background. It loads depth when the prepass or hidden-area mesh has already produced useful depth; otherwise, it clears depth itself. Later scene passes load and extend those attachments.

Water and transmission need a sampleable scene image while they draw. The renderer copies or resolves the earlier color into a separate source texture. The surface shader then reads that source while writing scene color. Sampling the same attachment that a pass writes would not provide a valid preceding scene image.

The MSAA path tracks which pass completes the world. Depending on visible content, the opaque pass can also draw the sky and ordinary transparency. Water, refraction, order-independent transparency, or viewmodels require later boundaries. The renderer resolves at the required source or final boundary instead of resolving every scene pass.

After scene reconstruction, lens_output identifies the HDR image consumed by the next lens pass. The display chain separately tracks its intermediate source and the remaining effects. This lets tone mapping or the last display effect write directly to the final destination when another intermediate is unnecessary. The interface follows world display effects, so those effects do not process ordinary screen-space interface elements.

History ownership across views

The second headset eye reuses work marked once per frame: shadows, atmosphere, cloud preparation, environment capture, caustics, reflection probes, particle simulation, and exposure. View-dependent work still uses the eye's camera and depth. Opaque and prepass bundle caches are indexed separately by eye and environment because their visible sets can differ.

Additional live-world interface cameras also reuse the renderer. They pause temporal accumulation, use their own camera and culling mask, and render into an offscreen texture. Their render scale follows their displayed pixel size, with a minimum scale of 0.125 relative to the main target. The scene atlas copies the camera picture on the next frame.

These views reuse the main scene targets, so the renderer preserves the main view's lit HDR scene before drawing them and restores it afterward. Otherwise, the next main view could gather indirect light from an interface camera's picture. Restoring the temporal state alone would not restore the color resource that screen-space lighting samples.

Scene TAA and screen-space lighting also keep separate validity state. A valid TAA history does not establish that an indirect-light history contains samples from the correct view. Their individual reconstruction and reset rules are described in Temporal anti-aliasing and Lighting and reflections.

Submission, presentation, and completion

After recording passes, the renderer records overlays, timestamp resolves, and any requested readback copy. It flushes model updates before submitting the command buffer. Successful frame recording advances the temporal state for subsequent frames.

When threaded submission is enabled and no readback is scheduled, main views and interface-camera views can hand the frame to a dedicated worker. The worker finishes the encoder, submits it, and presents surface targets. The main thread can advance simulation while that handoff runs. Capture readback follows the synchronous path instead.

Queue writes require special ordering: wgpu includes pending writes in the next submission. A main-thread write during a previous frame's handoff could attach data to the wrong submission. GuardedQueue waits for that handoff before allowing another queue operation.

Finishing the handoff means the commands have been submitted and presentation has been requested. It does not mean the GPU has completed those commands. The worker signals handoff completion before polling retired work. Screenshot readback separately maps its staging buffer and waits for completion, which introduces synchronization that ordinary rendering avoids.