From c28373014899238c2ac564670b982b57ca03cbff Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Wed, 27 Sep 2023 17:10:40 +0200 Subject: [PATCH 1/4] Log available adapters --- crates/fj-viewer/src/graphics/renderer.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/fj-viewer/src/graphics/renderer.rs b/crates/fj-viewer/src/graphics/renderer.rs index 9a65512df..6558a12a7 100644 --- a/crates/fj-viewer/src/graphics/renderer.rs +++ b/crates/fj-viewer/src/graphics/renderer.rs @@ -47,6 +47,10 @@ impl Renderer { // This is sound, as `window` is an object to create a surface upon. let surface = unsafe { instance.create_surface(screen.window()) }?; + for adapter in instance.enumerate_adapters(wgpu::Backends::all()) { + debug!("Available adapter: {:?}", adapter.get_info()); + } + let adapter = instance .request_adapter(&wgpu::RequestAdapterOptions { power_preference: wgpu::PowerPreference::None, From e7079ebb3062b665b1913c4d7e18cd316a003799 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Wed, 27 Sep 2023 17:24:26 +0200 Subject: [PATCH 2/4] Add `Device` --- crates/fj-viewer/src/graphics/device.rs | 5 +++ crates/fj-viewer/src/graphics/mod.rs | 1 + crates/fj-viewer/src/graphics/renderer.rs | 39 ++++++++++++----------- 3 files changed, 27 insertions(+), 18 deletions(-) create mode 100644 crates/fj-viewer/src/graphics/device.rs diff --git a/crates/fj-viewer/src/graphics/device.rs b/crates/fj-viewer/src/graphics/device.rs new file mode 100644 index 000000000..0f2c6512c --- /dev/null +++ b/crates/fj-viewer/src/graphics/device.rs @@ -0,0 +1,5 @@ +#[derive(Debug)] +pub struct Device { + pub device: wgpu::Device, + pub queue: wgpu::Queue, +} diff --git a/crates/fj-viewer/src/graphics/mod.rs b/crates/fj-viewer/src/graphics/mod.rs index 33e4cb56c..abda85fb1 100644 --- a/crates/fj-viewer/src/graphics/mod.rs +++ b/crates/fj-viewer/src/graphics/mod.rs @@ -1,5 +1,6 @@ //! Rendering primitives, routines, and structures. +mod device; mod draw_config; mod drawables; mod geometries; diff --git a/crates/fj-viewer/src/graphics/renderer.rs b/crates/fj-viewer/src/graphics/renderer.rs index 6558a12a7..b65c2d424 100644 --- a/crates/fj-viewer/src/graphics/renderer.rs +++ b/crates/fj-viewer/src/graphics/renderer.rs @@ -10,18 +10,17 @@ use crate::{ }; use super::{ - draw_config::DrawConfig, drawables::Drawables, geometries::Geometries, - navigation_cube::NavigationCubeRenderer, pipelines::Pipelines, - transform::Transform, uniforms::Uniforms, vertices::Vertices, DEPTH_FORMAT, - SAMPLE_COUNT, + device::Device, draw_config::DrawConfig, drawables::Drawables, + geometries::Geometries, navigation_cube::NavigationCubeRenderer, + pipelines::Pipelines, transform::Transform, uniforms::Uniforms, + vertices::Vertices, DEPTH_FORMAT, SAMPLE_COUNT, }; /// Graphics rendering state and target abstraction #[derive(Debug)] pub struct Renderer { surface: wgpu::Surface, - device: wgpu::Device, - queue: wgpu::Queue, + device: Device, surface_config: wgpu::SurfaceConfiguration, frame_buffer: wgpu::TextureView, @@ -198,8 +197,7 @@ impl Renderer { Ok(Self { surface, - device, - queue, + device: Device { device, queue }, surface_config, frame_buffer, @@ -217,7 +215,7 @@ impl Renderer { /// Updates the geometry of the model being rendered. pub fn update_geometry(&mut self, mesh: Vertices) { - self.geometries = Geometries::new(&self.device, &mesh); + self.geometries = Geometries::new(&self.device.device, &mesh); } /// Resizes the render surface. @@ -228,12 +226,17 @@ impl Renderer { self.surface_config.width = size.width; self.surface_config.height = size.height; - self.surface.configure(&self.device, &self.surface_config); + self.surface + .configure(&self.device.device, &self.surface_config); - self.frame_buffer = - Self::create_frame_buffer(&self.device, &self.surface_config); - self.depth_view = - Self::create_depth_buffer(&self.device, &self.surface_config); + self.frame_buffer = Self::create_frame_buffer( + &self.device.device, + &self.surface_config, + ); + self.depth_view = Self::create_depth_buffer( + &self.device.device, + &self.surface_config, + ); } /// Draws the renderer, camera, and config state to the window. @@ -249,7 +252,7 @@ impl Renderer { transform_normals: Transform::for_normals(camera), }; - self.queue.write_buffer( + self.device.queue.write_buffer( &self.uniform_buffer, 0, bytemuck::cast_slice(&[uniforms]), @@ -273,7 +276,7 @@ impl Renderer { .texture .create_view(&wgpu::TextureViewDescriptor::default()); - let mut encoder = self.device.create_command_encoder( + let mut encoder = self.device.device.create_command_encoder( &wgpu::CommandEncoderDescriptor { label: None }, ); @@ -323,13 +326,13 @@ impl Renderer { self.navigation_cube_renderer.draw( &color_view, &mut encoder, - &self.queue, + &self.device.queue, aspect_ratio, camera.rotation, ); let command_buffer = encoder.finish(); - self.queue.submit(Some(command_buffer)); + self.device.queue.submit(Some(command_buffer)); trace!("Presenting..."); surface_texture.present(); From d5cbcf3306a3ea4fb35c672194c67c657747f90a Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Wed, 27 Sep 2023 17:28:48 +0200 Subject: [PATCH 3/4] Add `Device::new` --- crates/fj-viewer/src/graphics/device.rs | 46 ++++++++++ crates/fj-viewer/src/graphics/renderer.rs | 104 +++++++++------------- 2 files changed, 87 insertions(+), 63 deletions(-) diff --git a/crates/fj-viewer/src/graphics/device.rs b/crates/fj-viewer/src/graphics/device.rs index 0f2c6512c..0062d5ea2 100644 --- a/crates/fj-viewer/src/graphics/device.rs +++ b/crates/fj-viewer/src/graphics/device.rs @@ -3,3 +3,49 @@ pub struct Device { pub device: wgpu::Device, pub queue: wgpu::Queue, } + +impl Device { + pub async fn new( + adapter: &wgpu::Adapter, + ) -> Result<(Self, wgpu::Features), wgpu::RequestDeviceError> { + let features = { + let desired_features = wgpu::Features::POLYGON_MODE_LINE; + let available_features = adapter.features(); + + // By requesting the intersection of desired and available features, + // we prevent two things: + // + // 1. That requesting the device panics, which would happen if we + // requested unavailable features. + // 2. That a developer ends up accidentally using features that + // happen to be available on their machine, but that aren't + // necessarily available for all the users. + desired_features.intersection(available_features) + }; + + let limits = { + // This is the lowest of the available defaults. It should guarantee + // that we can run pretty much everywhere. + let lowest_limits = wgpu::Limits::downlevel_webgl2_defaults(); + + // However, these lowest limits aren't necessarily capable of + // supporting the screen resolution of our current platform, so + // let's amend them. + let supported_limits = adapter.limits(); + lowest_limits.using_resolution(supported_limits) + }; + + let (device, queue) = adapter + .request_device( + &wgpu::DeviceDescriptor { + label: None, + features, + limits, + }, + None, + ) + .await?; + + Ok((Device { device, queue }, features)) + } +} diff --git a/crates/fj-viewer/src/graphics/renderer.rs b/crates/fj-viewer/src/graphics/renderer.rs index b65c2d424..8e7009404 100644 --- a/crates/fj-viewer/src/graphics/renderer.rs +++ b/crates/fj-viewer/src/graphics/renderer.rs @@ -61,43 +61,7 @@ impl Renderer { debug!("Using adapter: {:?}", adapter.get_info()); - let features = { - let desired_features = wgpu::Features::POLYGON_MODE_LINE; - let available_features = adapter.features(); - - // By requesting the intersection of desired and available features, - // we prevent two things: - // - // 1. That requesting the device panics, which would happen if we - // requested unavailable features. - // 2. That a developer ends up accidentally using features that - // happen to be available on their machine, but that aren't - // necessarily available for all the users. - desired_features.intersection(available_features) - }; - - let limits = { - // This is the lowest of the available defaults. It should guarantee - // that we can run pretty much everywhere. - let lowest_limits = wgpu::Limits::downlevel_webgl2_defaults(); - - // However, these lowest limits aren't necessarily capable of - // supporting the screen resolution of our current platform, so - // let's amend them. - let supported_limits = adapter.limits(); - lowest_limits.using_resolution(supported_limits) - }; - - let (device, queue) = adapter - .request_device( - &wgpu::DeviceDescriptor { - label: None, - features, - limits, - }, - None, - ) - .await?; + let (device, features) = Device::new(&adapter).await?; let color_format = 'color_format: { let capabilities = surface.get_capabilities(&adapter); @@ -145,20 +109,23 @@ impl Renderer { alpha_mode: wgpu::CompositeAlphaMode::Auto, view_formats: vec![], }; - surface.configure(&device, &surface_config); + surface.configure(&device.device, &surface_config); - let frame_buffer = Self::create_frame_buffer(&device, &surface_config); - let depth_view = Self::create_depth_buffer(&device, &surface_config); + let frame_buffer = + Self::create_frame_buffer(&device.device, &surface_config); + let depth_view = + Self::create_depth_buffer(&device.device, &surface_config); - let uniform_buffer = - device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + let uniform_buffer = device.device.create_buffer_init( + &wgpu::util::BufferInitDescriptor { label: None, contents: bytemuck::cast_slice(&[Uniforms::default()]), usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, - }); - let bind_group_layout = - device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { + }, + ); + let bind_group_layout = device.device.create_bind_group_layout( + &wgpu::BindGroupLayoutDescriptor { entries: &[wgpu::BindGroupLayoutEntry { binding: 0, visibility: wgpu::ShaderStages::all(), @@ -174,30 +141,41 @@ impl Renderer { count: None, }], label: None, + }, + ); + let bind_group = + device.device.create_bind_group(&wgpu::BindGroupDescriptor { + layout: &bind_group_layout, + entries: &[wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::Buffer( + wgpu::BufferBinding { + buffer: &uniform_buffer, + offset: 0, + size: None, + }, + ), + }], + label: None, }); - let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { - layout: &bind_group_layout, - entries: &[wgpu::BindGroupEntry { - binding: 0, - resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding { - buffer: &uniform_buffer, - offset: 0, - size: None, - }), - }], - label: None, - }); - let geometries = Geometries::new(&device, &Vertices::empty()); - let pipelines = - Pipelines::new(&device, &bind_group_layout, color_format, features); + let geometries = Geometries::new(&device.device, &Vertices::empty()); + let pipelines = Pipelines::new( + &device.device, + &bind_group_layout, + color_format, + features, + ); - let navigation_cube_renderer = - NavigationCubeRenderer::new(&device, &queue, &surface_config); + let navigation_cube_renderer = NavigationCubeRenderer::new( + &device.device, + &device.queue, + &surface_config, + ); Ok(Self { surface, - device: Device { device, queue }, + device, surface_config, frame_buffer, From 6ec7815839d6517a5447b07777b2c292c57bf57a Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Wed, 27 Sep 2023 17:29:33 +0200 Subject: [PATCH 4/4] Fix redundancy in error messages --- crates/fj-viewer/src/graphics/renderer.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/fj-viewer/src/graphics/renderer.rs b/crates/fj-viewer/src/graphics/renderer.rs index 8e7009404..469c26f2c 100644 --- a/crates/fj-viewer/src/graphics/renderer.rs +++ b/crates/fj-viewer/src/graphics/renderer.rs @@ -367,11 +367,11 @@ impl Renderer { #[derive(Error, Debug)] pub enum RendererInitError { /// General IO error - #[error("I/O error: {0}")] + #[error("I/O error")] Io(#[from] io::Error), /// Surface creating error - #[error("Error creating surface: {0}")] + #[error("Error creating surface")] CreateSurface(#[from] wgpu::CreateSurfaceError), /// Graphics accelerator acquisition error @@ -381,7 +381,7 @@ pub enum RendererInitError { /// Device request errors /// /// See: [wgpu::RequestDeviceError](https://docs.rs/wgpu/latest/wgpu/struct.RequestDeviceError.html) - #[error("Error requesting device: {0}")] + #[error("Error requesting device")] RequestDevice(#[from] wgpu::RequestDeviceError), }