From 06cc558baf8d3f8db331ab18a511f20873e30020 Mon Sep 17 00:00:00 2001 From: Florian RICHER Date: Thu, 7 Nov 2024 14:05:09 +0100 Subject: [PATCH] Finish vk_instance Add vk_physical_device --- src/display/app.rs | 4 +++ src/vulkan/mod.rs | 7 +++-- src/vulkan/vk_instance.rs | 45 ++++++++++++++++++---------- src/vulkan/vk_physical_device.rs | 51 ++++++++++++++++++++++++++++++++ 4 files changed, 90 insertions(+), 17 deletions(-) create mode 100644 src/vulkan/vk_physical_device.rs diff --git a/src/display/app.rs b/src/display/app.rs index e7270ab..78d5cbc 100644 --- a/src/display/app.rs +++ b/src/display/app.rs @@ -34,6 +34,10 @@ impl ApplicationHandler for App { self.instance = self.window .as_ref() .and_then(|w| Some(VkInstance::new(w))); + + if let Some(instance) = self.instance.as_ref() { + let _ = instance.get_physical_devices(); + } } fn window_event(&mut self, event_loop: &ActiveEventLoop, id: WindowId, event: WindowEvent) { diff --git a/src/vulkan/mod.rs b/src/vulkan/mod.rs index ef95c25..c34e218 100644 --- a/src/vulkan/mod.rs +++ b/src/vulkan/mod.rs @@ -1,2 +1,5 @@ -mod vk_instance; -pub use vk_instance::VkInstance; \ No newline at end of file +pub(self) mod vk_instance; +pub(self) mod vk_physical_device; + +pub use vk_instance::VkInstance; +pub use vk_physical_device::VkPhysicalDevice; \ No newline at end of file diff --git a/src/vulkan/vk_instance.rs b/src/vulkan/vk_instance.rs index bf96269..42f1630 100644 --- a/src/vulkan/vk_instance.rs +++ b/src/vulkan/vk_instance.rs @@ -1,25 +1,21 @@ -use std::ffi; -use std::ffi::c_char; +use std::ffi::CString; use ash::{Instance, vk, Entry}; use winit::raw_window_handle::{HasDisplayHandle}; +use crate::vulkan::VkPhysicalDevice; pub struct VkInstance { - instance: Instance + handle: Instance, } impl VkInstance { pub fn new(window: &impl HasDisplayHandle) -> Self { let entry = Entry::linked(); - let app_name = unsafe { ffi::CStr::from_bytes_with_nul_unchecked(b"VulkanTriangle\0") }; - let layer_names = [ - unsafe { ffi::CStr::from_bytes_with_nul_unchecked(b"VK_LAYER_KHRONOS_validation\0") } - ]; - let layers_names_raw: Vec<*const c_char> = layer_names - .iter() - .map(|raw_name| raw_name.as_ptr()) - .collect(); + // Layers + let layers_available = unsafe { entry.enumerate_instance_layer_properties().unwrap_or_default() }; + let layer_names = layers_available.iter().map(|layer| layer.layer_name.as_ptr()).collect::>(); + // Extensions let mut extension_names = ash_window::enumerate_required_extensions(window.display_handle().expect("No display handle").as_raw()) .unwrap() @@ -32,10 +28,12 @@ impl VkInstance { extension_names.push(ash::khr::get_physical_device_properties2::NAME.as_ptr()); } + // App Info + let app_name = CString::new("VulkanTriangle").unwrap(); let appinfo = vk::ApplicationInfo::default() - .application_name(app_name) + .application_name(app_name.as_c_str()) .application_version(0) - .engine_name(app_name) + .engine_name(app_name.as_c_str()) .engine_version(0) .api_version(vk::make_api_version(0, 1, 0, 0)); @@ -45,9 +43,10 @@ impl VkInstance { vk::InstanceCreateFlags::default() }; + // Instance Info let create_info = vk::InstanceCreateInfo::default() .application_info(&appinfo) - .enabled_layer_names(&layers_names_raw) + .enabled_layer_names(&layer_names) .enabled_extension_names(&extension_names) .flags(create_flags); @@ -58,7 +57,23 @@ impl VkInstance { }; Self { - instance + handle: instance + } + } + + 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); } } } \ No newline at end of file diff --git a/src/vulkan/vk_physical_device.rs b/src/vulkan/vk_physical_device.rs new file mode 100644 index 0000000..0b0ee2a --- /dev/null +++ b/src/vulkan/vk_physical_device.rs @@ -0,0 +1,51 @@ +use ash::vk; + +pub struct VkPhysicalDevice { + // Vulkan properties + handle: vk::PhysicalDevice, + properties: vk::PhysicalDeviceProperties, + features: vk::PhysicalDeviceFeatures, + queue_family_properties: Vec, +} + +impl VkPhysicalDevice { + pub fn new(instance: &ash::Instance, physical_device: vk::PhysicalDevice) -> Self { + let device_properties = unsafe { instance.get_physical_device_properties(physical_device) }; + let device_features = unsafe { instance.get_physical_device_features(physical_device) }; + let device_queue_families = + unsafe { instance.get_physical_device_queue_family_properties(physical_device) }; + + Self { + handle: physical_device, + properties: device_properties, + features: device_features, + queue_family_properties: device_queue_families + } + } + + pub fn priority(&self) -> usize { + let mut priority = 0; + + let has_graphics_support = self.queue_family_properties.iter().any(|qf| qf.queue_flags.contains(vk::QueueFlags::GRAPHICS)); + let has_compute_support = self.queue_family_properties.iter().any(|qf| qf.queue_flags.contains(vk::QueueFlags::COMPUTE)); + let has_transfer_support = self.queue_family_properties.iter().any(|qf| qf.queue_flags.contains(vk::QueueFlags::TRANSFER)); + let has_sparse_binding_support = self.queue_family_properties.iter().any(|qf| qf.queue_flags.contains(vk::QueueFlags::SPARSE_BINDING)); + let physical_device_type = self.properties.device_type; + + priority |= has_graphics_support as usize; + priority |= (has_sparse_binding_support as usize) << 1; + priority |= (has_transfer_support as usize) << 2; + priority |= (has_compute_support as usize) << 3; + + let weight : usize = match physical_device_type { + vk::PhysicalDeviceType::CPU => 1, + vk::PhysicalDeviceType::VIRTUAL_GPU => 2, + vk::PhysicalDeviceType::INTEGRATED_GPU => 3, + vk::PhysicalDeviceType::DISCRETE_GPU => 4, + _ => 0 + }; + priority |= weight << 4; + + priority + } +} \ No newline at end of file