meat/app/render-worker.ts
2026-08-05 09:24:13 +02:00

61 lines
2 KiB
TypeScript

import type { Framebuffer } from "../engine/render/Framebuffer"
import type { RenderConfig } from "../engine/render/RenderConfig"
import { renderBand, type Scene } from "./renderScene"
/** One-time setup: shared framebuffer + control/param buffers, the (cloned)
* scene, this worker's row band, and its index into the per-worker times array. */
type Init = {
colorSAB: SharedArrayBuffer
depthSAB: SharedArrayBuffer
width: number
height: number
scene: Scene
band: [number, number]
config: RenderConfig
skyStep: number
ctrlSAB: SharedArrayBuffer
camSAB: SharedArrayBuffer
vpSAB: SharedArrayBuffer
visSAB: SharedArrayBuffer
timesSAB: SharedArrayBuffer
index: number
}
const FRAME = 0
const DONE = 1
const VIS = 2
const ctx = globalThis as unknown as {
addEventListener: (type: "message", handler: (e: { data: Init }) => void) => void
}
ctx.addEventListener("message", (e) => {
const m = e.data
const fb: Framebuffer = {
width: m.width,
height: m.height,
color: new Uint32Array(m.colorSAB),
depth: new Float32Array(m.depthSAB),
}
const ctrl = new Int32Array(m.ctrlSAB)
const cam = new Float64Array(m.camSAB)
const vp = new Float32Array(m.vpSAB)
const vis = new Int32Array(m.visSAB)
const times = new Float64Array(m.timesSAB)
const { scene, band, config, skyStep, index } = m
// Lock-free frame loop: block until main bumps the frame counter, render this
// band, record the band time, and signal done. No messages per frame.
let last = 0
for (;;) {
Atomics.wait(ctrl, FRAME, last)
last = Atomics.load(ctrl, FRAME)
const t0 = performance.now()
const camera = { position: { x: cam[0], y: cam[1], z: cam[2] }, yaw: cam[3], pitch: cam[4], fov: cam[5] }
const count = Atomics.load(ctrl, VIS)
const visible = [...vis.subarray(0, count)]
renderBand(fb, scene, camera, vp, visible, config, skyStep, cam[6], band[0], band[1])
times[index] = performance.now() - t0
Atomics.add(ctrl, DONE, 1)
}
})