Skip to main content

scena/diagnostics/
display.rs

1use std::error;
2use std::fmt;
3
4use super::{
5    AnimationError, AssetError, BuildError, Error, ImportError, InstantiateError, LookupError,
6    NotPreparedReason, PrepareError, RenderError,
7};
8
9#[path = "display/asset.rs"]
10mod asset;
11
12impl fmt::Display for Error {
13    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
14        match self {
15            Self::Build(error) => error.fmt(formatter),
16            Self::Asset(error) => error.fmt(formatter),
17            Self::Import(error) => error.fmt(formatter),
18            Self::Instantiate(error) => error.fmt(formatter),
19            Self::Prepare(error) => error.fmt(formatter),
20            Self::Render(error) => error.fmt(formatter),
21            Self::Lookup(error) => error.fmt(formatter),
22            Self::Animation(error) => error.fmt(formatter),
23        }
24    }
25}
26
27impl fmt::Display for BuildError {
28    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
29        match self {
30            Self::InvalidTargetSize { width, height } => {
31                write!(formatter, "invalid render target size {width}x{height}")
32            }
33            Self::AsyncSurfaceRequired { backend } => {
34                write!(
35                    formatter,
36                    "attached surface initialization for {backend:?} requires async construction"
37                )
38            }
39            Self::CreateSurface { backend } => {
40                write!(formatter, "failed to create GPU surface for {backend:?}")
41            }
42            Self::NoAdapter { backend } => {
43                write!(formatter, "no compatible GPU adapter found for {backend:?}")
44            }
45            Self::RequestDevice { backend } => {
46                write!(formatter, "failed to request GPU device for {backend:?}")
47            }
48            Self::SurfaceUnsupported { backend } => {
49                write!(
50                    formatter,
51                    "no compatible surface configuration found for {backend:?}"
52                )
53            }
54            Self::UnsupportedBackend { backend } => {
55                write!(
56                    formatter,
57                    "backend {backend:?} is not supported on this target"
58                )
59            }
60        }
61    }
62}
63
64impl fmt::Display for ImportError {
65    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
66        match self {
67            Self::Asset(error) => error.fmt(formatter),
68            Self::Instantiate(error) => error.fmt(formatter),
69        }
70    }
71}
72
73impl From<AssetError> for ImportError {
74    fn from(error: AssetError) -> Self {
75        Self::Asset(error)
76    }
77}
78
79impl From<InstantiateError> for ImportError {
80    fn from(error: InstantiateError) -> Self {
81        Self::Instantiate(error)
82    }
83}
84
85impl fmt::Display for InstantiateError {
86    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
87        match self {
88            Self::InvalidChildIndex { parent, child } => write!(
89                formatter,
90                "glTF node {parent} references invalid child node index {child}"
91            ),
92            Self::InvalidSkinIndex { node, skin } => {
93                write!(
94                    formatter,
95                    "glTF node {node} references invalid skin index {skin}"
96                )
97            }
98            Self::InvalidSkinJointIndex { skin, joint } => write!(
99                formatter,
100                "glTF skin {skin} references invalid joint node index {joint}"
101            ),
102            Self::InvalidAnchorExtras { node, reason } => {
103                write!(
104                    formatter,
105                    "glTF node {node} has invalid anchor extras: {reason}"
106                )
107            }
108            Self::UnsupportedCoordinateSystem {
109                coordinate_system,
110                reason,
111            } => write!(
112                formatter,
113                "source coordinate system {coordinate_system:?} is not supported for this import: {reason}"
114            ),
115        }
116    }
117}
118
119impl fmt::Display for PrepareError {
120    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
121        match self {
122            Self::InvalidTargetSize { width, height } => {
123                write!(formatter, "invalid render target size {width}x{height}")
124            }
125            Self::AssetsRequired { node } => {
126                write!(
127                    formatter,
128                    "node {node:?} references asset handles; call prepare_with_assets"
129                )
130            }
131            Self::GeometryNotFound { node, geometry } => {
132                write!(
133                    formatter,
134                    "node {node:?} references missing geometry handle {geometry:?}"
135                )
136            }
137            Self::MaterialNotFound { node, material } => {
138                write!(
139                    formatter,
140                    "node {node:?} references missing material handle {material:?}"
141                )
142            }
143            Self::TextureNotFound {
144                node,
145                material,
146                texture,
147                slot,
148            } => {
149                write!(
150                    formatter,
151                    "node {node:?} material {material:?} references missing texture handle {texture:?} in slot {slot}"
152                )
153            }
154            Self::EnvironmentAssetsRequired { environment } => {
155                write!(
156                    formatter,
157                    "environment handle {environment:?} requires prepare_with_assets"
158                )
159            }
160            Self::EnvironmentNotFound { environment } => {
161                write!(
162                    formatter,
163                    "active environment handle {environment:?} was not found in assets"
164                )
165            }
166            Self::UnsupportedGeometryTopology { node, topology } => {
167                write!(
168                    formatter,
169                    "node {node:?} uses unsupported geometry topology {topology:?}"
170                )
171            }
172            Self::UnsupportedMaterialKind { node, kind } => {
173                write!(
174                    formatter,
175                    "node {node:?} uses unsupported material kind {kind:?}"
176                )
177            }
178            Self::UnsupportedAlphaMode { node, alpha_mode } => {
179                write!(
180                    formatter,
181                    "node {node:?} uses unsupported alpha mode {alpha_mode:?}"
182                )
183            }
184            Self::UnsupportedModelNode { node } => {
185                write!(
186                    formatter,
187                    "node {node:?} is a model node; model preparation is not implemented"
188                )
189            }
190            Self::MultipleShadowedDirectionalLights { first, second } => write!(
191                formatter,
192                "only one shadowed directional light is supported; nodes {first:?} and {second:?} both cast shadows"
193            ),
194            Self::InvalidSkinGeometry { node, reason } => {
195                write!(
196                    formatter,
197                    "node {node:?} has invalid skin geometry: {reason}"
198                )
199            }
200            Self::BackendCapabilityMismatch {
201                feature,
202                backend,
203                help,
204            } => {
205                write!(
206                    formatter,
207                    "backend {backend:?} cannot provide required feature {feature}: {help}"
208                )
209            }
210            Self::GpuResourceUpload { backend, reason } => {
211                write!(
212                    formatter,
213                    "backend {backend:?} failed during explicit GPU resource upload: {reason}"
214                )
215            }
216        }
217    }
218}
219
220impl fmt::Display for RenderError {
221    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
222        match self {
223            Self::NotPrepared { reason } => write!(formatter, "renderer is not prepared: {reason}"),
224            Self::NoActiveCamera => write!(formatter, "scene has no active camera"),
225            Self::CameraNotFound(_) => write!(formatter, "camera key does not exist in the scene"),
226            Self::InvalidSurfaceSize { width, height } => {
227                write!(formatter, "invalid surface size {width}x{height}")
228            }
229            Self::SurfaceLost { recoverable } => {
230                write!(
231                    formatter,
232                    "render surface was lost; recoverable={recoverable}"
233                )
234            }
235            Self::ContextLost { recoverable } => {
236                write!(
237                    formatter,
238                    "render context was lost; recoverable={recoverable}"
239                )
240            }
241            Self::GpuDeviceLost { recoverable } => {
242                write!(formatter, "GPU device was lost; recoverable={recoverable}")
243            }
244            Self::GpuResourcesNotPrepared { backend } => {
245                write!(formatter, "GPU resources for {backend:?} were not prepared")
246            }
247            Self::UnsupportedSampleCount {
248                backend,
249                requested,
250                maximum,
251            } => {
252                write!(
253                    formatter,
254                    "backend {backend:?} does not support MSAA sample count {requested}; maximum supported sample count is {maximum}"
255                )
256            }
257            Self::UnsupportedSupersampleFactor {
258                factor,
259                width,
260                height,
261                scaled_width,
262                scaled_height,
263                maximum_dimension,
264                maximum_pixels,
265            } => {
266                write!(
267                    formatter,
268                    "supersample factor {factor} for {width}x{height} would render {scaled_width}x{scaled_height}, exceeding the maximum internal target {maximum_dimension}px per axis or {maximum_pixels} pixels"
269                )
270            }
271            Self::GpuReadback { backend } => {
272                write!(formatter, "failed to read rendered output for {backend:?}")
273            }
274        }
275    }
276}
277
278impl fmt::Display for NotPreparedReason {
279    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
280        match self {
281            Self::NeverPrepared => write!(formatter, "prepare has not been called"),
282            Self::DifferentScene => write!(formatter, "prepare was called for a different scene"),
283            Self::SceneChanged {
284                prepared_revision,
285                current_revision,
286                change,
287            }
288            | Self::EnvironmentChanged {
289                prepared_revision,
290                current_revision,
291                change,
292            } => write!(
293                formatter,
294                "prepared state changed after prepare ({prepared_revision} -> {current_revision}, {change:?})"
295            ),
296            Self::TargetChanged {
297                prepared_revision,
298                current_revision,
299                change,
300            } => write!(
301                formatter,
302                "render target changed after prepare ({prepared_revision} -> {current_revision}, {change:?})"
303            ),
304        }
305    }
306}
307
308impl fmt::Display for LookupError {
309    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
310        match self {
311            Self::NodeNotFound(_) => write!(formatter, "node key does not exist in the scene"),
312            Self::CannotRemoveRootNode(_) => {
313                write!(formatter, "the scene root node cannot be removed")
314            }
315            Self::NodeNameNotFound { name } => {
316                write!(formatter, "imported scene has no node named '{name}'")
317            }
318            Self::AmbiguousNodeName { name, matches } => write!(
319                formatter,
320                "imported scene node name '{name}' is ambiguous across {} nodes",
321                matches.len()
322            ),
323            Self::AnchorNotFound { name } => {
324                write!(formatter, "imported scene has no anchor named '{name}'")
325            }
326            Self::AmbiguousAnchorName { name, hosts } => write!(
327                formatter,
328                "imported scene anchor name '{name}' is ambiguous across {} host nodes",
329                hosts.len()
330            ),
331            Self::ConnectorNotFound { name } => {
332                write!(formatter, "imported scene has no connector named '{name}'")
333            }
334            Self::AmbiguousConnectorName { name, hosts } => write!(
335                formatter,
336                "imported scene connector name '{name}' is ambiguous across {} host nodes",
337                hosts.len()
338            ),
339            Self::ClipNotFound { name } => {
340                write!(
341                    formatter,
342                    "imported scene has no animation clip named '{name}'"
343                )
344            }
345            Self::VariantNotFound { name } => write!(
346                formatter,
347                "imported scene has no KHR_materials_variants variant named '{name}'"
348            ),
349            Self::AmbiguousVariantName { name, matches } => write!(
350                formatter,
351                "imported scene KHR_materials_variants name '{name}' is ambiguous across {} variants",
352                matches.len()
353            ),
354            Self::AmbiguousClipName { name, matches } => write!(
355                formatter,
356                "imported scene animation clip name '{name}' is ambiguous across {} clips",
357                matches.len()
358            ),
359            Self::PathNotFound { path } => {
360                write!(formatter, "imported scene path '{path}' was not found")
361            }
362            Self::InvalidViewport { width, height } => {
363                write!(
364                    formatter,
365                    "viewport {width}x{height} is invalid; width and height must be non-zero"
366                )
367            }
368            Self::InvalidBounds { reason } => {
369                write!(formatter, "bounds are invalid: {reason}")
370            }
371            Self::InvalidFramingOption { field, reason } => {
372                write!(
373                    formatter,
374                    "camera framing option '{field}' is invalid: {reason}"
375                )
376            }
377            Self::UnsupportedCameraType {
378                camera,
379                operation,
380                supported,
381            } => {
382                write!(
383                    formatter,
384                    "{operation} does not support camera {camera:?}; supported camera type: {supported}"
385                )
386            }
387            Self::ImportHasNoBounds => {
388                write!(
389                    formatter,
390                    "imported scene has no renderable bounds to frame"
391                )
392            }
393            Self::StaleImport => write!(formatter, "scene import has been invalidated"),
394            Self::NodeIsNotMesh { node } => write!(formatter, "node {node:?} is not a mesh node"),
395            Self::NonInvertibleParentTransform { node, parent } => write!(
396                formatter,
397                "node {node:?} cannot be placed in world space because parent {parent:?} has a non-invertible transform"
398            ),
399            Self::GeometryNotFound { node, .. } => {
400                write!(
401                    formatter,
402                    "geometry for mesh node {node:?} was not found in Assets"
403                )
404            }
405            Self::InvalidSkinBinding {
406                joint_count,
407                inverse_bind_count,
408            } => write!(
409                formatter,
410                "skin binding has {joint_count} joints but {inverse_bind_count} inverse bind matrices"
411            ),
412            Self::CameraNotFound(_) => write!(formatter, "camera key does not exist in the scene"),
413            Self::ClippingPlaneNotFound(_) => {
414                write!(formatter, "clipping plane key does not exist in the scene")
415            }
416            Self::InstanceSetNotFound(_) => {
417                write!(formatter, "instance set key does not exist in the scene")
418            }
419            Self::ParticleSetNotFound(_) => {
420                write!(formatter, "particle set key does not exist in the scene")
421            }
422            Self::InstanceNotFound {
423                instance_set,
424                instance,
425            } => write!(
426                formatter,
427                "instance {:?} does not exist in instance set {:?}",
428                instance, instance_set
429            ),
430            Self::InvalidInstanceTint {
431                instance_set,
432                instance,
433                reason,
434            } => write!(
435                formatter,
436                "instance {:?} in instance set {:?} has invalid tint: {reason}",
437                instance, instance_set
438            ),
439            Self::LabelNotFound(_) => write!(formatter, "label key does not exist in the scene"),
440            Self::UnsupportedLabelText { reason, .. } => {
441                write!(
442                    formatter,
443                    "label text is not supported by its font: {reason}"
444                )
445            }
446            Self::InvalidLabelStyle { field, reason } => {
447                write!(formatter, "{field} is not supported: {reason}")
448            }
449        }
450    }
451}
452
453impl error::Error for Error {}
454impl error::Error for BuildError {}
455impl error::Error for AssetError {}
456impl error::Error for ImportError {}
457impl error::Error for InstantiateError {}
458impl error::Error for PrepareError {}
459impl error::Error for RenderError {}
460impl error::Error for LookupError {}
461impl error::Error for AnimationError {}