euv_engine/renderer/webgpu/enum.rs
1use super::*;
2
3/// Errors that can occur while asynchronously initializing a `WebGpuRenderer`.
4///
5/// Each variant maps to one specific failure mode that the WebGPU init
6/// pipeline can encounter when calling into the browser's GPU API. The
7/// underlying JS error (when available) is carried as a `JsValue` so callers
8/// can surface the exact diagnostic string without losing fidelity.
9///
10/// Instead of logging diagnostics inside the engine, `WebGpuRenderer::init`
11/// returns `Result<WebGpuRenderer, WebGpuInitError>` and lets the caller
12/// decide how to react — typically via `Console::error` on the example side
13/// or by falling back to the Canvas 2D backend.
14#[derive(Clone, Debug)]
15pub enum WebGpuInitError {
16 /// `Reflect::get(navigator, "webgpu")` threw an exception.
17 ///
18 /// Surfaced when the JavaScript binding lookup itself fails rather than
19 /// simply returning `undefined`/`null`. Carries the original JS error.
20 NavigatorLookup(JsValue),
21 /// `navigator.gpu` is `undefined` or `null`.
22 ///
23 /// The browser does not expose WebGPU on the current origin. The most
24 /// common causes are serving over an insecure origin (must be HTTPS or
25 /// `localhost`) or running in a browser that lacks the WebGPU feature.
26 NavigatorGpuMissing,
27 /// `Reflect::get(gpu, "requestAdapter")` threw an exception.
28 ///
29 /// Carries the original JS error returned by the reflect call.
30 RequestAdapterLookup(JsValue),
31 /// `gpu.requestAdapter()` threw an exception synchronously.
32 ///
33 /// Carries the thrown JS error or value.
34 RequestAdapterCall(JsValue),
35 /// The adapter promise rejected, or the `INIT_PROMISE_TIMEOUT_MILLIS`
36 /// race timer fired before the adapter was produced.
37 ///
38 /// Carries the rejection value, which may be a string, an error object,
39 /// or `undefined` when the timeout won the race.
40 AdapterPromise(JsValue),
41 /// `requestAdapter()` resolved to `null` or `undefined`.
42 ///
43 /// No compatible GPU adapter exists for the requested `powerPreference`.
44 AdapterUnavailable,
45 /// `Reflect::get(adapter, "requestDevice")` threw an exception.
46 RequestDeviceLookup(JsValue),
47 /// `adapter.requestDevice()` threw an exception synchronously.
48 RequestDeviceCall(JsValue),
49 /// The device promise rejected, or the `INIT_PROMISE_TIMEOUT_MILLIS`
50 /// race timer fired before the device was produced.
51 DevicePromise(JsValue),
52 /// `requestDevice()` resolved to `null` or `undefined`.
53 ///
54 /// The adapter could not allocate a device, typically because the
55 /// adapter is in a `device-lost` state.
56 DeviceUnavailable,
57 /// `document.querySelector(canvas_selector)` returned `None`.
58 ///
59 /// The canvas element is not in the DOM yet (or its selector is wrong).
60 /// Carries the selector string that was queried.
61 CanvasNotFound(String),
62 /// `document.querySelector(canvas_selector)` threw an exception.
63 CanvasQuery(JsValue),
64 /// `canvas.get_context("webgpu")` returned `None`.
65 ///
66 /// The canvas is already using a different context type, or WebGPU is
67 /// disabled for this canvas.
68 CanvasContextUnavailable,
69 /// `Reflect::get(gpu, "getPreferredCanvasFormat")` threw an exception.
70 PreferredFormatLookup(JsValue),
71 /// `gpu.getPreferredCanvasFormat()` threw an exception synchronously.
72 PreferredFormatCall(JsValue),
73 /// `getPreferredCanvasFormat()` resolved to a value that is not a string.
74 ///
75 /// Carries the offending JS value so callers can log its type/name.
76 PreferredFormatType(JsValue),
77 /// `Reflect::get(context, "configure")` threw an exception.
78 ConfigureLookup(JsValue),
79 /// `Reflect::get(device, "queue")` threw an exception.
80 QueueLookup(JsValue),
81}
82
83/// WebGPU receiver-class discriminator for the `cached_method` cache.
84///
85/// JS class methods live on the prototype, so the same `Function` instance
86/// is returned for every receiver of a given class — the `(class, method)`
87/// pair uniquely identifies the cached `Function` and no receiver identity
88/// is needed. This replaces the previous stack-address keying: per-frame
89/// temporary `JsValue`s (pass encoders, command encoders) reuse stack
90/// slots across frames, so an address-keyed cache could return the wrong
91/// class's `Function` when a `GPUComputePassEncoder` landed on a slot that
92/// previously held a `GPURenderPassEncoder` (both share `setPipeline` /
93/// `setBindGroup` / `end`), producing a swallowed TypeError and a silently
94/// skipped GPU call.
95#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
96pub enum GpuReceiverClass {
97 /// `GPUDevice` (immortal, renderer-owned).
98 Device,
99 /// `GPUQueue` (immortal, renderer-owned).
100 Queue,
101 /// `GPUCanvasContext` (immortal, renderer-owned).
102 Context,
103 /// `GPUTexture` (per-call temporary).
104 Texture,
105 /// `GPUCommandEncoder` (per-frame temporary).
106 CommandEncoder,
107 /// `GPURenderPassEncoder` (per-pass temporary).
108 RenderPass,
109 /// `GPUComputePassEncoder` (per-pass temporary).
110 ComputePass,
111}