Skip to content

Commit 09a20a4

Browse files
authored
Use thiserror in re_renderer everywhere except shader file reloading (#4759)
### What * part of #1845 Started also removing it the file resolver/reloader but it's super tedious and makes errors worse since during include resolve we often want to stack errors. We can revisit that if we ever move out the shader reloading or when we tackle * #2664 but otherwise I don't think it's worth it. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/4759/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/4759/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/4759/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG - [PR Build Summary](https://build.rerun.io/pr/4759) - [Docs preview](https://rerun.io/preview/79d6075baae6651555be0431005e07817440c3b5/docs) <!--DOCS-PREVIEW--> - [Examples preview](https://rerun.io/preview/79d6075baae6651555be0431005e07817440c3b5/examples) <!--EXAMPLES-PREVIEW--> - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)
1 parent 48f64a7 commit 09a20a4

5 files changed

Lines changed: 100 additions & 45 deletions

File tree

crates/re_renderer/src/config.rs

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,21 @@ pub enum DeviceTier {
2323
//HighEnd
2424
}
2525

26+
#[derive(thiserror::Error, Debug)]
27+
pub enum InsufficientDeviceCapabilities {
28+
#[error("Adapter does not support the minimum shader model required. Supported is {actual:?} but required is {required:?}")]
29+
TooLowShaderModel {
30+
required: wgpu::ShaderModel,
31+
actual: wgpu::ShaderModel,
32+
},
33+
34+
#[error("Adapter does not have all the required capability flags required. Supported are {actual:?} but required are {required:?}")]
35+
MissingCapabilitiesFlags {
36+
required: wgpu::DownlevelFlags,
37+
actual: wgpu::DownlevelFlags,
38+
},
39+
}
40+
2641
/// Capabilities of a given device.
2742
///
2843
/// Generally, this is a higher level interpretation of [`wgpu::Limits`].
@@ -115,25 +130,27 @@ impl DeviceCaps {
115130
/// Checks if passed downlevel capabilities support the given device tier.
116131
pub fn check_downlevel_capabilities(
117132
&self,
118-
downlevel_capabilities: &wgpu::DownlevelCapabilities,
119-
) -> anyhow::Result<()> {
120-
let required_downlevel_capabilities = self.required_downlevel_capabilities();
121-
anyhow::ensure!(
122-
downlevel_capabilities.shader_model >= required_downlevel_capabilities.shader_model,
123-
"Adapter does not support the minimum shader model required to run re_renderer at the {:?} tier: {:?}",
124-
self.tier,
125-
required_downlevel_capabilities.shader_model
126-
);
127-
anyhow::ensure!(
128-
downlevel_capabilities
129-
.flags
130-
.contains(required_downlevel_capabilities.flags),
131-
"Adapter does not support the downlevel capabilities required to run re_renderer at the {:?} tier: {:?}",
132-
self.tier,
133-
required_downlevel_capabilities.flags - downlevel_capabilities.flags
134-
);
135-
136-
Ok(())
133+
capabilities: &wgpu::DownlevelCapabilities,
134+
) -> Result<(), InsufficientDeviceCapabilities> {
135+
let wgpu::DownlevelCapabilities {
136+
flags,
137+
limits: _,
138+
shader_model,
139+
} = self.required_downlevel_capabilities();
140+
141+
if capabilities.shader_model < shader_model {
142+
Err(InsufficientDeviceCapabilities::TooLowShaderModel {
143+
required: shader_model,
144+
actual: capabilities.shader_model,
145+
})
146+
} else if !capabilities.flags.contains(flags) {
147+
Err(InsufficientDeviceCapabilities::MissingCapabilitiesFlags {
148+
required: flags,
149+
actual: capabilities.flags,
150+
})
151+
} else {
152+
Ok(())
153+
}
137154
}
138155
}
139156

crates/re_renderer/src/importer/gltf.rs

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,54 @@
11
use std::sync::Arc;
22

33
use ahash::{HashMap, HashMapExt};
4-
use anyhow::Context as _;
54
use gltf::texture::WrappingMode;
65
use itertools::Itertools;
76
use smallvec::SmallVec;
87

98
use crate::{
10-
mesh::{Material, Mesh},
9+
mesh::{Material, Mesh, MeshError},
1110
renderer::MeshInstance,
1211
resource_managers::{
13-
GpuMeshHandle, GpuTexture2D, ResourceLifeTime, Texture2DCreationDesc, TextureManager2D,
12+
GpuMeshHandle, GpuTexture2D, ResourceLifeTime, ResourceManagerError, Texture2DCreationDesc,
13+
TextureManager2D,
1414
},
1515
RenderContext, Rgba32Unmul,
1616
};
1717

18+
#[derive(thiserror::Error, Debug)]
19+
pub enum GltfImportError {
20+
#[error(transparent)]
21+
GltfLoading(#[from] gltf::Error),
22+
23+
#[error(transparent)]
24+
ResourceManager(#[from] ResourceManagerError),
25+
26+
#[error(transparent)]
27+
MeshError(#[from] MeshError),
28+
29+
#[error("Unsupported texture format {0:?}.")]
30+
UnsupportedTextureFormat(gltf::image::Format),
31+
32+
#[error("Mesh {mesh_name:?} has multiple sets of texture coordinates. Only a single one is supported.")]
33+
MultipleTextureCoordinateSets { mesh_name: String },
34+
35+
#[error("Mesh {mesh_name:?} has no triangles.")]
36+
NoIndices { mesh_name: String },
37+
38+
#[error("Mesh {mesh_name:?} has no vertex positions.")]
39+
NoPositions { mesh_name: String },
40+
41+
#[error("Mesh {mesh_name:?} has no triangle primitives.")]
42+
NoTrianglePrimitives { mesh_name: String },
43+
}
44+
1845
/// Loads both gltf and glb into the mesh & texture manager.
1946
pub fn load_gltf_from_buffer(
2047
mesh_name: &str,
2148
buffer: &[u8],
2249
lifetime: ResourceLifeTime,
2350
ctx: &RenderContext,
24-
) -> anyhow::Result<Vec<MeshInstance>> {
51+
) -> Result<Vec<MeshInstance>, GltfImportError> {
2552
re_tracing::profile_function!();
2653

2754
let (doc, buffers, images) = {
@@ -44,7 +71,7 @@ pub fn load_gltf_from_buffer(
4471
crate::pad_rgb_to_rgba(&image.pixels, 255),
4572
)
4673
} else {
47-
anyhow::bail!("Unsupported texture format {:?}", image.format);
74+
return Err(GltfImportError::UnsupportedTextureFormat(image.format));
4875
}
4976
};
5077

@@ -93,8 +120,7 @@ pub fn load_gltf_from_buffer(
93120
for ref mesh in doc.meshes() {
94121
re_tracing::profile_scope!("mesh");
95122

96-
let re_mesh = import_mesh(mesh, &buffers, &images_as_textures, &ctx.texture_manager_2d)
97-
.with_context(|| format!("mesh {} (name {:?})", mesh.index(), mesh.name()))?;
123+
let re_mesh = import_mesh(mesh, &buffers, &images_as_textures, &ctx.texture_manager_2d)?;
98124
meshes.insert(
99125
mesh.index(),
100126
(
@@ -140,9 +166,11 @@ fn import_mesh(
140166
buffers: &[gltf::buffer::Data],
141167
gpu_image_handles: &[GpuTexture2D],
142168
texture_manager: &TextureManager2D, //imported_materials: HashMap<usize, Material>,
143-
) -> anyhow::Result<Mesh> {
169+
) -> Result<Mesh, GltfImportError> {
144170
re_tracing::profile_function!();
145171

172+
let mesh_name = mesh.name().map_or("<unknown", |f| f).to_owned();
173+
146174
let mut triangle_indices = Vec::new();
147175
let mut vertex_positions = Vec::new();
148176
let mut vertex_colors = Vec::new();
@@ -171,13 +199,13 @@ fn import_mesh(
171199
.map(glam::UVec3::from),
172200
);
173201
} else {
174-
anyhow::bail!("Gltf primitives must have indices");
202+
return Err(GltfImportError::NoIndices { mesh_name });
175203
}
176204

177205
if let Some(primitive_positions) = reader.read_positions() {
178206
vertex_positions.extend(primitive_positions.map(glam::Vec3::from));
179207
} else {
180-
anyhow::bail!("Gltf primitives must have positions");
208+
return Err(GltfImportError::NoPositions { mesh_name });
181209
}
182210

183211
if let Some(colors) = reader.read_colors(set) {
@@ -206,10 +234,9 @@ fn import_mesh(
206234
let pbr_material = primitive_material.pbr_metallic_roughness();
207235

208236
let albedo = if let Some(texture) = pbr_material.base_color_texture() {
209-
anyhow::ensure!(
210-
texture.tex_coord() == 0,
211-
"Only a single set of texture coordinates is supported"
212-
);
237+
if texture.tex_coord() != 0 {
238+
return Err(GltfImportError::MultipleTextureCoordinateSets { mesh_name });
239+
}
213240
let texture = &texture.texture();
214241

215242
let sampler = &texture.sampler();
@@ -259,7 +286,7 @@ fn import_mesh(
259286
});
260287
}
261288
if vertex_positions.is_empty() || triangle_indices.is_empty() {
262-
anyhow::bail!("empty mesh");
289+
return Err(GltfImportError::NoTrianglePrimitives { mesh_name });
263290
}
264291

265292
let mesh = Mesh {

crates/re_renderer/src/importer/obj.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,33 @@
11
use std::sync::Arc;
22

3-
use anyhow::Context as _;
43
use smallvec::smallvec;
54

65
use crate::{
7-
mesh::{Material, Mesh},
6+
mesh::{Material, Mesh, MeshError},
87
renderer::MeshInstance,
9-
resource_managers::ResourceLifeTime,
8+
resource_managers::{ResourceLifeTime, ResourceManagerError},
109
RenderContext, Rgba32Unmul,
1110
};
1211

12+
#[derive(thiserror::Error, Debug)]
13+
pub enum ObjImportError {
14+
#[error(transparent)]
15+
ObjLoading(#[from] tobj::LoadError),
16+
17+
#[error(transparent)]
18+
Mesh(#[from] MeshError),
19+
20+
#[error(transparent)]
21+
ResourceManager(#[from] ResourceManagerError),
22+
}
23+
1324
/// Load a [Wavefront .obj file](https://en.wikipedia.org/wiki/Wavefront_.obj_file)
1425
/// into the mesh & texture manager.
1526
pub fn load_obj_from_buffer(
1627
buffer: &[u8],
1728
lifetime: ResourceLifeTime,
1829
ctx: &RenderContext,
19-
) -> anyhow::Result<Vec<MeshInstance>> {
30+
) -> Result<Vec<MeshInstance>, ObjImportError> {
2031
re_tracing::profile_function!();
2132

2233
let (models, _materials) = tobj::load_obj_buf(
@@ -27,8 +38,7 @@ pub fn load_obj_from_buffer(
2738
..Default::default()
2839
},
2940
|_material_path| Err(tobj::LoadError::MaterialParseError),
30-
)
31-
.context("failed loading obj")?;
41+
)?;
3242

3343
// TODO(andreas) Merge all obj meshes into a single re_renderer mesh with multiple materials.
3444
models

crates/re_renderer/src/renderer/mesh_renderer.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::{
1212
draw_phases::{DrawPhase, OutlineMaskProcessor},
1313
include_shader_module,
1414
mesh::{gpu_data::MaterialUniformBuffer, mesh_vertices, GpuMesh, Mesh},
15-
resource_managers::{GpuMeshHandle, ResourceHandle},
15+
resource_managers::{GpuMeshHandle, ResourceHandle, ResourceManagerError},
1616
view_builder::ViewBuilder,
1717
wgpu_resources::{
1818
BindGroupLayoutDesc, BufferDesc, GpuBindGroupLayoutHandle, GpuBuffer,
@@ -151,7 +151,10 @@ impl MeshDrawData {
151151
/// Try bundling all mesh instances into a single draw data instance whenever possible.
152152
/// If you pass zero mesh instances, subsequent drawing will do nothing.
153153
/// Mesh data itself is gpu uploaded if not already present.
154-
pub fn new(ctx: &RenderContext, instances: &[MeshInstance]) -> anyhow::Result<Self> {
154+
pub fn new(
155+
ctx: &RenderContext,
156+
instances: &[MeshInstance],
157+
) -> Result<MeshDrawData, ResourceManagerError> {
155158
re_tracing::profile_function!();
156159

157160
let _mesh_renderer = ctx.renderer::<MeshRenderer>();

crates/re_renderer/src/view_builder.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use anyhow::Context;
21
use parking_lot::RwLock;
32
use std::sync::Arc;
43

@@ -517,8 +516,7 @@ impl ViewBuilder {
517516
phase,
518517
pass,
519518
queued_draw.draw_data.as_ref(),
520-
)
521-
.with_context(|| format!("draw call during phase {phase:?}"));
519+
);
522520
if let Err(err) = res {
523521
re_log::error!(renderer=%queued_draw.renderer_name, %err,
524522
"renderer failed to draw");

0 commit comments

Comments
 (0)