diff --git a/src/app.rs b/src/app.rs index 7fa4bfc..33f40bc 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,6 +1,7 @@ use crate::create_instance; use crate::VALIDATION_ENABLED; use ::anyhow::{anyhow, Result}; +use ::log::*; use ::thiserror::Error; use ::vulkanalia::loader::{LibloadingLoader, LIBRARY}; use ::vulkanalia::prelude::v1_0::*; @@ -51,6 +52,7 @@ impl App { #[derive(Clone, Debug, Default)] pub struct AppData { messenger: vk::DebugUtilsMessengerEXT, + physical_device: vk::PhysicalDevice, } #[derive(Debug, Error)] @@ -58,5 +60,58 @@ pub struct AppData { pub struct SuitabilityError(pub &'static str); unsafe fn pick_physical_device(instance: &Instance, data: &mut AppData) -> Result<()> { + for physical_device in instance.enumerate_physical_devices()? { + let properties = instance.get_physical_device_properties(physical_device); + + if let Err(error) = check_physical_device(instance, data, physical_device) { + warn!( + "Skipping physical device (`{}`): {}", + properties.device_name, error + ); + } else { + info!("Selected physical device (`{}`).", properties.device_name); + data.physical_device = physical_device; + return Ok(()); + } + } + + Err(anyhow!("Failed to find suitable physical device.")) +} + +unsafe fn check_physical_device( + instance: &Instance, + data: &AppData, + physical_device: vk::PhysicalDevice, +) -> Result<()> { + QueueFamilyIndicies::get(instance, data, physical_device)?; + Ok(()) } + +#[derive(Copy, Clone, Debug)] +struct QueueFamilyIndicies { + graphics: u32, +} + +impl QueueFamilyIndicies { + unsafe fn get( + instance: &Instance, + data: &AppData, + physical_device: vk::PhysicalDevice, + ) -> Result { + let properties = instance.get_physical_device_queue_family_properties(physical_device); + + let graphics = properties + .iter() + .position(|p| p.queue_flags.contains(vk::QueueFlags::GRAPHICS)) + .map(|i| i as u32); + + if let Some(graphics) = graphics { + Ok(Self { graphics }) + } else { + Err(anyhow!(SuitabilityError( + "Missing required queue families." + ))) + } + } +}