Files
yawn/docs/guide/architecture.md
T

2.9 KiB

How Yawn fits together

Yawn has two public boundaries: worker communication for small, infrequent operations and shared render data for values that change often. Everything else is an authoring or convenience layer outside core.

JSO / fluent builder ─┐
                     ├──▶ canonical DAG AST ─▶ S-expression ─▶ render worker
FXNode snapshot ─────┘                                           │
                                                                ├─ graph compiler
glTF import worker ───── shared upload array ────────────────────┤
                                                                ├─ transient allocator
any browser thread ─── lifecycle messages ──────────────────────┤
any browser thread ─── atomic SOA writes ────────────────────────┘

What core owns

@yawn/core owns only the protocol client for render data and render graphs. The worker behind it owns graph validation, loadout preparation, transient lifetime analysis, GPU allocation, and rendering.

Core does not own a camera module, scene object model, glTF parser, shader library, editor, or picking system. Camera and material values are ordinary render-data columns. Higher-level objects are optional addon views over those columns.

The graph is the program

Every frontend must produce @yawn/render-graph-ast data. A node is named, while an input contains one or more { node, socket } references. Reusing the same reference creates fan-out, so the format describes a DAG instead of duplicating a tree.

Render and compute pipeline declarations are part of that AST. Their WGSL and state are compiled into a prepared loadout, not linked into core.

The SOA is the mutable scene

Shared arrays are 64-byte aligned and each row stride is a multiple of 16 bytes. The standard columns cover mesh, instance, camera, and material data. Applications can request additional mesh-, instance-, or fixed-domain arrays; domain arrays grow with the corresponding render-data capacity.

Lifecycle operations such as allocating a column, importing an asset, compiling a graph, or creating an instance cross the command boundary. A frame-rate transform, camera, classification, or material update writes the existing SAB row directly.

Thread placement is a choice

The JS client only requires a Worker-like endpoint. A main thread can own it, or another worker can connect through a MessagePort. Shared descriptors can be passed to additional workers, which can then read or write the same SOA data without proxying every update through the main thread.

::: warning Cross-origin isolation is required Serve the application with Cross-Origin-Opener-Policy: same-origin and Cross-Origin-Embedder-Policy: require-corp. npm run examples supplies both headers. :::