use crate::prelude::*; use anyhow::Result; use std::collections::HashSet; use std::fmt; use std::mem::MaybeUninit; use std::ptr; use std::sync::Arc; use std::os::raw::c_char; use std::os::raw::c_void; use std::ffi::CStr; use std::ffi::CString; Extensions!(InstanceExtensions, { (xlib_surface, "VK_KHR_xlib_surface"), (wayland_surface, "VK_KHR_wayland_surface"), (android_surface, "VK_KHR_android_surface"), (macos_surface, "VK_KHR_macos_surface"), (win32_surface, "VK_KHR_win32_surface"), (surface, "VK_KHR_surface"), (physical_device_properties2, "VK_KHR_get_physical_device_properties2"), }); #[derive(Copy, Clone, Eq, PartialEq, Debug, Default)] pub struct VulkanDebugInfo { pub debugging: bool, pub steam_layer: bool, pub verbose: bool, pub renderdoc: bool, } pub struct Instance { _static_functions: StaticFunctions, _entry_functions: Option, pub(crate) instance_functions: InstanceFunctions, instance_wsi_functions: InstanceWSIFunctions, physical_device_properties2_functions: PhysicalDeviceProperties2Functions, debug_report_callback_functions: DebugReportCallbackFunctions, instance: VkInstance, instance_extensions: InstanceExtensions, debug_report: Option, api_version: u32, } struct Layer { props: Vec, } impl Layer { fn create(entry_functions: &EntryFunctions) -> Result { Ok(Layer { props: Instance::enumerate_layer_properties( entry_functions.vkEnumerateInstanceLayerProperties, )?, }) } fn names( &self, debugging: bool, steam_layer: bool, verbose: bool, renderdoc: bool, ) -> Result> { let mut names = Vec::new(); for i in 0..self.props.len() { let name_string = self.props[i].layer_name()?; let name = name_string.as_str(); if debugging && name == "VK_LAYER_KHRONOS_validation" { names.push(name_string.clone()); } if verbose && name == "VK_LAYER_LUNARG_api_dump" { names.push(name_string.clone()); } if renderdoc && name == "VK_LAYER_RENDERDOC_Capture" { names.push(name_string.clone()); } if steam_layer && (name == "VK_LAYER_VALVE_steam_overlay_64" || name == "VK_LAYER_VALVE_steam_overlay_32") { names.push(name_string.clone()); } } Ok(names) } } fn log(msg: impl ToString) { use std::io::Write; let home = std::env::var("HOME").unwrap(); let log_file = format!("{}/rf2_vk_hud.log", home); if let Ok(mut file) = std::fs::OpenOptions::new() .append(true) .create(true) .open(&log_file) { if let Err(_) = file.write_all(format!("{}\n", msg.to_string()).as_bytes()) {} } } impl Instance { pub fn preinitialized( instance: VkInstance, proc_addr: PFN_vkGetInstanceProcAddr, extensions: &[VkString], api_version: Option, ) -> Result> { log("Instance::preinitialized: start"); let static_functions = StaticFunctions { _lib: None, vkGetInstanceProcAddr: proc_addr, }; log("Instance::preinitialized: queried StaticFunctions"); let instance_functions = InstanceFunctions::new(&static_functions, instance); log("Instance::preinitialized: queried InstanceFunctions"); let instance_wsi_functions = InstanceWSIFunctions::new(&static_functions, instance); log("Instance::preinitialized: queried InstanceWSIFunctions"); let physical_device_properties2_functions = PhysicalDeviceProperties2Functions::new(&static_functions, instance); log("Instance::preinitialized: queried PhysicalDeviceProperties2Functions"); let debug_report_callback_functions = DebugReportCallbackFunctions::new(&static_functions, instance); log("Instance::preinitialized: queried DebugReportCallbackFunctions"); let instance_extensions = InstanceExtensions::from_list(extensions); log("Instance::preinitialized: queried InstanceExtensions"); let instance = Arc::new(Instance { _static_functions: static_functions, _entry_functions: None, instance_functions, instance_wsi_functions, physical_device_properties2_functions, debug_report_callback_functions, instance, instance_extensions, debug_report: None, api_version: api_version.unwrap_or(VK_MAKE_VERSION(1, 0, 0)), }); Ok(instance) } pub fn new( app_info: VkApplicationInfo<'_>, debug_info: VulkanDebugInfo, mut extensions: InstanceExtensions, ) -> Result> { // required in physical device extensions.physical_device_properties2 = true; let static_functions = StaticFunctions::load()?; let entry_functions = EntryFunctions::new(&static_functions); let layers = if debug_info.debugging { let layer_object = Layer::create(&entry_functions)?; layer_object.names( true, debug_info.steam_layer, debug_info.verbose, debug_info.renderdoc, )? } else if debug_info.renderdoc { let layer_object = Layer::create(&entry_functions)?; // render doc only layer_object.names(false, false, false, true)? } else { Vec::new() }; let mut checked_extensions = Vec::new(); let mut extension_list = extensions.as_list(); if debug_info.debugging || debug_info.renderdoc { extension_list.push(VkString::new("VK_EXT_debug_report")); } if !extension_list.is_empty() { let extension_properties = Self::get_extension_properties(&entry_functions, &layers)?; for extension in extension_list { for ext_prop in &extension_properties { if extension == *ext_prop { checked_extensions.push(extension); break; } } } } // instance create info let layer_names = VkNames::new(layers.as_slice()); let extension_names = VkNames::new(checked_extensions.as_slice()); let instance_ci = VkInstanceCreateInfo::new( VK_INSTANCE_CREATE_NULL_BIT, &app_info, &layer_names, &extension_names, ); println!("enabled layers ({}):", layer_names.len()); for layer_name in layer_names.iter() { println!("\t- {:?}", layer_name); } println!("\nenabled instance extensions ({}):", extension_names.len()); for extension_name in extension_names.iter() { println!("\t- {:?}", extension_name); } println!(); let enabled_extensions = InstanceExtensions::from_list(&checked_extensions); if let Err(missing_extensions) = extensions.check_availability(&enabled_extensions) { for m in missing_extensions { println!("{}", m); } } let instance = unsafe { let mut instance = MaybeUninit::uninit(); let result = entry_functions.vkCreateInstance(&instance_ci, ptr::null(), instance.as_mut_ptr()); if result == VK_SUCCESS { instance.assume_init() } else { return Err(anyhow::Error::new(result)); } }; let instance_functions = InstanceFunctions::new(&static_functions, instance); let instance_wsi_functions = InstanceWSIFunctions::new(&static_functions, instance); let physical_device_properties2_functions = PhysicalDeviceProperties2Functions::new(&static_functions, instance); let debug_report_callback_functions = DebugReportCallbackFunctions::new(&static_functions, instance); let mut instance = Instance { _static_functions: static_functions, _entry_functions: Some(entry_functions), instance_functions, instance_wsi_functions, physical_device_properties2_functions, debug_report_callback_functions, instance, instance_extensions: enabled_extensions, debug_report: None, api_version: app_info.apiVersion, }; if !layers.is_empty() { if let Err(msg) = instance.create_debug_report() { println!("failed creating debug report: {}", msg); } } Ok(Arc::new(instance)) } pub(crate) fn api_version(&self) -> u32 { self.api_version } pub fn enabled_extensions(&self) -> &InstanceExtensions { &self.instance_extensions } } impl_vk_handle!(Instance, VkInstance, instance); // private impl Instance { fn create_debug_report(&mut self) -> Result<()> { let debug_report_info = VkDebugReportCallbackCreateInfoEXT::new( VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT | VK_DEBUG_REPORT_ERROR_BIT_EXT, Instance::debug_report_callback, ); let debug_report = self.create_debug_report_callbacks(&debug_report_info)?; self.debug_report = Some(debug_report); Ok(()) } fn get_extension_properties( entry_functions: &EntryFunctions, layers: &[VkString], ) -> Result> { let mut properties = HashSet::new(); let default_properties = Self::enumerate_extension_properties( entry_functions.vkEnumerateInstanceExtensionProperties, None, )?; for property in default_properties { let prop_string = VkString::new(&property.extension_name()?); properties.insert(prop_string); } for layer in layers { let tmp_properties = Self::enumerate_extension_properties( entry_functions.vkEnumerateInstanceExtensionProperties, Some(layer), )?; for property in tmp_properties { let prop_string = VkString::new(&property.extension_name()?); properties.insert(prop_string); } } Ok(properties.iter().cloned().collect()) } } // debug impl Instance { extern "system" fn debug_report_callback( flags: VkDebugReportFlagsEXT, object_type: VkDebugReportObjectTypeEXT, _src_object: u64, _location: usize, _msg_code: i32, _layer_prefix: *const c_char, msg: *const c_char, _user_data: *mut c_void, ) -> VkBool32 { let mut output: String = String::new(); output += match flags { VK_DEBUG_REPORT_INFORMATION_BIT_EXT => "INFO", VK_DEBUG_REPORT_WARNING_BIT_EXT => "WARNING", VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT => "PERFORMANCE", VK_DEBUG_REPORT_ERROR_BIT_EXT => "ERROR", VK_DEBUG_REPORT_DEBUG_BIT_EXT => "DEBUG", }; output += ": OBJ( "; output += match object_type { VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT => "UNKNOWN", VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT => "INSTANCE", VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT => "PHYSICAL DEVICE", VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT => "DEVICE", VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT => "QUEUE", VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT => "SEMAPHORE", VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT => "COMMAND BUFFER", VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT => "FENCE", VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT => "DEVICE MEMORY", VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT => "BUFFER", VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT => "IMAGE", VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT => "EVENT", VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT => "QUERY POOL", VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT => "BUFFER VIEW", VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT => "IMAGE VIEW", VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT => "SHADER MODULE", VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT => "PIPELINE CACHE", VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT => "PIPELINE LAYOUT", VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT => "RENDER PASS", VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT => "PIPELINE", VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT => "DESCRIPTOR SET LAYOUT", VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT => "SAMPLER", VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT => "DESCRIPTOR POOL", VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT => "DESCRIPTOR SET", VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT => "FRAME BUFFER", VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT => "COMMAND POOL", VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT => "SURFACE KHR", VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT => "SWAPCHAIN KHR", VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT => "DEBUG REPORT", VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT => "DISPLAY KHR", VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT => "DISPLAY MODE KHR", VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT => "OBJECT TABLE NVX", VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT => { "INDIRECT COMMANDS LAYOUT NVX" } VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT => "VALIDATION CACHE ", VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT => "SAMPLER YCBCR CONVERSION ", VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT => { "DESCRIPTOR UPDATE TEMPLATE " } VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR_EXT => { "ACCELERATION STRUCTURE NV" } }; let tmp1 = unsafe { CString::from_raw(msg as *mut c_char) }; let tmp2 = match tmp1.into_string() { Ok(string) => string, Err(err) => { println!("{}", err); return VK_FALSE; } }; output += " ):\n\t"; output += tmp2.as_ref(); println!("{}", output); VK_TRUE } } impl fmt::Debug for Instance { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Instance (VkInstance: {:#?})", self.instance) } } impl Drop for Instance { fn drop(&mut self) { if let Some(debug_report) = &self.debug_report { self.destroy_debug_report_callbacks(*debug_report); } self.destroy_instance(); } } // private wrapper impl Instance { #[inline] fn enumerate_layer_properties( enumerate_instance_layer_properties: PFN_vkEnumerateInstanceLayerProperties, ) -> Result> { let mut property_count: u32 = 0; // get the amount of properties let result = enumerate_instance_layer_properties(&mut property_count, ptr::null_mut()); if result != VK_SUCCESS { return Err(anyhow::Error::new(result)); } let mut properties = Vec::with_capacity(property_count as usize); unsafe { properties.set_len(property_count as usize) }; // get the properties let result = enumerate_instance_layer_properties(&mut property_count, properties.as_mut_ptr()); if result == VK_SUCCESS { Ok(properties) } else { Err(anyhow::Error::new(result)) } } #[inline] fn enumerate_extension_properties( enumerate_instance_extension_properties: PFN_vkEnumerateInstanceExtensionProperties, layer_name: Option<&VkString>, ) -> Result> { let mut count = 0; let name = match layer_name { Some(name) => name.as_ptr(), None => ptr::null(), }; let mut result = enumerate_instance_extension_properties(name, &mut count, ptr::null_mut()); if result != VK_SUCCESS { return Err(anyhow::Error::new(result)); } let mut properties = Vec::with_capacity(count as usize); unsafe { properties.set_len(count as usize) }; result = enumerate_instance_extension_properties(name, &mut count, properties.as_mut_ptr()); if result == VK_SUCCESS { Ok(properties) } else { Err(anyhow::Error::new(result)) } } #[inline] fn destroy_instance(&self) { unsafe { self.instance_functions .vkDestroyInstance(self.instance, ptr::null()); } } } // public, wrapped vulkan calls impl Instance { #[inline] pub fn create_debug_report_callbacks( &self, debug_report_callback_create_info: &VkDebugReportCallbackCreateInfoEXT, ) -> Result { unsafe { let mut debug_report_callback = MaybeUninit::uninit(); let result = self .debug_report_callback_functions .vkCreateDebugReportCallbackEXT( self.instance, debug_report_callback_create_info, ptr::null(), debug_report_callback.as_mut_ptr(), ); if result == VK_SUCCESS { Ok(debug_report_callback.assume_init()) } else { Err(anyhow::Error::new(result)) } } } #[inline] pub fn destroy_debug_report_callbacks(&self, debug_report_callback: VkDebugReportCallbackEXT) { unsafe { self.debug_report_callback_functions .vkDestroyDebugReportCallbackEXT(self.instance, debug_report_callback, ptr::null()) } } #[inline] pub fn get_device_proc_addr(&self, device: VkDevice, name: VkString) -> PFN_vkVoidFunction { unsafe { self.instance_functions .vkGetDeviceProcAddr(device, name.as_ptr()) } } #[inline] pub fn get_device_proc_addr_raw(&self, device: VkDevice, name: &CStr) -> PFN_vkVoidFunction { unsafe { self.instance_functions .vkGetDeviceProcAddr(device, name.as_ptr()) } } #[inline] pub fn enumerate_physical_devices(&self) -> Result> { let mut count = 0; let result = unsafe { self.instance_functions.vkEnumeratePhysicalDevices( self.instance, &mut count, ptr::null_mut(), ) }; if result != VK_SUCCESS { return Err(anyhow::Error::new(result)); } let mut physical_devices = Vec::with_capacity(count as usize); unsafe { physical_devices.set_len(count as usize) }; let result = unsafe { self.instance_functions.vkEnumeratePhysicalDevices( self.instance, &mut count, physical_devices.as_mut_ptr(), ) }; if result == VK_SUCCESS { Ok(physical_devices) } else { Err(anyhow::Error::new(result)) } } #[inline] pub fn physical_device_properties( &self, physical_device: VkPhysicalDevice, ) -> VkPhysicalDeviceProperties { unsafe { let mut physical_device_properties = MaybeUninit::uninit(); self.instance_functions.vkGetPhysicalDeviceProperties( physical_device, physical_device_properties.as_mut_ptr(), ); physical_device_properties.assume_init() } } #[inline] pub fn physical_device_features( &self, physical_device: VkPhysicalDevice, ) -> VkPhysicalDeviceFeatures { unsafe { let mut physical_device_features = MaybeUninit::uninit(); self.instance_functions.vkGetPhysicalDeviceFeatures( physical_device, physical_device_features.as_mut_ptr(), ); physical_device_features.assume_init() } } #[inline] pub fn physical_device_format_properties( &self, physical_device: VkPhysicalDevice, format: VkFormat, ) -> VkFormatProperties { unsafe { let mut physical_device_format_properties = MaybeUninit::uninit(); self.instance_functions.vkGetPhysicalDeviceFormatProperties( physical_device, format, physical_device_format_properties.as_mut_ptr(), ); physical_device_format_properties.assume_init() } } #[inline] pub fn physical_device_queue_family_properties( &self, physical_device: VkPhysicalDevice, ) -> Vec { let mut count = 0; unsafe { self.instance_functions .vkGetPhysicalDeviceQueueFamilyProperties( physical_device, &mut count, ptr::null_mut(), ); } let mut queue_family_properties = Vec::with_capacity(count as usize); unsafe { queue_family_properties.set_len(count as usize) }; unsafe { self.instance_functions .vkGetPhysicalDeviceQueueFamilyProperties( physical_device, &mut count, queue_family_properties.as_mut_ptr(), ); } queue_family_properties } #[inline] pub fn physical_device_memory_properties( &self, physical_device: VkPhysicalDevice, ) -> VkPhysicalDeviceMemoryProperties { unsafe { let mut physical_device_memory_properties = MaybeUninit::uninit(); self.instance_functions.vkGetPhysicalDeviceMemoryProperties( physical_device, physical_device_memory_properties.as_mut_ptr(), ); physical_device_memory_properties.assume_init() } } #[inline] pub fn physical_device_sparse_image_format_properties( &self, physical_device: VkPhysicalDevice, format: VkFormat, ty: VkImageType, samples: VkSampleCountFlags, usage: impl Into, tiling: VkImageTiling, ) -> Vec { let mut count = 0; let usage = usage.into(); unsafe { self.instance_functions .vkGetPhysicalDeviceSparseImageFormatProperties( physical_device, format, ty, samples, usage, tiling, &mut count, ptr::null_mut(), ); } let mut sparse_image_formats = Vec::with_capacity(count as usize); unsafe { sparse_image_formats.set_len(count as usize) }; unsafe { self.instance_functions .vkGetPhysicalDeviceSparseImageFormatProperties( physical_device, format, ty, samples, usage, tiling, &mut count, sparse_image_formats.as_mut_ptr(), ); } sparse_image_formats } #[inline] pub fn physical_device_image_format_properties( &self, physical_device: VkPhysicalDevice, format: VkFormat, image_type: VkImageType, tiling: VkImageTiling, usage: impl Into, flags: impl Into, ) -> Result { unsafe { let mut image_format_properties = MaybeUninit::uninit(); let result = self .instance_functions .vkGetPhysicalDeviceImageFormatProperties( physical_device, format, image_type, tiling, usage.into(), flags.into(), image_format_properties.as_mut_ptr(), ); if result == VK_SUCCESS { Ok(image_format_properties.assume_init()) } else { Err(anyhow::Error::new(result)) } } } #[inline] pub fn create_device<'a>( &self, physical_device: VkPhysicalDevice, device_create_info: &'a VkDeviceCreateInfo<'a>, ) -> Result { unsafe { let mut device = MaybeUninit::uninit(); let result = self.instance_functions.vkCreateDevice( physical_device, device_create_info, ptr::null(), device.as_mut_ptr(), ); if result == VK_SUCCESS { Ok(device.assume_init()) } else { Err(anyhow::Error::new(result)) } } } #[inline] pub fn physical_device_surface_support( &self, physical_device: VkPhysicalDevice, queue_family_index: u32, surface: VkSurfaceKHR, ) -> Result { unsafe { let mut supported = MaybeUninit::uninit(); let result = self .instance_wsi_functions .vkGetPhysicalDeviceSurfaceSupportKHR( physical_device, queue_family_index, surface, supported.as_mut_ptr(), ); if result == VK_SUCCESS { Ok(supported.assume_init() == VK_TRUE) } else { Err(anyhow::Error::new(result)) } } } #[inline] pub fn physical_device_surface_capabilities( &self, physical_device: VkPhysicalDevice, surface: VkSurfaceKHR, ) -> Result { unsafe { let mut surface_capabilities = MaybeUninit::uninit(); let result = self .instance_wsi_functions .vkGetPhysicalDeviceSurfaceCapabilitiesKHR( physical_device, surface, surface_capabilities.as_mut_ptr(), ); if result == VK_SUCCESS { Ok(surface_capabilities.assume_init()) } else { Err(anyhow::Error::new(result)) } } } #[inline] pub fn physical_device_surface_formats( &self, physical_device: VkPhysicalDevice, surface: VkSurfaceKHR, ) -> Result> { let mut count = 0; let result = unsafe { self.instance_wsi_functions .vkGetPhysicalDeviceSurfaceFormatsKHR( physical_device, surface, &mut count, ptr::null_mut(), ) }; if result != VK_SUCCESS { return Err(anyhow::Error::new(result)); } let mut surface_formats = Vec::with_capacity(count as usize); unsafe { surface_formats.set_len(count as usize) }; let result = unsafe { self.instance_wsi_functions .vkGetPhysicalDeviceSurfaceFormatsKHR( physical_device, surface, &mut count, surface_formats.as_mut_ptr(), ) }; if result == VK_SUCCESS { Ok(surface_formats) } else { Err(anyhow::Error::new(result)) } } #[inline] pub fn physical_device_present_modes( &self, physical_device: VkPhysicalDevice, surface: VkSurfaceKHR, ) -> Result> { let mut count = 0; let result = unsafe { self.instance_wsi_functions .vkGetPhysicalDeviceSurfacePresentModesKHR( physical_device, surface, &mut count, ptr::null_mut(), ) }; if result != VK_SUCCESS { return Err(anyhow::Error::new(result)); } let mut surface_present_modes = Vec::with_capacity(count as usize); unsafe { surface_present_modes.set_len(count as usize) }; let result = unsafe { self.instance_wsi_functions .vkGetPhysicalDeviceSurfacePresentModesKHR( physical_device, surface, &mut count, surface_present_modes.as_mut_ptr(), ) }; if result == VK_SUCCESS { Ok(surface_present_modes) } else { Err(anyhow::Error::new(result)) } } #[inline] pub fn enumerate_device_extensions( &self, physical_device: VkPhysicalDevice, ) -> Result> { let mut count = 0; let result = unsafe { self.instance_functions .vkEnumerateDeviceExtensionProperties( physical_device, ptr::null(), &mut count, ptr::null_mut(), ) }; if result != VK_SUCCESS { return Err(anyhow::Error::new(result)); } let mut extension_properties = Vec::with_capacity(count as usize); unsafe { extension_properties.set_len(count as usize) }; let result = unsafe { self.instance_functions .vkEnumerateDeviceExtensionProperties( physical_device, ptr::null(), &mut count, extension_properties.as_mut_ptr(), ) }; if result == VK_SUCCESS { Ok(extension_properties) } else { Err(anyhow::Error::new(result)) } } #[inline] pub fn physical_device_properties2( &self, physical_device: VkPhysicalDevice, device_properties: &mut VkPhysicalDeviceProperties2KHR, ) { unsafe { self.physical_device_properties2_functions .vkGetPhysicalDeviceProperties2KHR(physical_device, device_properties); } } #[inline] pub fn physical_device_features2( &self, physical_device: VkPhysicalDevice, device_features: &mut VkPhysicalDeviceFeatures2KHR, ) { unsafe { self.physical_device_properties2_functions .vkGetPhysicalDeviceFeatures2KHR(physical_device, device_features); } } #[inline] pub fn physical_device_format_properties2( &self, physical_device: VkPhysicalDevice, ) -> VkFormatProperties2KHR<'_> { unsafe { let mut handle = MaybeUninit::uninit(); self.physical_device_properties2_functions .vkGetPhysicalDeviceFormatProperties2KHR(physical_device, handle.as_mut_ptr()); handle.assume_init() } } #[inline] pub fn physical_device_image_format_properties2( &self, physical_device: VkPhysicalDevice, image_format_info: &VkPhysicalDeviceImageFormatInfo2KHR, ) -> VkImageFormatProperties2KHR<'_> { unsafe { let mut handle = MaybeUninit::uninit(); self.physical_device_properties2_functions .vkGetPhysicalDeviceImageFormatProperties2KHR( physical_device, image_format_info, handle.as_mut_ptr(), ); handle.assume_init() } } #[inline] pub fn physical_device_queue_family_properties2( &self, physical_device: VkPhysicalDevice, ) -> Vec { let mut count = 0; unsafe { self.physical_device_properties2_functions .vkGetPhysicalDeviceQueueFamilyProperties2KHR( physical_device, &mut count, ptr::null_mut(), ) }; let mut family_queue_properties = Vec::with_capacity(count as usize); unsafe { family_queue_properties.set_len(count as usize) }; unsafe { self.physical_device_properties2_functions .vkGetPhysicalDeviceQueueFamilyProperties2KHR( physical_device, &mut count, family_queue_properties.as_mut_ptr(), ) }; family_queue_properties } #[inline] pub fn physical_device_memory_properties2( &self, physical_device: VkPhysicalDevice, ) -> VkPhysicalDeviceMemoryProperties2KHR { unsafe { let mut handle = MaybeUninit::uninit(); self.physical_device_properties2_functions .vkGetPhysicalDeviceMemoryProperties2KHR(physical_device, handle.as_mut_ptr()); handle.assume_init() } } #[inline] pub fn physical_device_memory_budget( &self, physical_device: VkPhysicalDevice, ) -> (VkPhysicalDeviceMemoryBudgetPropertiesEXT, u32) { unsafe { let mut properties = VkPhysicalDeviceMemoryProperties2KHR::default(); let mut memory_budget = VkPhysicalDeviceMemoryBudgetPropertiesEXT::default(); properties.chain(&mut memory_budget); self.physical_device_properties2_functions .vkGetPhysicalDeviceMemoryProperties2KHR(physical_device, &mut properties); (memory_budget, properties.memoryProperties.memoryHeapCount) } } #[inline] pub fn physical_device_sparse_image_format_properties2( &self, physical_device: VkPhysicalDevice, format_info: &VkPhysicalDeviceSparseImageFormatInfo2KHR, ) -> Vec { let mut count = 0; unsafe { self.physical_device_properties2_functions .vkGetPhysicalDeviceSparseImageFormatProperties2KHR( physical_device, format_info, &mut count, ptr::null_mut(), ) }; let mut sparse_image_formats = Vec::with_capacity(count as usize); unsafe { sparse_image_formats.set_len(count as usize) }; unsafe { self.physical_device_properties2_functions .vkGetPhysicalDeviceSparseImageFormatProperties2KHR( physical_device, format_info, &mut count, sparse_image_formats.as_mut_ptr(), ) }; sparse_image_formats } #[inline] pub fn destroy_surface(&self, surface: VkSurfaceKHR) { unsafe { self.instance_wsi_functions .vkDestroySurfaceKHR(self.instance, surface, ptr::null()) }; } }