/ proof-of-concept / plate-dynamics-lab
Sign in
proof-of-concept / plate-dynamics-lab
plate-dynamics-lab / packages / core / src / runner / worker.ts
57 lines · 1.9 KBBlameHistoryRaw
1/// <reference lib="webworker" />
2/**
3 * Web Worker that owns a numbl instance and, when the browser exposes WebGPU
4 * to workers, a GPU device for the ported time loop. One run at a time; the
5 * host cancels a run by terminating the worker, which is why nothing here
6 * needs to be interruptible.
7 */
8import { numblVersion } from "./execute";
9import { executeRequest, type GpuProvider } from "./executeGpu";
10import { requestGpuDevice, type GpuHandle } from "../gpu/fdLoop";
11import { collectBuffers } from "./plain";
12import type { FromWorker, ToWorker } from "./protocol";
13import type { BackendInfo } from "./types";
15const backend: BackendInfo = {
16 engine: "numbl",
17 version: numblVersion(),
18 optimization: "1",
19 host: "web-worker",
20};
22const post = (msg: FromWorker, transfer: ArrayBuffer[] = []) => self.postMessage(msg, transfer);
24// The device is requested once and kept; a lost device is requested again next time.
25let gpuHandle: Promise<GpuHandle> | null = null;
26const gpuProvider: GpuProvider = () => {
27 if (!gpuHandle) {
28 gpuHandle = requestGpuDevice().then((h) => {
29 void h.device.lost.then(() => {
30 gpuHandle = null;
31 });
32 return h;
33 });
34 gpuHandle.catch(() => {
35 gpuHandle = null;
36 });
37 }
38 return gpuHandle;
39};
40const hasWebGpu =
41 typeof navigator !== "undefined" && "gpu" in navigator && !!(navigator as { gpu?: unknown }).gpu;
43self.onmessage = async (e: MessageEvent<ToWorker>) => {
44 const msg = e.data;
45 if (msg.type === "info") {
46 post({ type: "info", id: msg.id, backend });
47 return;
48 }
49 const result = await executeRequest(
50 { bundle: msg.bundle, inputs: msg.inputs, gpu: msg.gpu },
51 backend,
52 (text) => post({ type: "output", id: msg.id, text }),
53 hasWebGpu ? gpuProvider : undefined,
54 );
55 const transfer = result.ok ? collectBuffers(result.value) : [];
56 post({ type: "done", id: msg.id, result }, transfer);
57};
↑↓ move↵openescclose