From caeb083a3d234c98a6354c989481e9de888f1a4b Mon Sep 17 00:00:00 2001 From: Robert Date: Wed, 8 Feb 2023 00:44:14 +0100 Subject: [PATCH] add error handling --- Cargo.toml | 2 +- src/application.rs | 32 ++++++++++++++--------------- src/error.rs | 50 ++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 1 + src/window.rs | 11 +++++----- 5 files changed, 73 insertions(+), 23 deletions(-) create mode 100644 src/error.rs diff --git a/Cargo.toml b/Cargo.toml index c9fb517..24c0c4e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,4 +10,4 @@ vulkano = "0.31.0" glfw = { version = "0.50.0", features = ["vulkan"] } [profile.dev] -opt-level = 1 +# opt-level = 1 diff --git a/src/application.rs b/src/application.rs index 100ab7a..d17b257 100644 --- a/src/application.rs +++ b/src/application.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use crate::window::Window; +use crate::{window::Window, error::ApplicationError}; fn key_callback_func(window: &mut glfw::Window, key: glfw::Key, _: glfw::Scancode, action: glfw::Action, _: glfw::Modifiers) { if key == glfw::Key::Escape && action == glfw::Action::Press { @@ -16,10 +16,10 @@ pub struct Application { } impl Application { - pub fn new() -> Result { + pub fn new() -> Result { let mut glfw = match glfw::init(glfw::FAIL_ON_ERRORS) { Ok(instance) => instance, - Err(_) => return Err("Failed to initialize GLFW") + Err(_) => return Err(ApplicationError::new("GLFW", "Failed to initialize GLFW")) }; let mut window = Window::new(&mut glfw, 800, 800, "Vulkan Test")?; @@ -35,29 +35,27 @@ impl Application { }) } - fn init_vulkan(glfw: &glfw::Glfw) -> Result, &'static str> { + fn init_vulkan(glfw: &glfw::Glfw) -> Result, ApplicationError> { let mut create_info = vulkano::instance::InstanceCreateInfo::application_from_cargo_toml(); create_info.engine_name = Some("No engine".into()); create_info.engine_version = vulkano::Version::V1_0; create_info.max_api_version = Some(vulkano::Version::V1_0); - if let Some(extensions) = glfw.get_required_instance_extensions() { - create_info.enabled_extensions = vulkano::instance::InstanceExtensions::from_iter(extensions.iter().map(|name| name.as_str())); - } else { - return Err("Failed to fetch GLFW's required instance extensions"); - } + let required_extensions = glfw.get_required_instance_extensions().ok_or( + ApplicationError::new("GLFW", "Failed to get required GLFW extensions") + )?; - if let Ok(library) = vulkano::VulkanLibrary::new() { - return match vulkano::instance::Instance::new(library, create_info) { - Ok(instance) => Ok(instance), - Err(_) => Err("Failed to create Vulkan instance") - }; - } + create_info.enabled_extensions = vulkano::instance::InstanceExtensions::from_iter( + required_extensions.iter().map(|ext| ext.as_str()) + ); - return Err("Failed to create Vulkano library"); + let library = vulkano::library::VulkanLibrary::new()?; + let instance = vulkano::instance::Instance::new(library, create_info)?; + + Ok(instance) } - pub fn run(&mut self) -> Result<(), &'static str> { + pub fn run(&mut self) -> Result<(), ApplicationError> { while !self.window.should_close() { self.glfw.poll_events(); self.window.handle_events(); diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..40b50ac --- /dev/null +++ b/src/error.rs @@ -0,0 +1,50 @@ +use std::fmt::Display; + +use vulkano::{LoadingError, instance::{self, InstanceCreationError, Instance, InstanceCreateInfo}}; + +#[derive(Debug)] +pub struct ApplicationError { + what: String, + which: String +} + +impl ApplicationError { + pub fn new(which: &str, what: &str) -> ApplicationError { + ApplicationError { what: what.into(), which: which.into() } + } +} + +impl Display for ApplicationError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + writeln!(f, "[{}] {}", self.which, self.what) + } +} + +impl From for ApplicationError { + fn from(value: LoadingError) -> Self { + ApplicationError { + which: "Loading Error".into(), + what: match value { + LoadingError::LibraryLoadFailure(error) => error.to_string(), + LoadingError::OomError(error) => error.to_string() + } + } + } +} + +impl From for ApplicationError { + fn from(value: InstanceCreationError) -> Self { + ApplicationError { + what: "Instance Creation Error".into(), + which: match value { + InstanceCreationError::ExtensionNotPresent => "Extension not present".into(), + InstanceCreationError::ExtensionRestrictionNotMet(error) => error.to_string(), + InstanceCreationError::IncompatibleDriver => "Incompatible driver".into(), + InstanceCreationError::InitializationFailed => "Initialization failed".into(), + InstanceCreationError::LayerNotPresent => "Layer not present".into(), + InstanceCreationError::OomError(error) => error.to_string(), + InstanceCreationError::RequirementNotMet { required_for, requires_one_of } => format!("{} requires one of {}", required_for, requires_one_of) + } + } + } +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index c129c1e..f1edcab 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ use application::Application; mod application; mod window; +mod error; fn main() { let mut app = Application::new().unwrap(); diff --git a/src/window.rs b/src/window.rs index 56715c9..5d1d974 100644 --- a/src/window.rs +++ b/src/window.rs @@ -1,5 +1,7 @@ use std::{sync::mpsc::Receiver, ops::Deref}; +use crate::{error::ApplicationError, application::Application}; + type KeyCallbackFunc = fn(&mut glfw::Window, glfw::Key, glfw::Scancode, glfw::Action, glfw::Modifiers); pub struct Window { @@ -10,14 +12,13 @@ pub struct Window { } impl Window { - pub fn new(glfw: &mut glfw::Glfw, width: u32, height: u32, title: &str) -> Result { + pub fn new(glfw: &mut glfw::Glfw, width: u32, height: u32, title: &str) -> Result { glfw.window_hint(glfw::WindowHint::Resizable(false)); glfw.window_hint(glfw::WindowHint::ClientApi(glfw::ClientApiHint::NoApi)); - let (mut window, events) = match glfw.create_window(width, height, title, glfw::WindowMode::Windowed) { - Some(val) => val, - None => return Err("Failed to create window and event receiver") - }; + let (mut window, events) = + glfw.create_window(width, height, title, glfw::WindowMode::Windowed) + .ok_or(ApplicationError::new("Window", "Failed to create window and event receiver"))?; window.set_key_polling(true);