From 5e9b12a0a2e785ee1bfa9778d2e33f031dd7e56b Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Tue, 5 Mar 2024 16:27:01 +0900 Subject: [PATCH] WIP setup "window surface", "presentation queue" TODO: "swap chain" https://vulkan-tutorial.com/en/Drawing_a_triangle/Presentation/Swap_chain --- src/main.rs | 163 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 101 insertions(+), 62 deletions(-) diff --git a/src/main.rs b/src/main.rs index 202f8c1..d1b2df9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,6 +15,7 @@ mod ffi { } } +use std::collections::HashSet; use std::ffi::{CStr, CString}; const WINDOW_WIDTH: i32 = 800; @@ -123,61 +124,15 @@ fn create_debug_messenger_create_info() -> ffi::VkDebugUtilsMessengerCreateInfoE } } -fn is_device_suitable(dev: ffi::VkPhysicalDevice) -> bool { - let mut dev_props: ffi::VkPhysicalDeviceProperties = unsafe { std::mem::zeroed() }; - unsafe { - ffi::vkGetPhysicalDeviceProperties(dev, std::ptr::addr_of_mut!(dev_props)); - } - - let mut dev_feat: ffi::VkPhysicalDeviceFeatures = unsafe { std::mem::zeroed() }; - unsafe { - ffi::vkGetPhysicalDeviceFeatures(dev, std::ptr::addr_of_mut!(dev_feat)); - } - - // dev_props.deviceType == ffi::VkPhysicalDeviceType_VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU - // && dev_feat.geometryShader != 0 - - // Use previous checks for specifics, but for now, accept GPUs that support "graphics family". - find_queue_families(dev).graphics_family.is_some() -} - struct QueueFamilyIndices { graphics_family: Option, + present_family: Option, } -fn find_queue_families(dev: ffi::VkPhysicalDevice) -> QueueFamilyIndices { - let mut queue_fam = QueueFamilyIndices { - graphics_family: None, - }; - - let mut queue_family_count: u32 = 0; - unsafe { - ffi::vkGetPhysicalDeviceQueueFamilyProperties( - dev, - std::ptr::addr_of_mut!(queue_family_count), - std::ptr::null_mut(), - ); +impl QueueFamilyIndices { + fn is_complete(&self) -> bool { + self.graphics_family.is_some() && self.present_family.is_some() } - - let mut queue_family_props: Vec = - Vec::with_capacity(queue_family_count as usize); - queue_family_props.resize(queue_family_count as usize, unsafe { std::mem::zeroed() }); - unsafe { - ffi::vkGetPhysicalDeviceQueueFamilyProperties( - dev, - std::ptr::addr_of_mut!(queue_family_count), - queue_family_props.as_mut_ptr(), - ); - } - - for (idx, queue_family_prop) in queue_family_props.iter().enumerate() { - if queue_family_prop.queueFlags & ffi::VkQueueFlagBits_VK_QUEUE_GRAPHICS_BIT != 0 { - queue_fam.graphics_family = Some(idx as u32); - break; - } - } - - queue_fam } struct VulkanApp { @@ -188,6 +143,7 @@ struct VulkanApp { physical_device: ffi::VkPhysicalDevice, device: ffi::VkDevice, graphics_queue: ffi::VkQueue, + present_queue: ffi::VkQueue, } impl VulkanApp { @@ -200,6 +156,7 @@ impl VulkanApp { physical_device: std::ptr::null_mut(), device: std::ptr::null_mut(), graphics_queue: std::ptr::null_mut(), + present_queue: std::ptr::null_mut(), } } @@ -360,7 +317,7 @@ impl VulkanApp { } for phys_dev in phys_dev_handles_vec { - if is_device_suitable(phys_dev) { + if self.is_device_suitable(phys_dev) { self.physical_device = phys_dev; break; } @@ -376,25 +333,32 @@ impl VulkanApp { panic!("\"physical_device\" must be set before calling \"create_logical_device\"!"); } - let indices = find_queue_families(self.physical_device); + let indices = self.find_queue_families(self.physical_device); - let mut dev_queue_create_info: ffi::VkDeviceQueueCreateInfo = unsafe { std::mem::zeroed() }; - dev_queue_create_info.sType = - ffi::VkStructureType_VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - dev_queue_create_info.queueFamilyIndex = indices - .graphics_family - .expect("\"physical_device\" must support graphics!"); - dev_queue_create_info.queueCount = 1; + let mut dev_queue_create_infos: Vec = Vec::new(); + let mut unique_queue_families: HashSet = HashSet::new(); + unique_queue_families.insert(indices.graphics_family.unwrap()); + unique_queue_families.insert(indices.present_family.unwrap()); let queue_priority: f32 = 1.0; - dev_queue_create_info.pQueuePriorities = std::ptr::addr_of!(queue_priority); + + for queue_family in unique_queue_families { + let mut dev_queue_create_info: ffi::VkDeviceQueueCreateInfo = + unsafe { std::mem::zeroed() }; + dev_queue_create_info.sType = + ffi::VkStructureType_VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + dev_queue_create_info.queueFamilyIndex = queue_family; + dev_queue_create_info.queueCount = 1; + dev_queue_create_info.pQueuePriorities = std::ptr::addr_of!(queue_priority); + dev_queue_create_infos.push(dev_queue_create_info); + } let mut phys_dev_feat: ffi::VkPhysicalDeviceFeatures = unsafe { std::mem::zeroed() }; let mut dev_create_info: ffi::VkDeviceCreateInfo = unsafe { std::mem::zeroed() }; dev_create_info.sType = ffi::VkStructureType_VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - dev_create_info.pQueueCreateInfos = std::ptr::addr_of!(dev_queue_create_info); - dev_create_info.queueCreateInfoCount = 1; + dev_create_info.pQueueCreateInfos = dev_queue_create_infos.as_ptr(); + dev_create_info.queueCreateInfoCount = dev_queue_create_infos.len() as u32; dev_create_info.pEnabledFeatures = std::ptr::addr_of!(phys_dev_feat); dev_create_info.enabledExtensionCount = 0; @@ -424,6 +388,12 @@ impl VulkanApp { 0, std::ptr::addr_of_mut!(self.graphics_queue), ); + ffi::vkGetDeviceQueue( + self.device, + indices.present_family.unwrap(), + 0, + std::ptr::addr_of_mut!(self.present_queue), + ); } } @@ -459,6 +429,75 @@ impl VulkanApp { } } } + + fn find_queue_families(&self, dev: ffi::VkPhysicalDevice) -> QueueFamilyIndices { + let mut queue_fam = QueueFamilyIndices { + graphics_family: None, + present_family: None, + }; + + let mut queue_family_count: u32 = 0; + unsafe { + ffi::vkGetPhysicalDeviceQueueFamilyProperties( + dev, + std::ptr::addr_of_mut!(queue_family_count), + std::ptr::null_mut(), + ); + } + + let mut queue_family_props: Vec = + Vec::with_capacity(queue_family_count as usize); + queue_family_props.resize(queue_family_count as usize, unsafe { std::mem::zeroed() }); + unsafe { + ffi::vkGetPhysicalDeviceQueueFamilyProperties( + dev, + std::ptr::addr_of_mut!(queue_family_count), + queue_family_props.as_mut_ptr(), + ); + } + + for (idx, queue_family_prop) in queue_family_props.iter().enumerate() { + let mut present_support: ffi::VkBool32 = ffi::VK_FALSE; + unsafe { + ffi::vkGetPhysicalDeviceSurfaceSupportKHR( + dev, + idx as u32, + self.surface, + std::ptr::addr_of_mut!(present_support), + ); + } + if present_support != ffi::VK_FALSE { + queue_fam.present_family = Some(idx as u32); + } + if queue_family_prop.queueFlags & ffi::VkQueueFlagBits_VK_QUEUE_GRAPHICS_BIT != 0 { + queue_fam.graphics_family = Some(idx as u32); + } + + if queue_fam.is_complete() { + break; + } + } + + queue_fam + } + + fn is_device_suitable(&self, dev: ffi::VkPhysicalDevice) -> bool { + let mut dev_props: ffi::VkPhysicalDeviceProperties = unsafe { std::mem::zeroed() }; + unsafe { + ffi::vkGetPhysicalDeviceProperties(dev, std::ptr::addr_of_mut!(dev_props)); + } + + let mut dev_feat: ffi::VkPhysicalDeviceFeatures = unsafe { std::mem::zeroed() }; + unsafe { + ffi::vkGetPhysicalDeviceFeatures(dev, std::ptr::addr_of_mut!(dev_feat)); + } + + // dev_props.deviceType == ffi::VkPhysicalDeviceType_VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU + // && dev_feat.geometryShader != 0 + + // Use previous checks for specifics, but for now, accept GPUs with required support. + self.find_queue_families(dev).is_complete() + } } impl Drop for VulkanApp {