1use thiserror::Error;
4
5#[derive(Debug, Error)]
7#[non_exhaustive]
8pub enum RenderError {
9 #[error(transparent)]
11 Gpu(#[from] molgfx_gpu::GpuError),
12
13 #[error(transparent)]
15 Acceleration(#[from] molgfx_math::BvhBuildError),
16
17 #[error(transparent)]
19 Entity(#[from] molgfx_core::EntityIdError),
20
21 #[error(transparent)]
23 Picking(#[from] molgfx_core::PickingError),
24
25 #[error(transparent)]
27 Dataset(#[from] molgfx_core::DatasetError),
28
29 #[error("picking entity owner is not resident")]
31 PickingOwnerMissing,
32
33 #[error("dataset {dataset} has no resident {kind:?} picking page")]
35 PickingPageMissing {
36 dataset: molgfx_core::DatasetId,
38 kind: molgfx_core::EntityKind,
40 },
41
42 #[error("dynamic relation source {domain:?} is not resident")]
44 RelationSourceMissing {
45 domain: molgfx_core::RowDomain,
47 },
48
49 #[error(transparent)]
51 Packing(#[from] molgfx_geometry::PackingError),
52
53 #[error("render graph cycle involving pass {pass:?}")]
55 GraphCycle {
56 pass: &'static str,
58 },
59
60 #[error("pass {pass:?} references undeclared resource {resource}")]
62 UnknownResource {
63 pass: &'static str,
65 resource: u32,
67 },
68
69 #[error("invalid off-screen image dimensions")]
71 InvalidImageSize,
72
73 #[error("molecular source does not provide {capability}")]
75 SourceCapabilityMissing {
76 capability: &'static str,
78 },
79
80 #[error("invalid render sequence: {reason}")]
82 InvalidSequence {
83 reason: &'static str,
85 },
86
87 #[error("render sequence reached its {max_in_flight}-frame in-flight limit")]
89 SequenceBackpressure {
90 max_in_flight: u8,
92 },
93
94 #[error("invalid optical focus target: {reason}")]
96 InvalidFocusTarget {
97 reason: &'static str,
99 },
100
101 #[error("image encoding failed: {summary}")]
103 ImageEncoding {
104 summary: String,
106 },
107
108 #[error("render session encoding failed: {summary}")]
110 SessionEncoding {
111 summary: String,
113 },
114
115 #[error("residency operation failed: {reason}")]
117 Residency {
118 reason: &'static str,
120 },
121
122 #[error(transparent)]
124 ChunkResidency(#[from] crate::engine::ChunkResidencyError),
125
126 #[error(transparent)]
128 BrickAtlas(#[from] crate::scene_gpu::brick_atlas::types::BrickAtlasError),
129
130 #[error(
132 "dataset {dataset} identifies conflicting immutable assets ({resident_fingerprint:#018x} != {incoming_fingerprint:#018x})"
133 )]
134 AssetIdentityCollision {
135 dataset: molgfx_core::DatasetId,
137 resident_fingerprint: u64,
139 incoming_fingerprint: u64,
141 },
142
143 #[error("surface component filtering failed: {reason}")]
145 SurfaceComponents {
146 reason: &'static str,
148 },
149
150 #[error(transparent)]
152 AssetArena(#[from] crate::scene_gpu::AssetArenaError),
153}
154
155impl RenderError {
156 #[must_use]
158 pub fn code(&self) -> &'static str {
159 match self {
160 Self::Gpu(e) => e.code(),
161 Self::Acceleration(_) => "MOLGFX-E0077",
162 Self::Entity(_) => "MOLGFX-E0078",
163 Self::Picking(_) => "MOLGFX-E0082",
164 Self::Dataset(_) => "MOLGFX-E0083",
165 Self::PickingOwnerMissing => "MOLGFX-E0084",
166 Self::PickingPageMissing { .. } => "MOLGFX-E0085",
167 Self::RelationSourceMissing { .. } => "MOLGFX-E0091",
168 Self::Packing(_) => "MOLGFX-E0079",
169 Self::GraphCycle { .. } => "MOLGFX-E0070",
170 Self::UnknownResource { .. } => "MOLGFX-E0071",
171 Self::InvalidImageSize => "MOLGFX-E0072",
172 Self::SourceCapabilityMissing { .. } => "MOLGFX-E0092",
173 Self::InvalidSequence { .. } => "MOLGFX-E0089",
174 Self::SequenceBackpressure { .. } => "MOLGFX-E0090",
175 Self::InvalidFocusTarget { .. } => "MOLGFX-E0073",
176 Self::ImageEncoding { .. } => "MOLGFX-E0074",
177 Self::SessionEncoding { .. } => "MOLGFX-E0075",
178 Self::Residency { .. } => "MOLGFX-E0076",
179 Self::ChunkResidency(_) => "MOLGFX-E0086",
180 Self::BrickAtlas(_) => "MOLGFX-E0088",
181 Self::AssetIdentityCollision { .. } => "MOLGFX-E0080",
182 Self::SurfaceComponents { .. } => "MOLGFX-E0087",
183 Self::AssetArena(_) => "MOLGFX-E0081",
184 }
185 }
186}