Skip to main content

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}