2026-08-05 09:24:13 +02:00
|
|
|
import type { Framebuffer } from "../engine/render/Framebuffer"
|
2026-08-24 15:17:53 +02:00
|
|
|
import { RenderProtocol, type RenderWorkerInit } from "../engine/render/RenderProtocol"
|
|
|
|
|
import { RenderScene, type RenderInstance } from "../engine/render/RenderScene"
|
2026-08-05 09:24:13 +02:00
|
|
|
|
|
|
|
|
const ctx = globalThis as unknown as {
|
2026-08-24 15:17:53 +02:00
|
|
|
addEventListener: (
|
|
|
|
|
type: "message",
|
|
|
|
|
handler: (e: { data: RenderWorkerInit }) => void,
|
|
|
|
|
) => void
|
2026-08-05 09:24:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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)
|
2026-08-24 15:17:53 +02:00
|
|
|
const cameraData = new Float64Array(m.cameraSAB)
|
|
|
|
|
const viewProjection = new Float32Array(m.viewProjectionSAB)
|
|
|
|
|
const visibleChunks = new Int32Array(m.visibleChunkSAB)
|
|
|
|
|
const instanceIds = new Int32Array(m.instanceIdSAB)
|
|
|
|
|
const instanceTransforms = new Float32Array(m.instanceTransformSAB)
|
2026-08-05 09:24:13 +02:00
|
|
|
const times = new Float64Array(m.timesSAB)
|
2026-08-24 15:17:53 +02:00
|
|
|
const { scene, band, config, skyStep, workerIndex } = m
|
|
|
|
|
const instances: RenderInstance[] = []
|
2026-08-05 09:24:13 +02:00
|
|
|
|
|
|
|
|
// 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 (;;) {
|
2026-08-24 15:17:53 +02:00
|
|
|
Atomics.wait(ctrl, RenderProtocol.FRAME, last)
|
|
|
|
|
last = Atomics.load(ctrl, RenderProtocol.FRAME)
|
2026-08-05 09:24:13 +02:00
|
|
|
const t0 = performance.now()
|
2026-08-24 15:17:53 +02:00
|
|
|
const frameCamera = RenderProtocol.readCamera(cameraData)
|
|
|
|
|
const count = Atomics.load(ctrl, RenderProtocol.VISIBLE_CHUNKS)
|
|
|
|
|
const visible = [...visibleChunks.subarray(0, count)]
|
|
|
|
|
const instanceCount = Atomics.load(ctrl, RenderProtocol.VISIBLE_INSTANCES)
|
|
|
|
|
RenderProtocol.readInstances(
|
|
|
|
|
instanceIds,
|
|
|
|
|
instanceTransforms,
|
|
|
|
|
instanceCount,
|
|
|
|
|
instances,
|
|
|
|
|
)
|
|
|
|
|
RenderScene.renderBand(
|
|
|
|
|
fb,
|
|
|
|
|
scene,
|
|
|
|
|
frameCamera.camera,
|
|
|
|
|
viewProjection,
|
|
|
|
|
visible,
|
|
|
|
|
instances,
|
|
|
|
|
config,
|
|
|
|
|
skyStep,
|
|
|
|
|
frameCamera.time,
|
|
|
|
|
band[0],
|
|
|
|
|
band[1],
|
|
|
|
|
)
|
|
|
|
|
times[workerIndex] = performance.now() - t0
|
|
|
|
|
Atomics.add(ctrl, RenderProtocol.DONE, 1)
|
2026-08-05 09:24:13 +02:00
|
|
|
}
|
|
|
|
|
})
|