From c8121d4c6284a6d15b3c4fef216d6267dfd1fd01 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sat, 2 Dec 2023 08:40:29 +1300 Subject: [PATCH] fixed some todos --- crates/renderling-gpui/src/lib.rs | 2 +- crates/renderling-shader/src/gltf.rs | 2 +- crates/renderling-shader/src/lib.rs | 1 + crates/renderling-shader/src/pbr.rs | 3 +- crates/renderling-shader/src/slab.rs | 3 - crates/renderling-shader/src/stage.rs | 4 +- .../src/{stage => }/texture.rs | 2 - crates/renderling/src/atlas.rs | 2 +- crates/renderling/src/bloom.rs | 5 +- crates/renderling/src/lib.rs | 58 +++++++------------ crates/renderling/src/renderer.rs | 20 +++++-- crates/renderling/src/scene.rs | 3 +- crates/renderling/src/scene/gltf_support.rs | 43 ++++++-------- crates/renderling/src/skybox.rs | 4 +- crates/renderling/src/slab.rs | 2 +- crates/renderling/src/stage.rs | 4 +- crates/renderling/src/stage/gltf_support.rs | 8 +-- crates/renderling/src/state.rs | 35 ++++++----- crates/renderling/src/texture.rs | 2 +- crates/renderling/src/tutorial.rs | 10 ++-- crates/renderling/src/ui.rs | 10 +--- 21 files changed, 99 insertions(+), 124 deletions(-) rename crates/renderling-shader/src/{stage => }/texture.rs (99%) diff --git a/crates/renderling-gpui/src/lib.rs b/crates/renderling-gpui/src/lib.rs index 6c6ba613..21469b98 100644 --- a/crates/renderling-gpui/src/lib.rs +++ b/crates/renderling-gpui/src/lib.rs @@ -267,7 +267,7 @@ pub struct Gpui(pub Renderling); impl Gpui { /// Create a new UI renderer. pub fn new(width: u32, height: u32) -> Self { - let r = Renderling::headless(width, height).unwrap(); + let r = Renderling::headless(width, height); Self::new_from(&r) } diff --git a/crates/renderling-shader/src/gltf.rs b/crates/renderling-shader/src/gltf.rs index 9187978a..76d4bdb1 100644 --- a/crates/renderling-shader/src/gltf.rs +++ b/crates/renderling-shader/src/gltf.rs @@ -1,7 +1,7 @@ //! Gltf types that are used in shaders. use crate::{ self as renderling_shader, array::Array, id::Id, pbr::PbrMaterial, slab::Slabbed, - stage::GpuTexture, + texture::GpuTexture, }; #[repr(transparent)] #[derive(Default, Clone, Copy, Slabbed)] diff --git a/crates/renderling-shader/src/lib.rs b/crates/renderling-shader/src/lib.rs index 028b8f44..b83aa085 100644 --- a/crates/renderling-shader/src/lib.rs +++ b/crates/renderling-shader/src/lib.rs @@ -20,6 +20,7 @@ pub mod pbr; pub mod skybox; pub mod slab; pub mod stage; +pub mod texture; pub mod tonemapping; pub mod tutorial; pub mod ui; diff --git a/crates/renderling-shader/src/pbr.rs b/crates/renderling-shader/src/pbr.rs index af1d757f..0eabb4ca 100644 --- a/crates/renderling-shader/src/pbr.rs +++ b/crates/renderling-shader/src/pbr.rs @@ -21,7 +21,8 @@ use crate::{ id::Id, math, slab::Slab, - stage::{GpuLight, GpuTexture, LightType, LightingModel}, + stage::{GpuLight, LightType, LightingModel}, + texture::GpuTexture, IsVector, }; diff --git a/crates/renderling-shader/src/slab.rs b/crates/renderling-shader/src/slab.rs index 60066330..3c357742 100644 --- a/crates/renderling-shader/src/slab.rs +++ b/crates/renderling-shader/src/slab.rs @@ -21,9 +21,6 @@ pub trait Slabbed: core::any::Any + Sized { /// /// If the type cannot be read, the returned index will be equal /// to `index`. - // TODO: recondsider the mutability of `self` here. - // We could make this a `&self` and that might help with using it - // from multiple threads. fn read_slab(&mut self, index: usize, slab: &[u32]) -> usize; /// Write the type into the slab at starting `index` and return diff --git a/crates/renderling-shader/src/stage.rs b/crates/renderling-shader/src/stage.rs index c7c02815..f76d0e31 100644 --- a/crates/renderling-shader/src/stage.rs +++ b/crates/renderling-shader/src/stage.rs @@ -22,12 +22,10 @@ use crate::{ id::{Id, ID_NONE}, pbr::{self, PbrMaterial}, slab::{Slab, Slabbed}, + texture::GpuTexture, IsMatrix, IsVector, }; -mod texture; -pub use texture::*; - /// A vertex in a mesh. #[cfg_attr(not(target_arch = "spirv"), derive(Debug))] #[repr(C)] diff --git a/crates/renderling-shader/src/stage/texture.rs b/crates/renderling-shader/src/texture.rs similarity index 99% rename from crates/renderling-shader/src/stage/texture.rs rename to crates/renderling-shader/src/texture.rs index 622179ec..eef58a7f 100644 --- a/crates/renderling-shader/src/stage/texture.rs +++ b/crates/renderling-shader/src/texture.rs @@ -1,6 +1,4 @@ //! GPU textures. -//! -// TODO: move this (stage/texture.rs) to lib/texture.rs use glam::{UVec2, Vec2}; use renderling_derive::Slabbed; diff --git a/crates/renderling/src/atlas.rs b/crates/renderling/src/atlas.rs index 668e1d23..5d71a921 100644 --- a/crates/renderling/src/atlas.rs +++ b/crates/renderling/src/atlas.rs @@ -504,7 +504,7 @@ mod test { #[test] fn can_merge_atlas() { - let r = Renderling::headless(100, 100).unwrap(); + let r = Renderling::headless(100, 100); let (device, queue) = r.get_device_and_queue_owned(); println!("{}", std::env::current_dir().unwrap().display()); let cheetah = SceneImage::from_path("../../img/cheetah.jpg").unwrap(); diff --git a/crates/renderling/src/bloom.rs b/crates/renderling/src/bloom.rs index cb5a1cdf..ca2014fb 100644 --- a/crates/renderling/src/bloom.rs +++ b/crates/renderling/src/bloom.rs @@ -358,9 +358,8 @@ mod test { #[test] fn bloom_on_off() { - let mut renderling = Renderling::headless(100, 100) - .unwrap() - .with_background_color(glam::Vec4::splat(1.0)); + let mut renderling = + Renderling::headless(100, 100).with_background_color(glam::Vec4::splat(1.0)); let mut builder = renderling.new_scene(); let loader = builder .gltf_load("../../gltf/EmissiveStrengthTest.glb") diff --git a/crates/renderling/src/lib.rs b/crates/renderling/src/lib.rs index 6bffba7c..ae24a4ab 100644 --- a/crates/renderling/src/lib.rs +++ b/crates/renderling/src/lib.rs @@ -253,9 +253,7 @@ mod test { } fn cmy_triangle_setup() -> CmyTri { - let mut r = Renderling::headless(100, 100) - .unwrap() - .with_background_color(Vec4::splat(1.0)); + let mut r = Renderling::headless(100, 100).with_background_color(Vec4::splat(1.0)); let (projection, view) = default_ortho2d(100.0, 100.0); let mut builder = r.new_scene().with_camera(projection, view); let tri = builder @@ -349,9 +347,7 @@ mod test { #[test] fn cmy_cube_sanity() { - let mut r = Renderling::headless(100, 100) - .unwrap() - .with_background_color(Vec4::splat(1.0)); + let mut r = Renderling::headless(100, 100).with_background_color(Vec4::splat(1.0)); let mut builder = r.new_scene().with_camera( Mat4::perspective_rh(std::f32::consts::PI / 4.0, 1.0, 0.1, 100.0), Mat4::look_at_rh(Vec3::new(0.0, 12.0, 20.0), Vec3::ZERO, Vec3::Y), @@ -377,9 +373,7 @@ mod test { #[test] fn cmy_cube_visible() { - let mut r = Renderling::headless(100, 100) - .unwrap() - .with_background_color(Vec4::splat(1.0)); + let mut r = Renderling::headless(100, 100).with_background_color(Vec4::splat(1.0)); let (projection, view) = camera::default_perspective(100.0, 100.0); let mut builder = r.new_scene().with_camera(projection, view); @@ -440,9 +434,7 @@ mod test { #[test] fn cmy_cube_remesh() { - let mut r = Renderling::headless(100, 100) - .unwrap() - .with_background_color(Vec4::splat(1.0)); + let mut r = Renderling::headless(100, 100).with_background_color(Vec4::splat(1.0)); let (projection, view) = camera::default_perspective(100.0, 100.0); let mut builder = r .new_scene() @@ -533,9 +525,7 @@ mod test { // tests that updating the material actually updates the rendering of an unlit // mesh fn unlit_textured_cube_material() { - let mut r = Renderling::headless(100, 100) - .unwrap() - .with_background_color(Vec4::splat(0.0)); + let mut r = Renderling::headless(100, 100).with_background_color(Vec4::splat(0.0)); let (proj, view) = camera::default_perspective(100.0, 100.0); let mut builder = r.new_scene().with_camera(proj, view); let sandstone = SceneImage::from(image::open("../../img/sandstone.png").unwrap()); @@ -589,7 +579,8 @@ mod test { 100, 100, None as Option, - )); + )) + .unwrap(); let points = vec![ Vec4::new(0.0, 0.0, 0.0, 0.0), @@ -632,9 +623,8 @@ mod test { #[test] fn gpu_scene_sanity1() { - let mut r = Renderling::headless(100, 100) - .unwrap() - .with_background_color(Vec3::splat(0.0).extend(1.0)); + let mut r = + Renderling::headless(100, 100).with_background_color(Vec3::splat(0.0).extend(1.0)); let mut builder = r.new_scene(); let verts = vec![ @@ -730,9 +720,8 @@ mod test { #[test] fn gpu_scene_sanity2() { - let mut r = Renderling::headless(100, 100) - .unwrap() - .with_background_color(Vec3::splat(0.0).extend(1.0)); + let mut r = + Renderling::headless(100, 100).with_background_color(Vec3::splat(0.0).extend(1.0)); let (projection, view) = camera::default_ortho2d(100.0, 100.0); let mut builder = r.new_scene().with_camera(projection, view); // now test the textures functionality @@ -865,9 +854,8 @@ mod test { #[test] fn atlas_uv_mapping() { - let mut r = Renderling::headless(32, 32) - .unwrap() - .with_background_color(Vec3::splat(0.0).extend(1.0)); + let mut r = + Renderling::headless(32, 32).with_background_color(Vec3::splat(0.0).extend(1.0)); let (projection, view) = camera::default_ortho2d(32.0, 32.0); let mut builder = r.new_scene().with_camera(projection, view); let dirt = image::open("../../img/dirt.jpg").unwrap(); @@ -938,9 +926,7 @@ mod test { let sheet_h = icon_h * 3; let w = sheet_w * 3 + 2; let h = sheet_h; - let mut r = Renderling::headless(w, h) - .unwrap() - .with_background_color(Vec4::new(1.0, 1.0, 0.0, 1.0)); + let mut r = Renderling::headless(w, h).with_background_color(Vec4::new(1.0, 1.0, 0.0, 1.0)); let (projection, view) = camera::default_ortho2d(w as f32, h as f32); let mut builder = r.new_scene().with_camera(projection, view); let dirt = image::open("../../img/dirt.jpg").unwrap(); @@ -1037,9 +1023,7 @@ mod test { let sheet_h = icon_h * 3; let w = sheet_w * 3 + 2; let h = sheet_h; - let mut r = Renderling::headless(w, h) - .unwrap() - .with_background_color(Vec4::new(1.0, 1.0, 0.0, 1.0)); + let mut r = Renderling::headless(w, h).with_background_color(Vec4::new(1.0, 1.0, 0.0, 1.0)); let (projection, view) = camera::default_ortho2d(w as f32, h as f32); let mut builder = r.new_scene().with_camera(projection, view); let dirt = image::open("../../img/dirt.jpg").unwrap(); @@ -1151,9 +1135,8 @@ mod test { #[test] /// Ensures that the directional light coloring works. fn scene_cube_directional() { - let mut r = Renderling::headless(100, 100) - .unwrap() - .with_background_color(Vec3::splat(0.0).extend(1.0)); + let mut r = + Renderling::headless(100, 100).with_background_color(Vec3::splat(0.0).extend(1.0)); let mut builder = r.new_scene(); let red = Vec3::X.extend(1.0); @@ -1254,7 +1237,7 @@ mod test { #[test] // tests that nested children are transformed by their parent's transform fn scene_parent_sanity() { - let mut r = Renderling::headless(100, 100).unwrap(); + let mut r = Renderling::headless(100, 100); r.set_background_color(Vec4::splat(0.0)); let (projection, view) = camera::default_ortho2d(100.0, 100.0); let mut builder = r.new_scene().with_camera(projection, view); @@ -1421,9 +1404,8 @@ mod test { // see https://learnopengl.com/PBR/Lighting fn pbr_metallic_roughness_spheres() { let ss = 600; - let mut r = Renderling::headless(ss, ss) - .unwrap() - .with_background_color(Vec3::splat(0.0).extend(1.0)); + let mut r = + Renderling::headless(ss, ss).with_background_color(Vec3::splat(0.0).extend(1.0)); let radius = 0.5; let mut icosphere = icosahedron::Polyhedron::new_isocahedron(radius, 5); diff --git a/crates/renderling/src/renderer.rs b/crates/renderling/src/renderer.rs index fe07437e..7f973d58 100644 --- a/crates/renderling/src/renderer.rs +++ b/crates/renderling/src/renderer.rs @@ -64,6 +64,12 @@ pub enum RenderlingError { State { source: WgpuStateError }, } +impl From for RenderlingError { + fn from(source: WgpuStateError) -> Self { + Self::State { source } + } +} + /// A thread-safe, clonable wrapper around `wgpu::Device`. #[derive(Clone)] pub struct Device(pub Arc); @@ -180,7 +186,7 @@ impl Renderling { height, None as Option, ) - .await; + .await?; let depth_texture = crate::Texture::create_depth_texture(&device, width, height); Ok(Self::new( target, @@ -210,7 +216,7 @@ impl Renderling { .map_err(|e| WgpuStateError::CreateSurface { source: e }) }) as crate::CreateSurfaceFn), ) - .await; + .await?; let depth_texture = crate::Texture::create_depth_texture(&device, width, height); Ok(Self::new( @@ -251,9 +257,13 @@ impl Renderling { Self::try_from_raw_window_handle(window, inner_size.width, inner_size.height) } - // TODO: No reason for `headless` to return Result - pub fn headless(width: u32, height: u32) -> Result { - futures_lite::future::block_on(Self::try_new_headless(width, height)) + /// Create a new headless renderer. + /// + /// ## Panics + /// This function will panic if an adapter cannot be found. For example this would + /// happen on machines without a GPU. + pub fn headless(width: u32, height: u32) -> Self { + futures_lite::future::block_on(Self::try_new_headless(width, height)).unwrap() } pub fn set_background_color(&mut self, color: impl Into) { diff --git a/crates/renderling/src/scene.rs b/crates/renderling/src/scene.rs index 0ddcb7b5..54abc872 100644 --- a/crates/renderling/src/scene.rs +++ b/crates/renderling/src/scene.rs @@ -6,7 +6,7 @@ use moongraph::{Move, View, ViewMut}; use renderling_shader::debug::DebugChannel; use snafu::prelude::*; -pub use renderling_shader::{pbr::PbrMaterial, stage::*}; +pub use renderling_shader::{pbr::PbrMaterial, stage::*, texture::*}; use crate::{ bloom::BloomResult, frame::FrameTextureView, hdr::HdrSurface, Atlas, BufferArray, DepthTexture, @@ -495,7 +495,6 @@ impl Scene { }], }); - // TODO: rename this or regroup the bindgroups let render_buffers_bindgroup = create_scene_buffers_bindgroup( &device, &constants, diff --git a/crates/renderling/src/scene/gltf_support.rs b/crates/renderling/src/scene/gltf_support.rs index 8fc69a90..8731dc8b 100644 --- a/crates/renderling/src/scene/gltf_support.rs +++ b/crates/renderling/src/scene/gltf_support.rs @@ -5,7 +5,10 @@ use rustc_hash::FxHashMap; use snafu::prelude::*; use super::*; -use crate::Id; +use crate::{ + shader::texture::{GpuTexture, TextureAddressMode}, + Id, +}; mod anime; pub use anime::*; @@ -1197,9 +1200,7 @@ mod test { // tests importing a gltf file and rendering the first image as a 2d object // ensures we are decoding images correctly fn images() { - let mut r = Renderling::headless(100, 100) - .unwrap() - .with_background_color(Vec4::splat(1.0)); + let mut r = Renderling::headless(100, 100).with_background_color(Vec4::splat(1.0)); let mut builder = r.new_scene(); let _loader = builder.gltf_load("../../gltf/cheetah_cone.glb").unwrap(); let (projection, view) = camera::default_ortho2d(100.0, 100.0); @@ -1249,9 +1250,8 @@ mod test { #[test] // Ensures we can read a minimal gltf file with a simple triangle mesh. fn minimal_mesh() { - let mut r = Renderling::headless(20, 20) - .unwrap() - .with_background_color(Vec3::splat(0.0).extend(1.0)); + let mut r = + Renderling::headless(20, 20).with_background_color(Vec3::splat(0.0).extend(1.0)); let mut builder = r.new_scene(); let _loader = builder .gltf_load("../../gltf/gltfTutorial_003_MinimalGltfFile.gltf") @@ -1277,9 +1277,8 @@ mod test { // * support primitives w/ positions and normal attributes // * support transforming nodes (T * R * S) fn simple_meshes() { - let mut r = Renderling::headless(100, 50) - .unwrap() - .with_background_color(Vec3::splat(0.0).extend(1.0)); + let mut r = + Renderling::headless(100, 50).with_background_color(Vec3::splat(0.0).extend(1.0)); let mut builder = r.new_scene(); let _loader = builder .gltf_load("../../gltf/gltfTutorial_008_SimpleMeshes.gltf") @@ -1301,9 +1300,8 @@ mod test { #[test] fn simple_texture() { let size = 100; - let mut r = Renderling::headless(size, size) - .unwrap() - .with_background_color(Vec3::splat(0.0).extend(1.0)); + let mut r = + Renderling::headless(size, size).with_background_color(Vec3::splat(0.0).extend(1.0)); let mut builder = r.new_scene(); let _loader = builder .gltf_load("../../gltf/gltfTutorial_013_SimpleTexture.gltf") @@ -1333,9 +1331,8 @@ mod test { #[test] fn normal_mapping_brick_sphere() { let size = 600; - let mut r = Renderling::headless(size, size) - .unwrap() - .with_background_color(Vec3::splat(1.0).extend(1.0)); + let mut r = + Renderling::headless(size, size).with_background_color(Vec3::splat(1.0).extend(1.0)); let mut builder = r.new_scene(); let loader = builder.gltf_load("../../gltf/red_brick_03_1k.glb").unwrap(); let (projection, view) = loader.cameras.get(0).copied().unwrap(); @@ -1358,9 +1355,8 @@ mod test { // up a scene of multiple gltf documents. fn can_load_multiple_gltfs_into_one_builder() { let size = 600; - let mut r = Renderling::headless(size, size) - .unwrap() - .with_background_color(Vec3::splat(1.0).extend(1.0)); + let mut r = + Renderling::headless(size, size).with_background_color(Vec3::splat(1.0).extend(1.0)); let mut builder = r.new_scene(); let brick_loader = builder.gltf_load("../../gltf/red_brick_03_1k.glb").unwrap(); let (projection, view) = brick_loader.cameras.get(0).copied().unwrap(); @@ -1413,9 +1409,7 @@ mod test { #[cfg(feature = "gltf")] #[test] fn simple_animation() { - let mut r = Renderling::headless(50, 50) - .unwrap() - .with_background_color(Vec4::ONE); + let mut r = Renderling::headless(50, 50).with_background_color(Vec4::ONE); let projection = camera::perspective(50.0, 50.0); let view = camera::look_at(Vec3::Z * 3.0, Vec3::ZERO, Vec3::Y); @@ -1484,9 +1478,8 @@ mod test { use crate::{Scene, TweenProperty, ViewMut}; let size = 100; - let mut r = Renderling::headless(size, size) - .unwrap() - .with_background_color(Vec3::splat(0.0).extend(1.0)); + let mut r = + Renderling::headless(size, size).with_background_color(Vec3::splat(0.0).extend(1.0)); let projection = camera::perspective(50.0, 50.0); let view = camera::look_at(Vec3::Z * 4.0, Vec3::ZERO, Vec3::Y); let mut builder = r.new_scene().with_camera(projection, view); diff --git a/crates/renderling/src/skybox.rs b/crates/renderling/src/skybox.rs index 6c752cb3..d05b3b8f 100644 --- a/crates/renderling/src/skybox.rs +++ b/crates/renderling/src/skybox.rs @@ -708,7 +708,7 @@ mod test { #[test] fn hdr_skybox_scene() { - let mut r = Renderling::headless(600, 400).unwrap(); + let mut r = Renderling::headless(600, 400); let proj = crate::camera::perspective(600.0, 400.0); let view = crate::camera::look_at(Vec3::new(0.0, 0.0, 2.0), Vec3::ZERO, Vec3::Y); let mut builder = r.new_scene().with_camera(proj, view); @@ -794,7 +794,7 @@ mod test { #[test] fn precomputed_brdf() { assert_eq!(2, std::mem::size_of::()); - let r = Renderling::headless(32, 32).unwrap(); + let r = Renderling::headless(32, 32); let (device, queue) = r.get_device_and_queue_owned(); let brdf_lut = Skybox::create_precomputed_brdf_texture(&device, &queue); assert_eq!(wgpu::TextureFormat::Rg16Float, brdf_lut.texture.format()); diff --git a/crates/renderling/src/slab.rs b/crates/renderling/src/slab.rs index 36767ed5..63c3c569 100644 --- a/crates/renderling/src/slab.rs +++ b/crates/renderling/src/slab.rs @@ -382,7 +382,7 @@ mod test { fn slab_buffer_roundtrip() { println!("write"); let _ = env_logger::builder().is_test(true).try_init(); - let r = Renderling::headless(10, 10).unwrap(); + let r = Renderling::headless(10, 10); let device = r.get_device(); let queue = r.get_queue(); let slab = SlabBuffer::new(device, 2); diff --git a/crates/renderling/src/stage.rs b/crates/renderling/src/stage.rs index 58cebef2..7817d8c3 100644 --- a/crates/renderling/src/stage.rs +++ b/crates/renderling/src/stage.rs @@ -714,9 +714,7 @@ mod test { #[test] fn stage_new() { - let mut r = Renderling::headless(100, 100) - .unwrap() - .with_background_color(glam::Vec4::splat(1.0)); + let mut r = Renderling::headless(100, 100).with_background_color(glam::Vec4::splat(1.0)); let (device, queue) = r.get_device_and_queue_owned(); let stage = Stage::new(device.clone(), queue.clone()) .with_lighting(true) diff --git a/crates/renderling/src/stage/gltf_support.rs b/crates/renderling/src/stage/gltf_support.rs index 4b2cf8df..1a37e173 100644 --- a/crates/renderling/src/stage/gltf_support.rs +++ b/crates/renderling/src/stage/gltf_support.rs @@ -4,7 +4,8 @@ use crate::{ shader::{ gltf::*, pbr::PbrMaterial, - stage::{GpuTexture, LightingModel, TextureAddressMode, TextureModes}, + stage::LightingModel, + texture::{GpuTexture, TextureAddressMode, TextureModes}, }, SceneImage, }; @@ -657,9 +658,8 @@ mod test { fn stage_normal_mapping_brick_sphere() { crate::init_logging(); let size = 600; - let mut r = Renderling::headless(size, size) - .unwrap() - .with_background_color(Vec3::splat(1.0).extend(1.0)); + let mut r = + Renderling::headless(size, size).with_background_color(Vec3::splat(1.0).extend(1.0)); let (device, queue) = r.get_device_and_queue_owned(); let stage = Stage::new(device, queue); stage.configure_graph(&mut r, true); diff --git a/crates/renderling/src/state.rs b/crates/renderling/src/state.rs index 47d895b3..38ea048e 100644 --- a/crates/renderling/src/state.rs +++ b/crates/renderling/src/state.rs @@ -195,7 +195,7 @@ pub async fn new_adapter_device_queue_and_target<'a>( create_surface: Option< impl FnOnce(&wgpu::Instance) -> Result + 'a, >, -) -> (wgpu::Adapter, wgpu::Device, wgpu::Queue, RenderTarget) { +) -> Result<(wgpu::Adapter, wgpu::Device, wgpu::Queue, RenderTarget), WgpuStateError> { // The instance is a handle to our GPU // BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU let backends = wgpu::Backends::all(); @@ -215,7 +215,7 @@ pub async fn new_adapter_device_queue_and_target<'a>( async fn adapter( instance: &wgpu::Instance, compatible_surface: Option<&wgpu::Surface>, - ) -> wgpu::Adapter { + ) -> Result { let adapter = instance .request_adapter(&wgpu::RequestAdapterOptions { power_preference: wgpu::PowerPreference::default(), @@ -223,7 +223,7 @@ pub async fn new_adapter_device_queue_and_target<'a>( force_fallback_adapter: false, }) .await - .unwrap(); + .context(CannotCreateAdaptorSnafu)?; let info = adapter.get_info(); log::trace!( "using adapter: '{}' backend:{:?} driver:'{}'", @@ -231,10 +231,12 @@ pub async fn new_adapter_device_queue_and_target<'a>( info.backend, info.driver ); - adapter + Ok(adapter) } - async fn device(adapter: &wgpu::Adapter) -> (wgpu::Device, wgpu::Queue) { + async fn device( + adapter: &wgpu::Adapter, + ) -> Result<(wgpu::Device, wgpu::Queue), wgpu::RequestDeviceError> { adapter .request_device( &wgpu::DeviceDescriptor { @@ -243,20 +245,19 @@ pub async fn new_adapter_device_queue_and_target<'a>( // this one is a funny requirement, it seems it is needed if using storage buffers in // vertex shaders, even if those shaders are read-only | wgpu::Features::VERTEX_WRITABLE_STORAGE, //| wgpu::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES - //// when debugging rust-gpu shader miscompilation it's nice to have this - //| wgpu::Features::SPIRV_SHADER_PASSTHROUGH + //// when debugging rust-gpu shader miscompilation it's nice to have this + //| wgpu::Features::SPIRV_SHADER_PASSTHROUGH limits: limits(&adapter), label: None, }, None, // Trace path ) .await - .unwrap() } if let Some(create_surface) = create_surface { - let surface = (create_surface)(&instance).unwrap(); - let adapter = adapter(&instance, Some(&surface)).await; + let surface = (create_surface)(&instance)?; + let adapter = adapter(&instance, Some(&surface)).await?; let surface_caps = surface.get_capabilities(&adapter); let fmt = if surface_caps .formats @@ -277,17 +278,19 @@ pub async fn new_adapter_device_queue_and_target<'a>( vec![fmt.add_srgb_suffix()] }; log::debug!("surface capabilities: {surface_caps:#?}"); - let mut surface_config = surface.get_default_config(&adapter, width, height).unwrap(); + let mut surface_config = surface + .get_default_config(&adapter, width, height) + .context(IncompatibleSurfaceSnafu)?; surface_config.view_formats = view_fmts; - let (device, queue) = device(&adapter).await; + let (device, queue) = device(&adapter).await.context(CannotRequestDeviceSnafu)?; surface.configure(&device, &surface_config); let target = RenderTarget::Surface { surface, surface_config, }; - (adapter, device, queue, target) + Ok((adapter, device, queue, target)) } else { - let adapter = adapter(&instance, None).await; + let adapter = adapter(&instance, None).await?; let texture_desc = wgpu::TextureDescriptor { size: wgpu::Extent3d { width, @@ -304,9 +307,9 @@ pub async fn new_adapter_device_queue_and_target<'a>( label: None, view_formats: &[], }; - let (device, queue) = device(&adapter).await; + let (device, queue) = device(&adapter).await.context(CannotRequestDeviceSnafu)?; let texture = Arc::new(device.create_texture(&texture_desc)); let target = RenderTarget::Texture { texture }; - (adapter, device, queue, target) + Ok((adapter, device, queue, target)) } } diff --git a/crates/renderling/src/texture.rs b/crates/renderling/src/texture.rs index db018d1c..4be840df 100644 --- a/crates/renderling/src/texture.rs +++ b/crates/renderling/src/texture.rs @@ -850,7 +850,7 @@ mod test { #[test] fn generate_mipmaps() { - let r = Renderling::headless(10, 10).unwrap(); + let r = Renderling::headless(10, 10); let (device, queue) = r.get_device_and_queue_owned(); let img = image::open("../../img/sandstone.png").unwrap(); let width = img.width(); diff --git a/crates/renderling/src/tutorial.rs b/crates/renderling/src/tutorial.rs index bb817691..1cbf8239 100644 --- a/crates/renderling/src/tutorial.rs +++ b/crates/renderling/src/tutorial.rs @@ -17,7 +17,7 @@ mod test { #[test] fn implicit_isosceles_triangle() { - let mut r = Renderling::headless(100, 100).unwrap(); + let mut r = Renderling::headless(100, 100); let (device, _queue) = r.get_device_and_queue_owned(); let label = Some("implicit isosceles triangle"); let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { @@ -120,7 +120,7 @@ mod test { #[test] fn slabbed_isosceles_triangle_no_instance() { - let mut r = Renderling::headless(100, 100).unwrap(); + let mut r = Renderling::headless(100, 100); let (device, queue) = r.get_device_and_queue_owned(); // Create our geometry on the slab. @@ -292,7 +292,7 @@ mod test { #[test] fn slabbed_isosceles_triangle() { - let mut r = Renderling::headless(100, 100).unwrap(); + let mut r = Renderling::headless(100, 100); let (device, queue) = r.get_device_and_queue_owned(); // Create our geometry on the slab. @@ -481,7 +481,7 @@ mod test { #[test] fn slabbed_render_unit() { - let mut r = Renderling::headless(100, 100).unwrap(); + let mut r = Renderling::headless(100, 100); let (device, queue) = r.get_device_and_queue_owned(); // Create our geometry on the slab. @@ -674,7 +674,7 @@ mod test { #[test] fn slabbed_render_unit_camera() { - let mut r = Renderling::headless(100, 100).unwrap(); + let mut r = Renderling::headless(100, 100); let (device, queue) = r.get_device_and_queue_owned(); // Create our geometry on the slab. diff --git a/crates/renderling/src/ui.rs b/crates/renderling/src/ui.rs index 507d0f51..f1d94df8 100644 --- a/crates/renderling/src/ui.rs +++ b/crates/renderling/src/ui.rs @@ -593,7 +593,7 @@ mod test { #[test] fn ui_tri() { - let mut r = Renderling::headless(50, 50).unwrap(); + let mut r = Renderling::headless(50, 50); let builder = r.new_ui_scene().with_canvas_size(50, 50); let tri = builder .new_object() @@ -619,9 +619,7 @@ mod test { #[test] fn ui_image() { - let mut r = Renderling::headless(100, 100) - .unwrap() - .with_background_color(Vec4::splat(0.0)); + let mut r = Renderling::headless(100, 100).with_background_color(Vec4::splat(0.0)); let builder = r.new_ui_scene().with_canvas_size(100, 100); let img = image::open("../../img/dirt.jpg").unwrap(); let texture = builder.new_texture_from_dynamic_image(img); @@ -658,9 +656,7 @@ mod test { #[test] fn ui_text() { use crate::{FontArc, GlyphCache, Section, Text}; - let mut r = Renderling::headless(100, 50) - .unwrap() - .with_background_color(Vec4::splat(0.0)); + let mut r = Renderling::headless(100, 50).with_background_color(Vec4::splat(0.0)); let bytes: Vec = std::fs::read("../../fonts/Font Awesome 6 Free-Regular-400.otf").unwrap();