mirror of
https://github.com/hannobraun/Fornjot
synced 2025-11-11 17:40:18 +00:00
Merge pull request #2035 from hannobraun/render
Add debug logging, improve error messages, shuffle some render stuff around
This commit is contained in:
commit
336c4d0a81
51
crates/fj-viewer/src/graphics/device.rs
Normal file
51
crates/fj-viewer/src/graphics/device.rs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#[derive(Debug)]
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
//! Rendering primitives, routines, and structures.
|
//! Rendering primitives, routines, and structures.
|
||||||
|
|
||||||
|
mod device;
|
||||||
mod draw_config;
|
mod draw_config;
|
||||||
mod drawables;
|
mod drawables;
|
||||||
mod geometries;
|
mod geometries;
|
||||||
|
|||||||
@ -10,18 +10,17 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
draw_config::DrawConfig, drawables::Drawables, geometries::Geometries,
|
device::Device, draw_config::DrawConfig, drawables::Drawables,
|
||||||
navigation_cube::NavigationCubeRenderer, pipelines::Pipelines,
|
geometries::Geometries, navigation_cube::NavigationCubeRenderer,
|
||||||
transform::Transform, uniforms::Uniforms, vertices::Vertices, DEPTH_FORMAT,
|
pipelines::Pipelines, transform::Transform, uniforms::Uniforms,
|
||||||
SAMPLE_COUNT,
|
vertices::Vertices, DEPTH_FORMAT, SAMPLE_COUNT,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Graphics rendering state and target abstraction
|
/// Graphics rendering state and target abstraction
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Renderer {
|
pub struct Renderer {
|
||||||
surface: wgpu::Surface,
|
surface: wgpu::Surface,
|
||||||
device: wgpu::Device,
|
device: Device,
|
||||||
queue: wgpu::Queue,
|
|
||||||
|
|
||||||
surface_config: wgpu::SurfaceConfiguration,
|
surface_config: wgpu::SurfaceConfiguration,
|
||||||
frame_buffer: wgpu::TextureView,
|
frame_buffer: wgpu::TextureView,
|
||||||
@ -47,6 +46,10 @@ impl Renderer {
|
|||||||
// This is sound, as `window` is an object to create a surface upon.
|
// This is sound, as `window` is an object to create a surface upon.
|
||||||
let surface = unsafe { instance.create_surface(screen.window()) }?;
|
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
|
let adapter = instance
|
||||||
.request_adapter(&wgpu::RequestAdapterOptions {
|
.request_adapter(&wgpu::RequestAdapterOptions {
|
||||||
power_preference: wgpu::PowerPreference::None,
|
power_preference: wgpu::PowerPreference::None,
|
||||||
@ -58,43 +61,7 @@ impl Renderer {
|
|||||||
|
|
||||||
debug!("Using adapter: {:?}", adapter.get_info());
|
debug!("Using adapter: {:?}", adapter.get_info());
|
||||||
|
|
||||||
let features = {
|
let (device, features) = Device::new(&adapter).await?;
|
||||||
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 color_format = 'color_format: {
|
let color_format = 'color_format: {
|
||||||
let capabilities = surface.get_capabilities(&adapter);
|
let capabilities = surface.get_capabilities(&adapter);
|
||||||
@ -142,20 +109,23 @@ impl Renderer {
|
|||||||
alpha_mode: wgpu::CompositeAlphaMode::Auto,
|
alpha_mode: wgpu::CompositeAlphaMode::Auto,
|
||||||
view_formats: vec![],
|
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 frame_buffer =
|
||||||
let depth_view = Self::create_depth_buffer(&device, &surface_config);
|
Self::create_frame_buffer(&device.device, &surface_config);
|
||||||
|
let depth_view =
|
||||||
|
Self::create_depth_buffer(&device.device, &surface_config);
|
||||||
|
|
||||||
let uniform_buffer =
|
let uniform_buffer = device.device.create_buffer_init(
|
||||||
device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
&wgpu::util::BufferInitDescriptor {
|
||||||
label: None,
|
label: None,
|
||||||
contents: bytemuck::cast_slice(&[Uniforms::default()]),
|
contents: bytemuck::cast_slice(&[Uniforms::default()]),
|
||||||
usage: wgpu::BufferUsages::UNIFORM
|
usage: wgpu::BufferUsages::UNIFORM
|
||||||
| wgpu::BufferUsages::COPY_DST,
|
| 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 {
|
entries: &[wgpu::BindGroupLayoutEntry {
|
||||||
binding: 0,
|
binding: 0,
|
||||||
visibility: wgpu::ShaderStages::all(),
|
visibility: wgpu::ShaderStages::all(),
|
||||||
@ -171,31 +141,41 @@ impl Renderer {
|
|||||||
count: None,
|
count: None,
|
||||||
}],
|
}],
|
||||||
label: 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 geometries = Geometries::new(&device.device, &Vertices::empty());
|
||||||
let pipelines =
|
let pipelines = Pipelines::new(
|
||||||
Pipelines::new(&device, &bind_group_layout, color_format, features);
|
&device.device,
|
||||||
|
&bind_group_layout,
|
||||||
|
color_format,
|
||||||
|
features,
|
||||||
|
);
|
||||||
|
|
||||||
let navigation_cube_renderer =
|
let navigation_cube_renderer = NavigationCubeRenderer::new(
|
||||||
NavigationCubeRenderer::new(&device, &queue, &surface_config);
|
&device.device,
|
||||||
|
&device.queue,
|
||||||
|
&surface_config,
|
||||||
|
);
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
surface,
|
surface,
|
||||||
device,
|
device,
|
||||||
queue,
|
|
||||||
|
|
||||||
surface_config,
|
surface_config,
|
||||||
frame_buffer,
|
frame_buffer,
|
||||||
@ -213,7 +193,7 @@ impl Renderer {
|
|||||||
|
|
||||||
/// Updates the geometry of the model being rendered.
|
/// Updates the geometry of the model being rendered.
|
||||||
pub fn update_geometry(&mut self, mesh: Vertices) {
|
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.
|
/// Resizes the render surface.
|
||||||
@ -224,12 +204,17 @@ impl Renderer {
|
|||||||
self.surface_config.width = size.width;
|
self.surface_config.width = size.width;
|
||||||
self.surface_config.height = size.height;
|
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.frame_buffer = Self::create_frame_buffer(
|
||||||
Self::create_frame_buffer(&self.device, &self.surface_config);
|
&self.device.device,
|
||||||
self.depth_view =
|
&self.surface_config,
|
||||||
Self::create_depth_buffer(&self.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.
|
/// Draws the renderer, camera, and config state to the window.
|
||||||
@ -245,7 +230,7 @@ impl Renderer {
|
|||||||
transform_normals: Transform::for_normals(camera),
|
transform_normals: Transform::for_normals(camera),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.queue.write_buffer(
|
self.device.queue.write_buffer(
|
||||||
&self.uniform_buffer,
|
&self.uniform_buffer,
|
||||||
0,
|
0,
|
||||||
bytemuck::cast_slice(&[uniforms]),
|
bytemuck::cast_slice(&[uniforms]),
|
||||||
@ -269,7 +254,7 @@ impl Renderer {
|
|||||||
.texture
|
.texture
|
||||||
.create_view(&wgpu::TextureViewDescriptor::default());
|
.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 },
|
&wgpu::CommandEncoderDescriptor { label: None },
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -319,13 +304,13 @@ impl Renderer {
|
|||||||
self.navigation_cube_renderer.draw(
|
self.navigation_cube_renderer.draw(
|
||||||
&color_view,
|
&color_view,
|
||||||
&mut encoder,
|
&mut encoder,
|
||||||
&self.queue,
|
&self.device.queue,
|
||||||
aspect_ratio,
|
aspect_ratio,
|
||||||
camera.rotation,
|
camera.rotation,
|
||||||
);
|
);
|
||||||
|
|
||||||
let command_buffer = encoder.finish();
|
let command_buffer = encoder.finish();
|
||||||
self.queue.submit(Some(command_buffer));
|
self.device.queue.submit(Some(command_buffer));
|
||||||
|
|
||||||
trace!("Presenting...");
|
trace!("Presenting...");
|
||||||
surface_texture.present();
|
surface_texture.present();
|
||||||
@ -382,11 +367,11 @@ impl Renderer {
|
|||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum RendererInitError {
|
pub enum RendererInitError {
|
||||||
/// General IO error
|
/// General IO error
|
||||||
#[error("I/O error: {0}")]
|
#[error("I/O error")]
|
||||||
Io(#[from] io::Error),
|
Io(#[from] io::Error),
|
||||||
|
|
||||||
/// Surface creating error
|
/// Surface creating error
|
||||||
#[error("Error creating surface: {0}")]
|
#[error("Error creating surface")]
|
||||||
CreateSurface(#[from] wgpu::CreateSurfaceError),
|
CreateSurface(#[from] wgpu::CreateSurfaceError),
|
||||||
|
|
||||||
/// Graphics accelerator acquisition error
|
/// Graphics accelerator acquisition error
|
||||||
@ -396,7 +381,7 @@ pub enum RendererInitError {
|
|||||||
/// Device request errors
|
/// Device request errors
|
||||||
///
|
///
|
||||||
/// See: [wgpu::RequestDeviceError](https://docs.rs/wgpu/latest/wgpu/struct.RequestDeviceError.html)
|
/// 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),
|
RequestDevice(#[from] wgpu::RequestDeviceError),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user