Files
yawn/coredocs/reference/worker.md
T
Ampandheaust 4784ad7e87 Render continuously and optimize the glTF viewer
Remove vsync and dirty-flag frame gating, optimize PBR sampling and lighting, add a direct-to-canvas loadout, and preserve camera state on viewer resize.

Add regression coverage and update rendering documentation.

Amp-Thread-ID: https://ampcode.com/threads/T-01a0b382-1e79-712b-abd1-d29201c9bb5e
Co-authored-by: Heaust Azure <heaust.azure@gmail.com>
2026-09-18 08:58:27 +00:00

4.8 KiB

Worker message reference

All fields below are top-level beside type and request. Except for init and upload-texture, transfer lists are empty.

type Fields Transfer list Success result Constraints / effects
init canvas: OffscreenCanvas, arenaBytes: number [canvas] { buffer: SharedArrayBuffer, rows: Descriptor[], features: string[] } Once only; initializes WASM/WebGPU. features lists optional device features that were available (timestamp-query, indirect-first-instance).
create-rows name, rows, stride, format — { rows: descriptor, commit: boolean } Nonempty name; rows > 0; stride ≥16 and multiple of 16; format f32/u32/i32. Existing name may only retain format/stride and grow. commit: true means the rows moved: copy the old bytes into the descriptor and send commit-rows.
create-rows-batch rows: Array<{name,rows,stride,format}> — { rows: descriptor[] (input order), commit: string[] } Nonempty. Sequential; in-place creations/growths survive a later failure, staged relocations are discarded. commit lists the arrays that moved. Active GPU resources refresh once for in-place growth.
commit-rows names: string[] — undefined Publishes staged relocations after the caller copied them. Must name every staged array. Frees the old rows and refreshes bound GPU buffers once. While a relocation is staged the worker queues every other request until this arrives.
delete-rows name — undefined Not signals, not active slots, not referenced by active graph.
allocate-object name, count: u32 = 1 — { id, rows: descriptor, commit: boolean } Not signals; count > 0; reserves count contiguous rows starting at id; may grow. commit as in create-rows.
delete-object name, id: u32 — undefined ID must be the first row of an active span; the whole span is zeroed.
sync-rows name, first: u32 = 0, count: u32 — undefined Uploads rows first .. first + count of the array into every active GPU buffer bound to it (any sync). ROW_RANGE when the span exceeds the array. No-op without an active loadout.
compile-graph serialized: string — graph ID string Parses and stores; same ID replaces previously stored graph. Does not activate it.
switch-loadout id — undefined Builds GPU resources and activates stored graph. Clears bundleDirty.
upload-texture name, mipLevel: u32, image: ImageBitmap [image] undefined Uploads immediately if active graph has the texture and caches source for future switches. Source extent must fit destination/mip.
delete-texture name — undefined Deletes/closes cached mip sources; does not remove graph texture.
play — — undefined Enables render-loop ticks; resets last-time baseline.
pause — — undefined Stops loop updates/renders.
set-fps fps: u32 — undefined 0 uncapped; maximum 1000.
set-profiler enabled (boolean-coerced) — boolean Result says timestamp queries are supported. Enables only when requested and supported.

Rust/WASM numeric conversion applies to u32 fields; callers should send finite nonnegative integers in range rather than rely on coercion.

Profiler events

When enabled and supported, the worker polls every 250 ms and may send an unsolicited message with no request field:

{
  type: "profile",
  stats: {
    frame: 42,
    milliseconds: 0.31,
    readbackMilliseconds: 4.8,
    adapter: "Adapter name · DeviceType · Backend",
    canvas: { width: 1280, height: 720 },
    passes: [{ name: "triangle", milliseconds: 0.31 }]
  }
}

milliseconds is the sum of GPU timestamp durations across passes, not CPU frame time or the interval between frames. It excludes scheduling waits and readback latency; readbackMilliseconds reports the time from starting that frame to receiving its timestamp results.

One pass timing corresponds to a compiled execution; compatible adjacent render passes are merged into one execution labelled first … last (N draws). Samples are throttled and asynchronous, so they are diagnostics, not one event per frame. Disabling clears pending published statistics and the worker polling interval.

Texture lifecycle

Create an ImageBitmap, then relinquish it to the worker:

const image = await createImageBitmap(blob);
await request("upload-texture", { name: "albedo", mipLevel: 0, image }, [image]);

The name is a graph texture ID, not an arbitrary row name. Upload can precede graph activation because sources are cached. Non-transient textures with an unchanged descriptor can be retained across switches; cached levels are reapplied when needed. delete-texture only removes these cached sources.