From 2c5928dac4a370965576355639377b0b6d9326f4 Mon Sep 17 00:00:00 2001 From: Timothy Warren Date: Wed, 5 Apr 2023 15:41:32 -0400 Subject: [PATCH] Add window surface, fix rendering of logical device on mac --- Cargo.toml | 2 +- src/app.rs | 25 ++++++++++++++++++-- src/app/functions.rs | 54 ++++++++++++++++++++++++++++++++++++++------ 3 files changed, 71 insertions(+), 10 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e89d8cc..868eea4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,5 +14,5 @@ png = "0.17" pretty_env_logger = "0.4" thiserror = "1" tobj = { version = "3", features = ["log"] } -vulkanalia = { version = "=0.16.0", features = ["libloading", "window"] } +vulkanalia = { version = "=0.16.0", features = ["libloading", "window", "provisional"] } winit = "0.27" diff --git a/src/app.rs b/src/app.rs index 6ceabf5..3b1a544 100644 --- a/src/app.rs +++ b/src/app.rs @@ -8,6 +8,8 @@ use ::thiserror::Error; use ::vulkanalia::loader::{LibloadingLoader, LIBRARY}; use ::vulkanalia::prelude::v1_0::*; use ::vulkanalia::vk::ExtDebugUtilsExtension; +use ::vulkanalia::vk::KhrSurfaceExtension; +use ::vulkanalia::window as vk_window; use ::winit::window::Window; /// Our Vulkan app. @@ -26,6 +28,7 @@ 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)?; + data.surface = vk_window::create_surface(&instance, window)?; pick_physical_device(&instance, &mut data)?; let device = create_logical_device(&instance, &mut data)?; @@ -51,6 +54,7 @@ impl App { .destroy_debug_utils_messenger_ext(self.data.messenger, None); } + self.instance.destroy_surface_khr(self.data.surface, None); self.instance.destroy_instance(None); } } @@ -58,9 +62,13 @@ impl App { /// The Vulkan handles and associated properties used by our Vulkan app. #[derive(Clone, Debug, Default)] pub struct AppData { + surface: vk::SurfaceKHR, + // Debug messenger: vk::DebugUtilsMessengerEXT, + // Physical Device / Logical Device physical_device: vk::PhysicalDevice, graphics_queue: vk::Queue, + present_queue: vk::Queue, } #[derive(Debug, Error)] @@ -70,6 +78,7 @@ pub struct SuitabilityError(pub &'static str); #[derive(Copy, Clone, Debug)] pub(crate) struct QueueFamilyIndicies { graphics: u32, + present: u32, } impl QueueFamilyIndicies { @@ -85,8 +94,20 @@ impl QueueFamilyIndicies { .position(|p| p.queue_flags.contains(vk::QueueFlags::GRAPHICS)) .map(|i| i as u32); - if let Some(graphics) = graphics { - Ok(Self { graphics }) + let mut present = None; + for (index, properties) in properties.iter().enumerate() { + if instance.get_physical_device_surface_support_khr( + physical_device, + index as u32, + data.surface, + )? { + present = Some(index as u32); + break; + } + } + + if let (Some(graphics), Some(present)) = (graphics, present) { + Ok(Self { graphics, present }) } else { Err(anyhow!(SuitabilityError( "Missing required queue families." diff --git a/src/app/functions.rs b/src/app/functions.rs index 57ff485..f7e9bdf 100644 --- a/src/app/functions.rs +++ b/src/app/functions.rs @@ -37,6 +37,7 @@ pub(super) unsafe fn create_instance( entry: &Entry, data: &mut AppData, ) -> Result { + // Application Info let application_info = vk::ApplicationInfo::builder() .application_name(b"Vulkan Tutorial\0") .application_version(vk::make_version(1, 0, 0)) @@ -44,6 +45,7 @@ pub(super) unsafe fn create_instance( .engine_version(vk::make_version(1, 0, 0)) .api_version(vk::make_version(1, 0, 0)); + // Layers let available_layers = entry .enumerate_instance_layer_properties()? .iter() @@ -60,6 +62,7 @@ pub(super) unsafe fn create_instance( Vec::new() }; + // Extensions let mut extensions = vk_window::get_required_instance_extensions(window) .iter() .map(|e| e.as_ptr()) @@ -75,11 +78,17 @@ pub(super) unsafe fn create_instance( .any(|e| e.extension_name == vk::KHR_PORTABILITY_ENUMERATION_EXTENSION.name) { extensions.push(vk::KHR_PORTABILITY_ENUMERATION_EXTENSION.name.as_ptr()); + extensions.push( + vk::KHR_GET_PHYSICAL_DEVICE_PROPERTIES2_EXTENSION + .name + .as_ptr(), + ); vk::InstanceCreateFlags::ENUMERATE_PORTABILITY_KHR } else { vk::InstanceCreateFlags::empty() }; + // Create let mut info = vk::InstanceCreateInfo::builder() .application_info(&application_info) .enabled_layer_names(&layers) @@ -97,6 +106,11 @@ pub(super) unsafe fn create_instance( let instance = entry.create_instance(&info, None)?; + // Messenger + if VALIDATION_ENABLED { + data.messenger = instance.create_debug_utils_messenger_ext(&debug_info, None)?; + } + Ok(instance) } @@ -133,30 +147,56 @@ pub(super) unsafe fn create_logical_device( instance: &Instance, data: &mut AppData, ) -> Result { + // Queue Create Infos 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 mut unique_indices = HashSet::new(); + unique_indices.insert(indices.graphics); + unique_indices.insert(indices.present); + let queue_priorities = &[1.0]; + let queue_infos = unique_indices + .iter() + .map(|i| { + vk::DeviceQueueCreateInfo::builder() + .queue_family_index(*i) + .queue_priorities(queue_priorities) + }) + .collect::>(); + + // Layers let layers = if VALIDATION_ENABLED { vec![VALIDATION_LAYER.as_ptr()] } else { vec![] }; + // Extensions + let extension_names = if instance + .enumerate_device_extension_properties(data.physical_device, None)? + .iter() + .any(|e| e.extension_name == vk::KHR_PORTABILITY_SUBSET_EXTENSION.name) + { + vec![vk::KHR_PORTABILITY_SUBSET_EXTENSION.name.as_ptr()] + } else { + vec![] + }; + + // Features let features = vk::PhysicalDeviceFeatures::builder(); - let queue_infos = &[queue_info]; + // Create let info = vk::DeviceCreateInfo::builder() - .queue_create_infos(queue_infos) + .queue_create_infos(&queue_infos) .enabled_layer_names(&layers) - .enabled_features(&features); + .enabled_features(&features) + .enabled_extension_names(&extension_names); let device = instance.create_device(data.physical_device, &info, None)?; + // Queues data.graphics_queue = device.get_device_queue(indices.graphics, 0); + data.present_queue = device.get_device_queue(indices.present, 0); Ok(device) }