Spaces:
Running
Running
| // 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 }; | |