( context: GPUContextState )
| 120 | * @throws {Error} If already initialized |
| 121 | */ |
| 122 | export async function initializeGPUContext( |
| 123 | context: GPUContextState |
| 124 | ): Promise<GPUContextState> { |
| 125 | if (context.initialized) { |
| 126 | throw new Error('GPUContext is already initialized. Call destroyGPUContext() before reinitializing.'); |
| 127 | } |
| 128 | |
| 129 | // Be resilient: callers may construct GPUContextState manually. |
| 130 | const sanitizedDevicePixelRatio = |
| 131 | Number.isFinite(context.devicePixelRatio) && context.devicePixelRatio > 0 ? context.devicePixelRatio : 1.0; |
| 132 | |
| 133 | // Check for WebGPU support |
| 134 | if (!navigator.gpu) { |
| 135 | throw new Error( |
| 136 | 'WebGPU is not available in this browser. ' + |
| 137 | 'Please use a browser that supports WebGPU (Chrome 113+, Edge 113+, or Safari 18+). ' + |
| 138 | 'Ensure WebGPU is enabled in browser flags if needed.' |
| 139 | ); |
| 140 | } |
| 141 | |
| 142 | let device: GPUDevice | null = null; |
| 143 | |
| 144 | try { |
| 145 | // Request adapter with power preference from context |
| 146 | const adapter = await navigator.gpu.requestAdapter({ |
| 147 | powerPreference: context.powerPreference, |
| 148 | }); |
| 149 | |
| 150 | if (!adapter) { |
| 151 | throw new Error( |
| 152 | 'Failed to request WebGPU adapter. ' + |
| 153 | 'No compatible adapter found. This may occur if no GPU is available or WebGPU is disabled.' |
| 154 | ); |
| 155 | } |
| 156 | |
| 157 | // Request device from adapter |
| 158 | device = await adapter.requestDevice(); |
| 159 | |
| 160 | if (!device) { |
| 161 | throw new Error('Failed to request WebGPU device from adapter.'); |
| 162 | } |
| 163 | |
| 164 | // Set up device lost handler for error recovery |
| 165 | device.addEventListener('uncapturederror', (event: GPUUncapturedErrorEvent) => { |
| 166 | console.error('WebGPU uncaptured error:', event.error); |
| 167 | }); |
| 168 | |
| 169 | let canvasContext: GPUCanvasContext | null = null; |
| 170 | let preferredFormat: GPUTextureFormat | null = null; |
| 171 | |
| 172 | // Configure canvas if provided |
| 173 | if (context.canvas) { |
| 174 | const webgpuContext = context.canvas.getContext('webgpu') as GPUCanvasContext | null; |
| 175 | |
| 176 | if (!webgpuContext) { |
| 177 | // Clean up device before throwing |
| 178 | try { |
| 179 | device.destroy(); |
no test coverage detected