/ proof-of-concept / toy-instruments
Sign in
proof-of-concept / toy-instruments
toy-instruments / src / sim / worker.ts
35 lines · 1.4 KBBlameHistoryRaw
1import { simulate } from './solver';
2import { simulateGPU } from './gpu';
3import type { BeadSystem, Excitation, SimOptions, SimResult } from './types';
5export interface WorkerRequest {
6 sys: BeadSystem;
7 exc: Excitation;
8 opt: SimOptions;
9 gpu: boolean;
12const buffers = (r: SimResult) =>
13 [r.audio, r.frames, r.frameTimes, r.energy, r.balance, r.contactForce, r.malletPos].filter((a) => a).map((a) => a!.buffer) as ArrayBuffer[];
15self.onmessage = async (ev: MessageEvent<WorkerRequest>) => {
16 const { sys, exc, opt, gpu } = ev.data;
17 const progress = (f: number) => self.postMessage({ type: 'progress', fraction: f });
18 const partial = (result: SimResult) => self.postMessage({ type: 'partial', result }, { transfer: buffers(result) });
19 try {
20 let result: SimResult | undefined;
21 let fallback: string | undefined;
22 if (gpu) {
23 try {
24 const r = await simulateGPU(sys, exc, opt, progress, (p) => partial({ ...p, backend: `WebGPU (${(p as SimResult & { device: string }).device})` }));
25 result = { ...r, backend: `WebGPU (${r.device})` };
26 } catch (e) {
27 fallback = (e as Error).message ?? String(e);
28 }
29 }
30 result ??= { ...simulate(sys, exc, opt, progress, (p) => partial({ ...p, backend: 'CPU', fallback })), backend: 'CPU', fallback };
31 self.postMessage({ type: 'done', result }, { transfer: buffers(result) });
32 } catch (e) {
33 self.postMessage({ type: 'error', message: String(e) });
34 }
35};
↑↓ move↵openescclose