1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
//! The render error type.
use thiserror::Error;
/// Everything that can go wrong constructing or driving the engine.
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum RenderError {
/// A device-level failure, carried upward with its own code.
#[error(transparent)]
Gpu(#[from] molgfx_gpu::GpuError),
/// A CPU-built hierarchy exceeded the compact GPU index layout.
#[error(transparent)]
Acceleration(#[from] molgfx_math::BvhBuildError),
/// A logical entity row cannot be encoded in a chunk-local GPU identity.
#[error(transparent)]
Entity(#[from] molgfx_core::EntityIdError),
/// A bounded global picking page transition or readback was invalid.
#[error(transparent)]
Picking(#[from] molgfx_core::PickingError),
/// A chunk span used by a resident pick page was invalid.
#[error(transparent)]
Dataset(#[from] molgfx_core::DatasetError),
/// A visible scene entity references a structure that is no longer resident.
#[error("picking entity owner is not resident")]
PickingOwnerMissing,
/// A GPU record requested a namespace absent from the bounded page table.
#[error("dataset {dataset} has no resident {kind:?} picking page")]
PickingPageMissing {
/// Dataset whose page was required.
dataset: molgfx_core::DatasetId,
/// Entity namespace whose page was required.
kind: molgfx_core::EntityKind,
},
/// A validated dynamic relation source is not resident in the GPU scene.
#[error("dynamic relation source {domain:?} is not resident")]
RelationSourceMissing {
/// Spatial table required by the relation stream.
domain: molgfx_core::RowDomain,
},
/// CPU lowering exceeded a compact GPU record field.
#[error(transparent)]
Packing(#[from] molgfx_geometry::PackingError),
/// The render graph contains a dependency cycle.
#[error("render graph cycle involving pass {pass:?}")]
GraphCycle {
/// A pass on the cycle.
pass: &'static str,
},
/// A pass referenced a resource id the graph never declared.
#[error("pass {pass:?} references undeclared resource {resource}")]
UnknownResource {
/// The offending pass.
pass: &'static str,
/// The undeclared id.
resource: u32,
},
/// Off-screen dimensions overflowed a portable texture/readback layout.
#[error("invalid off-screen image dimensions")]
InvalidImageSize,
/// A physical representation requires source annotations not exposed by its provider.
#[error("molecular source does not provide {capability}")]
SourceCapabilityMissing {
/// Required provider capability.
capability: &'static str,
},
/// Sequence timestamps or buffering parameters violate the deterministic contract.
#[error("invalid render sequence: {reason}")]
InvalidSequence {
/// Stable caller-actionable reason.
reason: &'static str,
},
/// The caller must drain a completed sequence frame before submitting more work.
#[error("render sequence reached its {max_in_flight}-frame in-flight limit")]
SequenceBackpressure {
/// Configured bounded readback depth.
max_in_flight: u8,
},
/// A scene-tracked optical target is stale, empty, or behind the camera.
#[error("invalid optical focus target: {reason}")]
InvalidFocusTarget {
/// Stable, caller-actionable reason.
reason: &'static str,
},
/// The mapped image could not be encoded for publication.
#[error("image encoding failed: {summary}")]
ImageEncoding {
/// Encoder-provided diagnostic.
summary: String,
},
/// A render session could not be encoded or decoded.
#[error("render session encoding failed: {summary}")]
SessionEncoding {
/// Serializer-provided diagnostic.
summary: String,
},
/// Fixed residency capacity or lifecycle state rejected frame work.
#[error("residency operation failed: {reason}")]
Residency {
/// Stable failure category without backend-specific text allocation.
reason: &'static str,
},
/// Provider chunk residency failed with a typed lifecycle or capacity error.
#[error(transparent)]
ChunkResidency(#[from] crate::engine::ChunkResidencyError),
/// Sparse volume atlas validation, capacity or lifecycle failure.
#[error(transparent)]
BrickAtlas(#[from] crate::scene_gpu::brick_atlas::types::BrickAtlasError),
/// One caller-owned dataset id was reused for different immutable data.
#[error(
"dataset {dataset} identifies conflicting immutable assets ({resident_fingerprint:#018x} != {incoming_fingerprint:#018x})"
)]
AssetIdentityCollision {
/// Caller-owned dataset identity that collided.
dataset: molgfx_core::DatasetId,
/// Fingerprint already resident for the dataset.
resident_fingerprint: u64,
/// Fingerprint supplied by the incoming placement.
incoming_fingerprint: u64,
},
/// Sampled-surface component lowering exceeded its bounded working set.
#[error("surface component filtering failed: {reason}")]
SurfaceComponents {
/// Stable validation or capacity reason.
reason: &'static str,
},
/// Immutable GPU storage could not allocate or relocate safely.
#[error(transparent)]
AssetArena(#[from] crate::scene_gpu::AssetArenaError),
}
impl RenderError {
/// The stable registry code for this condition.
#[must_use]
pub fn code(&self) -> &'static str {
match self {
Self::Gpu(e) => e.code(),
Self::Acceleration(_) => "MOLGFX-E0077",
Self::Entity(_) => "MOLGFX-E0078",
Self::Picking(_) => "MOLGFX-E0082",
Self::Dataset(_) => "MOLGFX-E0083",
Self::PickingOwnerMissing => "MOLGFX-E0084",
Self::PickingPageMissing { .. } => "MOLGFX-E0085",
Self::RelationSourceMissing { .. } => "MOLGFX-E0091",
Self::Packing(_) => "MOLGFX-E0079",
Self::GraphCycle { .. } => "MOLGFX-E0070",
Self::UnknownResource { .. } => "MOLGFX-E0071",
Self::InvalidImageSize => "MOLGFX-E0072",
Self::SourceCapabilityMissing { .. } => "MOLGFX-E0092",
Self::InvalidSequence { .. } => "MOLGFX-E0089",
Self::SequenceBackpressure { .. } => "MOLGFX-E0090",
Self::InvalidFocusTarget { .. } => "MOLGFX-E0073",
Self::ImageEncoding { .. } => "MOLGFX-E0074",
Self::SessionEncoding { .. } => "MOLGFX-E0075",
Self::Residency { .. } => "MOLGFX-E0076",
Self::ChunkResidency(_) => "MOLGFX-E0086",
Self::BrickAtlas(_) => "MOLGFX-E0088",
Self::AssetIdentityCollision { .. } => "MOLGFX-E0080",
Self::SurfaceComponents { .. } => "MOLGFX-E0087",
Self::AssetArena(_) => "MOLGFX-E0081",
}
}
}