Skip to main content

par_term_render/
error.rs

1//! Typed error types for par-term-render.
2//!
3//! This module provides structured error types so callers at the crate boundary
4//! can match on specific error variants instead of relying on opaque `anyhow`
5//! strings.
6
7use thiserror::Error;
8
9/// Top-level error type for the GPU rendering engine.
10///
11/// Covers the main failure categories that callers may want to distinguish:
12/// - GPU initialisation (adapter, device, surface)
13/// - Shader compilation and reload
14/// - Image / texture loading
15/// - GPU surface / presentation
16/// - Screenshot capture
17#[derive(Debug, Error)]
18pub enum RenderError {
19    // -----------------------------------------------------------------------
20    // GPU initialisation
21    // -----------------------------------------------------------------------
22    /// A suitable wgpu GPU adapter could not be found for the given surface.
23    #[error("GPU adapter not found: no compatible GPU adapter available for this surface")]
24    AdapterNotFound,
25
26    /// The wgpu device could not be created or the device was lost.
27    #[error("GPU device error: {0}")]
28    DeviceError(String),
29
30    /// The wgpu surface could not be created for the window.
31    #[error("GPU surface creation failed: {0}")]
32    SurfaceCreation(String),
33
34    // -----------------------------------------------------------------------
35    // Shader errors
36    // -----------------------------------------------------------------------
37    /// The shader source file could not be read from disk.
38    #[error("Shader file read failed for '{path}': {source}")]
39    ShaderFileRead {
40        /// Path to the shader file that could not be read.
41        path: String,
42        /// Underlying I/O error.
43        #[source]
44        source: std::io::Error,
45    },
46
47    /// The GLSL source could not be parsed (transpilation step 1).
48    #[error("GLSL parse error in '{name}':\n{details}")]
49    GlslParse {
50        /// Shader name or path.
51        name: String,
52        /// Human-readable parse error messages.
53        details: String,
54    },
55
56    /// The intermediate WGSL source could not be parsed.
57    #[error("WGSL parse error for '{name}': {details}")]
58    WgslParse {
59        /// Shader name or path.
60        name: String,
61        /// Human-readable parse error details.
62        details: String,
63    },
64
65    /// The shader module failed naga validation.
66    #[error("Shader validation failed for '{name}': {details}")]
67    ShaderValidation {
68        /// Shader name or path.
69        name: String,
70        /// Human-readable validation error details.
71        details: String,
72    },
73
74    /// WGSL generation (from the naga IR) failed.
75    #[error("WGSL code generation failed for '{name}': {details}")]
76    WgslGeneration {
77        /// Shader name or path.
78        name: String,
79        /// Human-readable generation error details.
80        details: String,
81    },
82
83    /// A shader reload was requested but no shader is currently active,
84    /// or a shader compilation error occurred during reload.
85    #[error("Shader error: {0}")]
86    NoActiveShader(String),
87
88    // -----------------------------------------------------------------------
89    // Image / texture loading
90    // -----------------------------------------------------------------------
91    /// An image file could not be opened or decoded.
92    #[error("Image load failed for '{path}': {source}")]
93    ImageLoad {
94        /// Path to the image that failed to load.
95        path: String,
96        /// Underlying image error.
97        #[source]
98        source: image::ImageError,
99    },
100
101    /// The supplied raw RGBA byte slice has an unexpected length.
102    #[error("Invalid RGBA data size: expected {expected} bytes, got {actual} bytes")]
103    InvalidTextureData {
104        /// Expected byte count (`width * height * 4`).
105        expected: usize,
106        /// Actual byte count received.
107        actual: usize,
108    },
109
110    /// A cubemap face image is not square or all faces are not the same size.
111    #[error("Cubemap geometry error: {0}")]
112    CubemapGeometry(String),
113
114    /// A required cubemap face file could not be found on disk.
115    #[error("Cubemap face file not found: {0}")]
116    CubemapFaceNotFound(String),
117
118    // -----------------------------------------------------------------------
119    // Surface / presentation
120    // -----------------------------------------------------------------------
121    /// `Surface::get_current_texture()` failed (timeout, outdated, lost, ...).
122    #[error("GPU surface error: {0}")]
123    Surface(#[from] wgpu::SurfaceError),
124
125    // -----------------------------------------------------------------------
126    // Screenshot
127    // -----------------------------------------------------------------------
128    /// The GPU buffer could not be mapped back to CPU memory, or a render
129    /// step during screenshot capture failed.
130    #[error("Screenshot capture failed: {0}")]
131    ScreenshotMap(String),
132
133    /// The pixel data could not be assembled into a final `RgbaImage`.
134    #[error("Screenshot image assembly failed")]
135    ScreenshotImageAssembly,
136}
137
138// ---------------------------------------------------------------------------
139// Convenience conversions from common upstream error types
140// ---------------------------------------------------------------------------
141
142impl From<wgpu::CreateSurfaceError> for RenderError {
143    fn from(e: wgpu::CreateSurfaceError) -> Self {
144        RenderError::SurfaceCreation(e.to_string())
145    }
146}
147
148impl From<wgpu::RequestDeviceError> for RenderError {
149    fn from(e: wgpu::RequestDeviceError) -> Self {
150        RenderError::DeviceError(e.to_string())
151    }
152}