Strip core to render data and render graphs
Move glTF, picking, camera controls, and conventional handles into addons. Keep camera and material mutations in SIMD-aligned shared SOA rows and synchronize material updates directly into GPU buffers. Amp-Thread-ID: https://ampcode.com/threads/T-01a01380-b478-77d0-84a0-102880a5c5ae Co-authored-by: Heaust Azure <heaust.azure@gmail.com>
This commit is contained in:
@@ -16,7 +16,7 @@ JavaScript objects ──┘ │
|
||||
|
||||
Any browser thread ── infrequent commands ──────────────────> worker
|
||||
Any browser thread ── atomic SOA writes ────────────────────> shared WASM memory
|
||||
glTF import worker ── fetch URL ──> fixed shared SOA upload ─┘
|
||||
glTF import worker ── parse URL ──> generic render-data packet ─> fixed shared SOA ─┘
|
||||
```
|
||||
|
||||
The canonical AST is the only public render-graph wire format. Nodes are named
|
||||
@@ -29,17 +29,19 @@ pipelines before activating a graph.
|
||||
Authored render shaders use Yawn's fixed scene ABI. Render and compute declarations
|
||||
carry source, entry points, and dispatch/state metadata and are prepared with the
|
||||
graph loadout. Core contains no built-in shader source or pipeline declarations.
|
||||
Its public responsibility stops at shared render data and render-graph compilation,
|
||||
loadouts, lifecycle, and transient resource management; conveniences live outside it.
|
||||
|
||||
## Packages
|
||||
|
||||
- `packages/yawn-core` (`@yawn/core`) — the worker command transport, serialized
|
||||
graph lifecycle, and shared SOA views; it returns `[slot, generation]` handles.
|
||||
- `packages/yawn-core` (`@yawn/core`) — render-data shared arrays and render-graph
|
||||
lifecycle transport; it returns `[slot, generation]` render-data handles.
|
||||
- `addons/render-graph-ast` — canonical immutable DAG AST and S-expression serializer.
|
||||
- `addons/render-graph-js` — plain-object/fluent graph APIs that serialize and load ASTs.
|
||||
- `addons/render-graph-fxnode` — FXNode snapshot exporter and diagnostic mapping.
|
||||
- `addons/default-pipelines` — optional scene/frame shader and compute declarations.
|
||||
- `addons/gltf-import` — URL-fetching worker that writes GLB bytes directly to a fixed SOA.
|
||||
- `addons/mesh-handles` — conventional `Mesh`/`Instance` objects and optional BVH picking.
|
||||
- `addons/gltf-import` — glTF worker that writes format-neutral render-data packets directly to a fixed SOA.
|
||||
- `addons/mesh-handles` — conventional mesh, instance, camera, and material objects plus optional BVH picking.
|
||||
|
||||
The integration example in `examples/render-graph-studio` consumes every package
|
||||
through its public API; no example source or shader lives in core.
|
||||
@@ -80,7 +82,8 @@ await graph.load(core);
|
||||
`@yawn/core` exposes 64-byte-aligned shared SOA columns. Every stride is a multiple
|
||||
of 16 bytes and scalar lanes are atomic `u32`, `i32`, or IEEE-754 `f32` bits. The
|
||||
built-in instance transform/type columns are generation-guarded so a stale handle
|
||||
cannot mutate a reused slot.
|
||||
cannot mutate a reused slot. The built-in `camera.state` column is one 64-byte,
|
||||
16-lane `f32` row containing eye, target, up, and projection parameters.
|
||||
|
||||
Allocate application columns infrequently through the worker:
|
||||
|
||||
@@ -95,16 +98,32 @@ const velocity = await core.allocateArray({
|
||||
velocity.write(instanceSlot, [1, 0, 0, 0]);
|
||||
```
|
||||
|
||||
Camera state has no dedicated core API. Read and write it through the same render-data
|
||||
SOA interface as every other hot value; these mutations do not enqueue worker messages:
|
||||
|
||||
```js
|
||||
const camera = core.array("camera.state");
|
||||
const state = camera.read(0);
|
||||
state[0] = nextEye[0];
|
||||
state[1] = nextEye[1];
|
||||
state[2] = nextEye[2];
|
||||
camera.write(0, state);
|
||||
```
|
||||
|
||||
Import a GLB without transferring its bytes through renderer messages:
|
||||
|
||||
```js
|
||||
import { GltfImporter } from "@yawn/gltf-import";
|
||||
import { MeshHandles } from "@yawn/mesh-handles";
|
||||
import { CameraHandle, MaterialHandles, MeshHandles } from "@yawn/mesh-handles";
|
||||
|
||||
const importer = new GltfImporter(core);
|
||||
const handles = new MeshHandles(core);
|
||||
const meshes = handles.fromImportedScene(await importer.load(gltfUrl));
|
||||
const imported = await importer.load(gltfUrl);
|
||||
const meshes = new MeshHandles(core).fromImportedScene(imported);
|
||||
const materials = new MaterialHandles(core).fromImportedScene(imported);
|
||||
const camera = new CameraHandle(core);
|
||||
meshes[0].defaultInstance.setTransform(nextTransform); // direct shared-SOA write
|
||||
materials[0].roughness = 0.35; // direct shared-SOA write
|
||||
camera.position = [4, 3, 6]; // direct shared-SOA write
|
||||
```
|
||||
|
||||
The renderer grows mesh/instance-domain columns with render-data capacity and
|
||||
@@ -115,7 +134,7 @@ use shared memory; a GLB commit message contains only an array ID and byte count
|
||||
|
||||
`YawnCore` accepts a transport bridge whose worker endpoint can be a `Worker` or a
|
||||
started `MessagePort`, so the same API can run on the browser main thread or another
|
||||
worker. Optional picking is installed with the mesh addon's `createPickingWorker`.
|
||||
worker. Optional snapshot/BVH picking is owned entirely by the mesh-handles addon.
|
||||
|
||||
Cross-origin isolation is required (`COOP: same-origin`, `COEP: require-corp`). The
|
||||
Vite development and preview servers already set both headers.
|
||||
@@ -123,7 +142,7 @@ Vite development and preview servers already set both headers.
|
||||
## Development
|
||||
|
||||
```sh
|
||||
npm run dev
|
||||
npm run examples
|
||||
npm run test:js
|
||||
cargo check --workspace
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user