use crate::vulkan::utils::layers::{use_layers, LayersSelector}; use crate::vulkan::{VkPhysicalDevice, LOG_TARGET}; use ash::khr::surface; use ash::{vk, Entry, Instance}; use std::ffi::{c_char, CStr, CString}; pub struct VkInstance { pub(super) entry: Entry, pub(super) handle: Instance, pub(super) surface_loader: surface::Instance, } impl VkInstance { pub fn new(required_extensions: &Vec<*const c_char>) -> Self { let entry = Entry::linked(); log::debug!(target: LOG_TARGET, "Initializing Vulkan instance"); if log::log_enabled!(target: LOG_TARGET, log::Level::Debug) { let layer_properties = unsafe { entry.enumerate_instance_layer_properties() }.unwrap_or_default(); for layer_property in layer_properties { let layer_extensions = unsafe { entry.enumerate_instance_extension_properties( layer_property.layer_name_as_c_str().ok(), ) } .unwrap_or_default(); log::debug!(target: LOG_TARGET, "{layer_property:#?} {layer_extensions:#?}"); } } { let required_extensions = required_extensions .iter() .map(|str| unsafe { CStr::from_ptr(*str) }) .map(|cstr| cstr.to_string_lossy()) .collect::>(); log::debug!(target: LOG_TARGET, "Required instance extensions: {}", required_extensions.join(", ")); } // Layers let layers = use_layers( &entry, LayersSelector::SpecificLayers(vec![ "VK_LAYER_KHRONOS_validation", "VK_LAYER_MANGOHUD_overlay_x86_64", "VK_LAYER_NV_optimus", ]), ); { let layers = layers .iter() .map(|layer| layer.to_string_lossy()) .collect::>(); log::debug!(target: LOG_TARGET, "Selected debug layers : {}", layers.join(", ")) } let layers_raw = layers.iter().map(|s| s.as_ptr()).collect::>(); // App Info let app_name = CString::new("VulkanTriangle").unwrap(); let appinfo = vk::ApplicationInfo::default() .application_name(app_name.as_c_str()) .application_version(0) .engine_name(app_name.as_c_str()) .engine_version(0) .api_version(vk::make_api_version(0, 1, 0, 0)); let create_flags = if cfg!(any(target_os = "macos", target_os = "ios")) { vk::InstanceCreateFlags::ENUMERATE_PORTABILITY_KHR } else { vk::InstanceCreateFlags::default() }; // Instance Info let create_info = vk::InstanceCreateInfo::default() .application_info(&appinfo) .enabled_layer_names(&layers_raw) .enabled_extension_names(&required_extensions) .flags(create_flags); let instance: Instance = unsafe { entry .create_instance(&create_info, None) .expect("Instance creation error") }; let surface_loader = surface::Instance::new(&entry, &instance); log::debug!(target: LOG_TARGET, "Vulkan instance created ({:?})", instance.handle()); Self { entry, handle: instance, surface_loader, } } pub fn get_physical_devices(&self) -> Vec { let physical_devices = unsafe { self.handle.enumerate_physical_devices() }; physical_devices .unwrap_or_default() .iter() .map(|physical_device| VkPhysicalDevice::new(&self.handle, *physical_device)) .collect() } } impl Drop for VkInstance { fn drop(&mut self) { unsafe { self.handle.destroy_instance(None); } log::debug!(target: LOG_TARGET, "Vulkan instance destroyed ({:?})", self.handle.handle()); } }