Skip to main content

mtl_gpu/
error.rs

1//! Validation error types for Metal API.
2//!
3//! These errors are returned by safe wrapper methods that validate parameters
4//! before calling Metal APIs that would otherwise abort the process.
5
6use std::fmt;
7
8use mtl_foundation::UInteger;
9
10/// Validation error returned when resource creation would fail.
11///
12/// Metal's validation layer sometimes aborts the process instead of returning
13/// an error for certain invalid configurations. These safe wrapper methods
14/// validate parameters before calling Metal APIs and return this error type
15/// instead of allowing the process to abort.
16#[derive(Debug, Clone)]
17pub enum ValidationError {
18    // =========================================================================
19    // Render Pipeline Errors
20    // =========================================================================
21    /// Render pipeline descriptor is missing a required vertex function.
22    MissingVertexFunction,
23
24    /// The raster sample count is not supported by the device.
25    UnsupportedRasterSampleCount(UInteger),
26
27    // =========================================================================
28    // Compute Pipeline Errors
29    // =========================================================================
30    /// Compute pipeline descriptor is missing a required compute function.
31    MissingComputeFunction,
32
33    // =========================================================================
34    // Texture Errors
35    // =========================================================================
36    /// Texture dimensions are invalid (width, height, or depth is zero).
37    InvalidTextureDimensions {
38        width: UInteger,
39        height: UInteger,
40        depth: UInteger,
41    },
42
43    /// Requested mipmap count exceeds the maximum allowed for the texture dimensions.
44    InvalidMipmapCount {
45        requested: UInteger,
46        max_allowed: UInteger,
47    },
48
49    /// The texture sample count is not supported by the device.
50    UnsupportedTextureSampleCount(UInteger),
51
52    /// Array length is invalid (must be > 0 for array textures).
53    InvalidArrayLength,
54
55    // =========================================================================
56    // Sampler Errors
57    // =========================================================================
58    /// LOD clamp range is invalid (min must be <= max).
59    InvalidLodRange { min: f32, max: f32 },
60
61    /// Max anisotropy value is invalid (must be >= 1 and power of 2).
62    InvalidAnisotropy(UInteger),
63
64    // =========================================================================
65    // Heap Errors
66    // =========================================================================
67    /// Heap size is invalid (must be > 0).
68    InvalidHeapSize,
69
70    // =========================================================================
71    // Generic Errors
72    // =========================================================================
73    /// Metal failed to create the resource.
74    CreationFailed(Option<mtl_foundation::Error>),
75}
76
77impl fmt::Display for ValidationError {
78    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79        match self {
80            // Render Pipeline
81            ValidationError::MissingVertexFunction => {
82                write!(f, "render pipeline descriptor requires a vertex function")
83            }
84            ValidationError::UnsupportedRasterSampleCount(count) => {
85                write!(
86                    f,
87                    "raster sample count {} is not supported by device",
88                    count
89                )
90            }
91
92            // Compute Pipeline
93            ValidationError::MissingComputeFunction => {
94                write!(f, "compute pipeline descriptor requires a compute function")
95            }
96
97            // Texture
98            ValidationError::InvalidTextureDimensions {
99                width,
100                height,
101                depth,
102            } => {
103                write!(
104                    f,
105                    "invalid texture dimensions: {}x{}x{} (dimensions must be > 0)",
106                    width, height, depth
107                )
108            }
109            ValidationError::InvalidMipmapCount {
110                requested,
111                max_allowed,
112            } => {
113                write!(
114                    f,
115                    "invalid mipmap count: {} exceeds maximum {} for texture dimensions",
116                    requested, max_allowed
117                )
118            }
119            ValidationError::UnsupportedTextureSampleCount(count) => {
120                write!(
121                    f,
122                    "texture sample count {} is not supported by device",
123                    count
124                )
125            }
126            ValidationError::InvalidArrayLength => {
127                write!(f, "array length must be > 0 for array textures")
128            }
129
130            // Sampler
131            ValidationError::InvalidLodRange { min, max } => {
132                write!(
133                    f,
134                    "invalid LOD clamp range: min ({}) must be <= max ({})",
135                    min, max
136                )
137            }
138            ValidationError::InvalidAnisotropy(value) => {
139                write!(
140                    f,
141                    "invalid max anisotropy {}: must be >= 1 and a power of 2",
142                    value
143                )
144            }
145
146            // Heap
147            ValidationError::InvalidHeapSize => {
148                write!(f, "heap size must be > 0")
149            }
150
151            // Generic
152            ValidationError::CreationFailed(Some(err)) => {
153                write!(f, "resource creation failed: error code {}", err.code())
154            }
155            ValidationError::CreationFailed(None) => {
156                write!(f, "resource creation failed")
157            }
158        }
159    }
160}
161
162impl std::error::Error for ValidationError {
163    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
164        None
165    }
166}
167
168impl From<mtl_foundation::Error> for ValidationError {
169    fn from(err: mtl_foundation::Error) -> Self {
170        ValidationError::CreationFailed(Some(err))
171    }
172}