From 9713441c2e9d532f75839900f7bc20b5821d6efc Mon Sep 17 00:00:00 2001 From: Timothy Warren Date: Wed, 5 Apr 2023 13:04:20 -0400 Subject: [PATCH] Create logical device and its queues --- src/app.rs | 43 +++--------- src/app/functions.rs | 162 +++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 98 +------------------------- 3 files changed, 174 insertions(+), 129 deletions(-) create mode 100644 src/app/functions.rs diff --git a/src/app.rs b/src/app.rs index 33f40bc..6ceabf5 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,4 +1,6 @@ -use crate::create_instance; +mod functions; +use functions::{create_instance, create_logical_device, pick_physical_device}; + use crate::VALIDATION_ENABLED; use ::anyhow::{anyhow, Result}; use ::log::*; @@ -14,6 +16,7 @@ pub struct App { entry: Entry, instance: Instance, data: AppData, + device: Device, } impl App { @@ -23,12 +26,14 @@ impl App { let entry = Entry::new(loader).map_err(|b| anyhow!("{}", b))?; let mut data = AppData::default(); let instance = create_instance(window, &entry, &mut data)?; - pick_physical_device(&instance, &mut data)?; + let device = create_logical_device(&instance, &mut data)?; + Ok(Self { entry, instance, data, + device, }) } @@ -39,6 +44,8 @@ impl App { /// Destroys our Vulkan app. pub unsafe fn destroy(&mut self) { + self.device.destroy_device(None); + if VALIDATION_ENABLED { self.instance .destroy_debug_utils_messenger_ext(self.data.messenger, None); @@ -53,43 +60,15 @@ impl App { pub struct AppData { messenger: vk::DebugUtilsMessengerEXT, physical_device: vk::PhysicalDevice, + graphics_queue: vk::Queue, } #[derive(Debug, Error)] #[error("Missing {0}.")] 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 { +pub(crate) struct QueueFamilyIndicies { graphics: u32, } diff --git a/src/app/functions.rs b/src/app/functions.rs new file mode 100644 index 0000000..57ff485 --- /dev/null +++ b/src/app/functions.rs @@ -0,0 +1,162 @@ +use super::*; +use crate::{VALIDATION_ENABLED, VALIDATION_LAYER}; + +use ::anyhow::{anyhow, Result}; +use ::log::*; +use ::std::collections::HashSet; +use ::std::ffi::CStr; +use ::std::os::raw::c_void; +use ::vulkanalia::prelude::v1_0::*; +use ::vulkanalia::window as vk_window; +use ::winit::window::Window; + +extern "system" fn debug_callback( + severity: vk::DebugUtilsMessageSeverityFlagsEXT, + type_: vk::DebugUtilsMessageTypeFlagsEXT, + data: *const vk::DebugUtilsMessengerCallbackDataEXT, + _: *mut c_void, +) -> vk::Bool32 { + let data = unsafe { *data }; + let message = unsafe { CStr::from_ptr(data.message) }.to_string_lossy(); + + if severity >= vk::DebugUtilsMessageSeverityFlagsEXT::ERROR { + error!("({:?}) {}", type_, message); + } else if severity >= vk::DebugUtilsMessageSeverityFlagsEXT::WARNING { + warn!("({:?}) {}", type_, message); + } else if severity >= vk::DebugUtilsMessageSeverityFlagsEXT::INFO { + debug!("({:?}) {}", type_, message); + } else { + trace!("({:?}) {}", type_, message); + } + + vk::FALSE +} + +pub(super) unsafe fn create_instance( + window: &Window, + entry: &Entry, + data: &mut AppData, +) -> Result { + let application_info = vk::ApplicationInfo::builder() + .application_name(b"Vulkan Tutorial\0") + .application_version(vk::make_version(1, 0, 0)) + .engine_name(b"No Engine\0") + .engine_version(vk::make_version(1, 0, 0)) + .api_version(vk::make_version(1, 0, 0)); + + let available_layers = entry + .enumerate_instance_layer_properties()? + .iter() + .map(|l| l.layer_name) + .collect::>(); + + if VALIDATION_ENABLED && !available_layers.contains(&VALIDATION_LAYER) { + return Err(anyhow!("Validation layer requested but not supported.")); + } + + let layers = if VALIDATION_ENABLED { + vec![VALIDATION_LAYER.as_ptr()] + } else { + Vec::new() + }; + + let mut extensions = vk_window::get_required_instance_extensions(window) + .iter() + .map(|e| e.as_ptr()) + .collect::>(); + if VALIDATION_ENABLED { + extensions.push(vk::EXT_DEBUG_UTILS_EXTENSION.name.as_ptr()); + } + + // Compatibility extension for macOS + let flags = if entry + .enumerate_instance_extension_properties(None)? + .iter() + .any(|e| e.extension_name == vk::KHR_PORTABILITY_ENUMERATION_EXTENSION.name) + { + extensions.push(vk::KHR_PORTABILITY_ENUMERATION_EXTENSION.name.as_ptr()); + vk::InstanceCreateFlags::ENUMERATE_PORTABILITY_KHR + } else { + vk::InstanceCreateFlags::empty() + }; + + let mut info = vk::InstanceCreateInfo::builder() + .application_info(&application_info) + .enabled_layer_names(&layers) + .enabled_extension_names(&extensions) + .flags(flags); + + let mut debug_info = vk::DebugUtilsMessengerCreateInfoEXT::builder() + .message_severity(vk::DebugUtilsMessageSeverityFlagsEXT::all()) + .message_type(vk::DebugUtilsMessageTypeFlagsEXT::all()) + .user_callback(Some(debug_callback)); + + if VALIDATION_ENABLED { + info = info.push_next(&mut debug_info); + } + + let instance = entry.create_instance(&info, None)?; + + Ok(instance) +} + +pub(super) 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.")) +} + +pub(super) unsafe fn check_physical_device( + instance: &Instance, + data: &AppData, + physical_device: vk::PhysicalDevice, +) -> Result<()> { + QueueFamilyIndicies::get(instance, data, physical_device)?; + + Ok(()) +} + +pub(super) unsafe fn create_logical_device( + instance: &Instance, + data: &mut AppData, +) -> Result { + let indices = QueueFamilyIndicies::get(instance, data, data.physical_device)?; + + let queue_priorities = &[1.0]; + let queue_info = vk::DeviceQueueCreateInfo::builder() + .queue_family_index(indices.graphics) + .queue_priorities(queue_priorities); + + let layers = if VALIDATION_ENABLED { + vec![VALIDATION_LAYER.as_ptr()] + } else { + vec![] + }; + + let features = vk::PhysicalDeviceFeatures::builder(); + + let queue_infos = &[queue_info]; + let info = vk::DeviceCreateInfo::builder() + .queue_create_infos(queue_infos) + .enabled_layer_names(&layers) + .enabled_features(&features); + + let device = instance.create_device(data.physical_device, &info, None)?; + + data.graphics_queue = device.get_device_queue(indices.graphics, 0); + + Ok(device) +} diff --git a/src/lib.rs b/src/lib.rs index f74b7e9..6b9b32c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,14 +1,8 @@ mod app; pub use app::App; -use app::AppData; -use ::anyhow::{anyhow, Result}; -use ::log::*; -use ::std::collections::HashSet; -use ::std::ffi::CStr; -use ::std::os::raw::c_void; +use ::anyhow::Result; use ::vulkanalia::prelude::v1_0::*; -use ::vulkanalia::window as vk_window; use ::winit::window::Window; pub const VALIDATION_ENABLED: bool = cfg!(debug_assertions); @@ -18,93 +12,3 @@ pub const VALIDATION_LAYER: vk::ExtensionName = pub fn create_app(window: &Window) -> Result { Ok(unsafe { App::create(&window)? }) } - -extern "system" fn debug_callback( - severity: vk::DebugUtilsMessageSeverityFlagsEXT, - type_: vk::DebugUtilsMessageTypeFlagsEXT, - data: *const vk::DebugUtilsMessengerCallbackDataEXT, - _: *mut c_void, -) -> vk::Bool32 { - let data = unsafe { *data }; - let message = unsafe { CStr::from_ptr(data.message) }.to_string_lossy(); - - if severity >= vk::DebugUtilsMessageSeverityFlagsEXT::ERROR { - error!("({:?}) {}", type_, message); - } else if severity >= vk::DebugUtilsMessageSeverityFlagsEXT::WARNING { - warn!("({:?}) {}", type_, message); - } else if severity >= vk::DebugUtilsMessageSeverityFlagsEXT::INFO { - debug!("({:?}) {}", type_, message); - } else { - trace!("({:?}) {}", type_, message); - } - - vk::FALSE -} - -pub(crate) unsafe fn create_instance( - window: &Window, - entry: &Entry, - data: &mut AppData, -) -> Result { - let application_info = vk::ApplicationInfo::builder() - .application_name(b"Vulkan Tutorial\0") - .application_version(vk::make_version(1, 0, 0)) - .engine_name(b"No Engine\0") - .engine_version(vk::make_version(1, 0, 0)) - .api_version(vk::make_version(1, 0, 0)); - - let available_layers = entry - .enumerate_instance_layer_properties()? - .iter() - .map(|l| l.layer_name) - .collect::>(); - - if VALIDATION_ENABLED && !available_layers.contains(&VALIDATION_LAYER) { - return Err(anyhow!("Validation layer requested but not supported.")); - } - - let layers = if VALIDATION_ENABLED { - vec![VALIDATION_LAYER.as_ptr()] - } else { - Vec::new() - }; - - let mut extensions = vk_window::get_required_instance_extensions(window) - .iter() - .map(|e| e.as_ptr()) - .collect::>(); - if VALIDATION_ENABLED { - extensions.push(vk::EXT_DEBUG_UTILS_EXTENSION.name.as_ptr()); - } - - // Compatibility extension for macOS - let flags = if entry - .enumerate_instance_extension_properties(None)? - .iter() - .any(|e| e.extension_name == vk::KHR_PORTABILITY_ENUMERATION_EXTENSION.name) - { - extensions.push(vk::KHR_PORTABILITY_ENUMERATION_EXTENSION.name.as_ptr()); - vk::InstanceCreateFlags::ENUMERATE_PORTABILITY_KHR - } else { - vk::InstanceCreateFlags::empty() - }; - - let mut info = vk::InstanceCreateInfo::builder() - .application_info(&application_info) - .enabled_layer_names(&layers) - .enabled_extension_names(&extensions) - .flags(flags); - - let mut debug_info = vk::DebugUtilsMessengerCreateInfoEXT::builder() - .message_severity(vk::DebugUtilsMessageSeverityFlagsEXT::all()) - .message_type(vk::DebugUtilsMessageTypeFlagsEXT::all()) - .user_callback(Some(debug_callback)); - - if VALIDATION_ENABLED { - info = info.push_next(&mut debug_info); - } - - let instance = entry.create_instance(&info, None)?; - - Ok(instance) -}