Skip to main content

oxiui_render_wgpu/
error.rs

1//! GPU error mapping to [`oxiui_core::UiError`].
2//!
3//! GPU backends produce hardware-specific error conditions.  This module
4//! normalises them into the common [`oxiui_core::UiError`] type so callers
5//! need only handle one error hierarchy.
6
7use oxiui_core::UiError;
8
9// ── GpuErrorKind ─────────────────────────────────────────────────────────────
10
11/// The class of error reported by the GPU runtime.
12#[derive(Clone, Debug, PartialEq)]
13pub enum GpuErrorKind {
14    /// The GPU device was lost (driver crash, unplug, TDR, …).
15    DeviceLost,
16    /// The GPU ran out of memory.
17    OutOfMemory,
18    /// A shader module failed to compile.
19    ShaderCompile,
20    /// The swap-chain surface was lost (window closed, resize race, …).
21    SurfaceLost,
22}
23
24/// Map a [`GpuErrorKind`] and a detail string to a [`UiError`].
25///
26/// | Kind | Maps to |
27/// |------|---------|
28/// | `DeviceLost` | `UiError::Render` |
29/// | `OutOfMemory` | `UiError::Render` |
30/// | `SurfaceLost` | `UiError::Render` |
31/// | `ShaderCompile` | `UiError::Unsupported` |
32pub fn map_gpu_error(kind: GpuErrorKind, detail: String) -> UiError {
33    match kind {
34        GpuErrorKind::DeviceLost => {
35            UiError::Render(format!("GPU {:?}: {detail}", GpuErrorKind::DeviceLost))
36        }
37        GpuErrorKind::OutOfMemory => {
38            UiError::Render(format!("GPU {:?}: {detail}", GpuErrorKind::OutOfMemory))
39        }
40        GpuErrorKind::SurfaceLost => {
41            UiError::Render(format!("GPU {:?}: {detail}", GpuErrorKind::SurfaceLost))
42        }
43        GpuErrorKind::ShaderCompile => UiError::Unsupported(format!("shader compile: {detail}")),
44    }
45}
46
47// ── Tests ─────────────────────────────────────────────────────────────────────
48
49#[cfg(test)]
50mod tests {
51    use super::*;
52
53    #[test]
54    fn map_gpu_error_all_kinds() {
55        let device_lost = map_gpu_error(GpuErrorKind::DeviceLost, "reset".to_string());
56        assert!(
57            matches!(device_lost, UiError::Render(ref s) if s.contains("DeviceLost")),
58            "expected Render(DeviceLost …), got {device_lost:?}"
59        );
60
61        let oom = map_gpu_error(GpuErrorKind::OutOfMemory, "vram".to_string());
62        assert!(
63            matches!(oom, UiError::Render(ref s) if s.contains("OutOfMemory")),
64            "expected Render(OutOfMemory …), got {oom:?}"
65        );
66
67        let surface = map_gpu_error(GpuErrorKind::SurfaceLost, "resize".to_string());
68        assert!(
69            matches!(surface, UiError::Render(ref s) if s.contains("SurfaceLost")),
70            "expected Render(SurfaceLost …), got {surface:?}"
71        );
72
73        let shader = map_gpu_error(GpuErrorKind::ShaderCompile, "syntax error".to_string());
74        assert!(
75            matches!(shader, UiError::Unsupported(ref s) if s.contains("shader compile")),
76            "expected Unsupported(shader compile …), got {shader:?}"
77        );
78    }
79}