// holo-gpu-device.mjs — ONE WebGPU device for the whole app (the engine, BLAKE3 verify, Bao streaming). // Memoized: exactly one requestDevice() per page. Created with the ADAPTER'S MAX limits so a 145 MB block // binds as a storage buffer (the default cap is 128 MB — a separate default-limits device silently produced a // wrong hash on the embed → κ mismatch → the two-device clash). timestamp-query is requested when available. // Sharing ONE device is what lets fetch→verify→decode coexist without contending. let _p = null; export function getDevice() { if (_p) return _p; _p = (async () => { if (typeof navigator === "undefined" || !navigator.gpu) throw new Error("no WebGPU"); const adapter = await navigator.gpu.requestAdapter(); const L = adapter.limits; const canTs = adapter.features.has("timestamp-query"); const dev = await adapter.requestDevice({ requiredFeatures: canTs ? ["timestamp-query"] : [], requiredLimits: { maxStorageBufferBindingSize: L.maxStorageBufferBindingSize, maxBufferSize: L.maxBufferSize, maxComputeWorkgroupsPerDimension: L.maxComputeWorkgroupsPerDimension, }, }); try { if (typeof globalThis !== "undefined") globalThis.__gpuDeviceCount = (globalThis.__gpuDeviceCount || 0) + 1; } catch (e) {} return { dev, adapter, canTs }; })().catch((e) => { _p = null; throw e; }); return _p; } export default { getDevice };