Make things return errors where relevant

This commit is contained in:
Jarrod Doyle 2024-03-23 10:14:18 +00:00
parent 704f3519ef
commit 5d463daa1e
Signed by: Jayrude
GPG Key ID: 38B57B16E7C0ADF7
7 changed files with 56 additions and 40 deletions

View File

@ -1,4 +1,6 @@
use std::{sync::Arc, time::Instant}; use std::{sync::Arc, time::Instant};
use anyhow::Result;
use winit::{ use winit::{
dpi::PhysicalSize, dpi::PhysicalSize,
event::{Event, WindowEvent}, event::{Event, WindowEvent},
@ -18,16 +20,15 @@ pub struct App<'window> {
} }
impl<'window> App<'window> { impl<'window> App<'window> {
pub async fn new(width: u32, height: u32, title: &str) -> Self { pub async fn new(width: u32, height: u32, title: &str) -> Result<Self> {
log::info!("Initialising window..."); log::info!("Initialising window...");
let size = PhysicalSize::new(width, height); let size = PhysicalSize::new(width, height);
let event_loop = EventLoop::new().unwrap(); let event_loop = EventLoop::new()?;
let window = Arc::new( let window = Arc::new(
winit::window::WindowBuilder::new() winit::window::WindowBuilder::new()
.with_title(title) .with_title(title)
.with_inner_size(size) .with_inner_size(size)
.build(&event_loop) .build(&event_loop)?,
.unwrap(),
); );
let render_ctx = gfx::Context::new( let render_ctx = gfx::Context::new(
@ -38,16 +39,16 @@ impl<'window> App<'window> {
..Default::default() ..Default::default()
}, },
) )
.await; .await?;
Self { Ok(Self {
title: title.to_owned(), title: title.to_owned(),
event_loop, event_loop,
render_ctx, render_ctx,
} })
} }
pub fn run(mut self) { pub fn run(mut self) -> Result<()> {
let mut camera_controller = camera::CameraController::new( let mut camera_controller = camera::CameraController::new(
&self.render_ctx, &self.render_ctx,
camera::Camera::new( camera::Camera::new(
@ -81,7 +82,7 @@ impl<'window> App<'window> {
glam::uvec3(32, 32, 32), glam::uvec3(32, 32, 32),
); );
let mut renderer = voxel::VoxelRenderer::new(&self.render_ctx, &camera_controller); let mut renderer = voxel::VoxelRenderer::new(&self.render_ctx, &camera_controller)?;
let mut cumulative_dt = 0.0; let mut cumulative_dt = 0.0;
let mut frames_accumulated = 0.0; let mut frames_accumulated = 0.0;
@ -169,5 +170,7 @@ impl<'window> App<'window> {
// } // }
// } // }
}); });
Ok(())
} }
} }

View File

@ -1,5 +1,7 @@
use std::num::NonZeroU32; use std::num::NonZeroU32;
use anyhow::{Context as _, Result};
use super::Context; use super::Context;
#[derive(Debug, Default)] #[derive(Debug, Default)]
@ -123,13 +125,13 @@ impl<'a> BindGroupBuilder<'a> {
} }
#[inline] #[inline]
pub fn build(self, context: &Context) -> wgpu::BindGroup { pub fn build(self, context: &Context) -> Result<wgpu::BindGroup> {
context Ok(context
.device .device
.create_bind_group(&wgpu::BindGroupDescriptor { .create_bind_group(&wgpu::BindGroupDescriptor {
label: self.label, label: self.label,
layout: self.layout.unwrap(), layout: self.layout.context("BindGroupBuilder has no layout.")?,
entries: self.entries.as_slice(), entries: self.entries.as_slice(),
}) }))
} }
} }

View File

@ -1,5 +1,6 @@
use std::sync::Arc; use std::sync::Arc;
use anyhow::{Context as _, Result};
use winit::{ use winit::{
dpi::PhysicalSize, event::WindowEvent, event_loop::EventLoopWindowTarget, window::Window, dpi::PhysicalSize, event::WindowEvent, event_loop::EventLoopWindowTarget, window::Window,
}; };
@ -16,7 +17,7 @@ pub struct Context<'window> {
} }
impl<'window> Context<'window> { impl<'window> Context<'window> {
pub async fn new(window: Arc<Window>, limits: wgpu::Limits) -> Self { pub async fn new(window: Arc<Window>, limits: wgpu::Limits) -> Result<Self> {
log::info!("Initialising WGPU context..."); log::info!("Initialising WGPU context...");
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
backends: wgpu::Backends::VULKAN, backends: wgpu::Backends::VULKAN,
@ -29,7 +30,7 @@ impl<'window> Context<'window> {
// - A GPU device to draw to the surface // - A GPU device to draw to the surface
// - A draw command queue // - A draw command queue
log::info!("Initialising window surface..."); log::info!("Initialising window surface...");
let surface = instance.create_surface(window.clone()).unwrap(); let surface = instance.create_surface(window.clone())?;
log::info!("Requesting GPU adapter..."); log::info!("Requesting GPU adapter...");
let adapter = instance let adapter = instance
@ -39,7 +40,7 @@ impl<'window> Context<'window> {
compatible_surface: Some(&surface), compatible_surface: Some(&surface),
}) })
.await .await
.unwrap(); .context("Failed to find suitable GPU adapter")?;
log::info!("Checking GPU adapter meets requirements"); log::info!("Checking GPU adapter meets requirements");
log::info!("Requesting GPU device..."); log::info!("Requesting GPU device...");
@ -52,17 +53,16 @@ impl<'window> Context<'window> {
}, },
None, None,
) )
.await .await?;
.unwrap();
log::info!("Configuring window surface..."); log::info!("Configuring window surface...");
let size = window.inner_size(); let size = window.inner_size();
let surface_config = surface let surface_config = surface
.get_default_config(&adapter, size.width, size.height) .get_default_config(&adapter, size.width, size.height)
.unwrap(); .context("Surface configuration unsupported by adapter")?;
surface.configure(&device, &surface_config); surface.configure(&device, &surface_config);
Self { Ok(Self {
window, window,
instance, instance,
size, size,
@ -71,7 +71,7 @@ impl<'window> Context<'window> {
adapter, adapter,
device, device,
queue, queue,
} })
} }
pub fn resize_surface(&mut self, new_size: PhysicalSize<u32>) { pub fn resize_surface(&mut self, new_size: PhysicalSize<u32>) {

View File

@ -1,6 +1,8 @@
use std::time::Duration; use std::time::Duration;
use anyhow::Result;
pub trait Renderer { pub trait Renderer {
fn update(&mut self, dt: &Duration, context: &super::Context); fn update(&mut self, dt: &Duration, context: &super::Context) -> Result<()>;
fn render(&self, context: &super::Context); fn render(&self, context: &super::Context) -> Result<()>;
} }

View File

@ -1,7 +1,8 @@
// TODO: Support mip-mapping and multi-sampling use anyhow::Result;
use super::{BindGroupBuilder, BindGroupLayoutBuilder, Context}; use super::{BindGroupBuilder, BindGroupLayoutBuilder, Context};
// TODO: Support mip-mapping and multi-sampling
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct TextureAttributes { pub struct TextureAttributes {
pub size: wgpu::Extent3d, pub size: wgpu::Extent3d,
@ -98,7 +99,7 @@ impl TextureBuilder {
} }
#[inline] #[inline]
pub fn build(self, context: &Context) -> Texture { pub fn build(self, context: &Context) -> Result<Texture> {
Texture::new(context, self.attributes) Texture::new(context, self.attributes)
} }
} }
@ -114,7 +115,7 @@ pub struct Texture {
} }
impl Texture { impl Texture {
pub fn new(context: &Context, attributes: TextureAttributes) -> Self { pub fn new(context: &Context, attributes: TextureAttributes) -> Result<Self> {
let texture = context.device.create_texture(&wgpu::TextureDescriptor { let texture = context.device.create_texture(&wgpu::TextureDescriptor {
label: None, label: None,
size: attributes.size, size: attributes.size,
@ -163,16 +164,16 @@ impl Texture {
.with_layout(&bind_group_layout) .with_layout(&bind_group_layout)
.with_entry(wgpu::BindingResource::TextureView(&view)) .with_entry(wgpu::BindingResource::TextureView(&view))
.with_entry(wgpu::BindingResource::Sampler(&sampler)) .with_entry(wgpu::BindingResource::Sampler(&sampler))
.build(context); .build(context)?;
Self { Ok(Self {
attributes, attributes,
texture, texture,
view, view,
sampler, sampler,
bind_group_layout, bind_group_layout,
bind_group, bind_group,
} })
} }
pub fn update(&self, context: &Context, data: &[u8]) { pub fn update(&self, context: &Context, data: &[u8]) {

View File

@ -3,7 +3,10 @@ mod gfx;
mod math; mod math;
mod voxel; mod voxel;
fn main() { use anyhow::Result;
fn main() -> Result<()> {
env_logger::init(); env_logger::init();
pollster::block_on(core::App::new(1280, 720, "Epic")).run(); pollster::block_on(core::App::new(1280, 720, "Epic"))?.run()?;
Ok(())
} }

View File

@ -1,5 +1,7 @@
use std::time::Duration; use std::time::Duration;
use anyhow::Result;
use crate::{core, gfx}; use crate::{core, gfx};
#[derive(Debug)] #[derive(Debug)]
@ -15,7 +17,7 @@ pub struct VoxelRenderer {
} }
impl VoxelRenderer { impl VoxelRenderer {
pub fn new(context: &gfx::Context, camera_controller: &core::CameraController) -> Self { pub fn new(context: &gfx::Context, camera_controller: &core::CameraController) -> Result<Self> {
log::info!("Creating render shader..."); log::info!("Creating render shader...");
let shader_descriptor = wgpu::include_wgsl!("../../assets/shaders/shader.wgsl"); let shader_descriptor = wgpu::include_wgsl!("../../assets/shaders/shader.wgsl");
let shader = context.device.create_shader_module(shader_descriptor); let shader = context.device.create_shader_module(shader_descriptor);
@ -30,7 +32,7 @@ impl VoxelRenderer {
| wgpu::TextureUsages::STORAGE_BINDING, | wgpu::TextureUsages::STORAGE_BINDING,
) )
.with_shader_visibility(wgpu::ShaderStages::FRAGMENT | wgpu::ShaderStages::COMPUTE) .with_shader_visibility(wgpu::ShaderStages::FRAGMENT | wgpu::ShaderStages::COMPUTE)
.build(context); .build(context)?;
log::info!("Creating render pipeline..."); log::info!("Creating render pipeline...");
let render_pipeline = let render_pipeline =
@ -100,7 +102,7 @@ impl VoxelRenderer {
.get_brickgrid_unpack_buffer() .get_brickgrid_unpack_buffer()
.as_entire_binding(), .as_entire_binding(),
) )
.build(context); .build(context)?;
let unpack_pipeline = let unpack_pipeline =
context context
.device .device
@ -147,7 +149,7 @@ impl VoxelRenderer {
.with_entry(brickmap_manager.get_shading_buffer().as_entire_binding()) .with_entry(brickmap_manager.get_shading_buffer().as_entire_binding())
.with_entry(brickmap_manager.get_feedback_buffer().as_entire_binding()) .with_entry(brickmap_manager.get_feedback_buffer().as_entire_binding())
.with_entry(camera_controller.get_buffer().as_entire_binding()) .with_entry(camera_controller.get_buffer().as_entire_binding())
.build(context); .build(context)?;
let raycast_pipeline = let raycast_pipeline =
context context
.device .device
@ -164,7 +166,7 @@ impl VoxelRenderer {
entry_point: "compute", entry_point: "compute",
}); });
Self { Ok(Self {
clear_color: wgpu::Color::BLACK, clear_color: wgpu::Color::BLACK,
render_texture, render_texture,
render_pipeline, render_pipeline,
@ -173,13 +175,13 @@ impl VoxelRenderer {
raycast_bind_group, raycast_bind_group,
unpack_pipeline, unpack_pipeline,
unpack_bind_group, unpack_bind_group,
} })
} }
} }
impl gfx::Renderer for VoxelRenderer { impl gfx::Renderer for VoxelRenderer {
fn render(&self, context: &gfx::Context) { fn render(&self, context: &gfx::Context) -> Result<()> {
let frame = context.surface.get_current_texture().unwrap(); let frame = context.surface.get_current_texture()?;
let view = frame let view = frame
.texture .texture
.create_view(&wgpu::TextureViewDescriptor::default()); .create_view(&wgpu::TextureViewDescriptor::default());
@ -231,9 +233,12 @@ impl gfx::Renderer for VoxelRenderer {
context.queue.submit(Some(encoder.finish())); context.queue.submit(Some(encoder.finish()));
frame.present(); frame.present();
Ok(())
} }
fn update(&mut self, _dt: &Duration, _context: &gfx::Context) {} fn update(&mut self, _dt: &Duration, _context: &gfx::Context) -> Result<()> {
Ok(())
}
} }
impl VoxelRenderer { impl VoxelRenderer {