diff --git a/crates/engine_vulkan/src/utils/device.rs b/crates/engine_vulkan/src/utils/device.rs index 6c4b49f..e44ac52 100644 --- a/crates/engine_vulkan/src/utils/device.rs +++ b/crates/engine_vulkan/src/utils/device.rs @@ -1,8 +1,9 @@ -use std::sync::Arc; +use std::{collections::HashMap, sync::Arc}; use bevy_ecs::world::World; use engine_window::raw_handle::DisplayHandleWrapper; use vulkano::{ + VulkanError, command_buffer::allocator::StandardCommandBufferAllocator, descriptor_set::allocator::StandardDescriptorSetAllocator, device::{ @@ -86,22 +87,30 @@ fn pick_physical_device(world: &World, config: &VulkanConfig) -> Option() .expect("Failed to get VulkanInstance during vulkan plugin initialization"); - instance + let result = instance .0 .enumerate_physical_devices() .expect("Failed to enumerate physical devices") - .filter_map(|p| check_physical_device(world, &p, config)) - .min_by_key( - |p| match p.device.physical_device().properties().device_type { - PhysicalDeviceType::DiscreteGpu => 0, - PhysicalDeviceType::IntegratedGpu => 1, - PhysicalDeviceType::VirtualGpu => 2, - PhysicalDeviceType::Cpu => 3, - PhysicalDeviceType::Other => 4, - _ => 5, - }, - ) - .take() + .filter_map(|p| check_physical_device_support(world, &p, config).and_then(|r| Some((p, r)))) + .min_by_key(|(p, _)| match p.properties().device_type { + PhysicalDeviceType::DiscreteGpu => 0, + PhysicalDeviceType::IntegratedGpu => 1, + PhysicalDeviceType::VirtualGpu => 2, + PhysicalDeviceType::Cpu => 3, + PhysicalDeviceType::Other => 4, + _ => 5, + }) + .take(); + + match result { + Some((p, (device_extensions, picked_queues_info))) => Some(create_device( + config, + &p, + device_extensions, + &picked_queues_info, + )), + None => None, + } } fn check_device_extensions_support( @@ -147,7 +156,7 @@ fn check_queues_support( let mut transfer_queue_family_index: Option = None; for (i, queue_family_property) in physical_device.queue_family_properties().iter().enumerate() { - if config.with_graphics_queue { + if config.with_graphics_queue && graphics_queue_family_index.is_none() { let graphics_supported = queue_family_property .queue_flags .intersects(QueueFlags::GRAPHICS); @@ -169,7 +178,7 @@ fn check_queues_support( } } - if config.with_compute_queue { + if config.with_compute_queue && compute_queue_family_index.is_none() { let compute_supported = queue_family_property .queue_flags .intersects(QueueFlags::COMPUTE); @@ -179,7 +188,7 @@ fn check_queues_support( } } - if config.with_transfer_queue { + if config.with_transfer_queue && transfer_queue_family_index.is_none() { let transfer_supported = queue_family_property .queue_flags .intersects(QueueFlags::TRANSFER); @@ -193,7 +202,10 @@ fn check_queues_support( if !config.with_graphics_queue { log::debug!("\t\t[SKIPPED] Graphics queue is not required"); } else if graphics_queue_family_index.is_some() { - log::debug!("\t\t[OK] Graphics queue is supported"); + log::debug!( + "\t\t[OK] Graphics queue is supported (family index: {:?})", + graphics_queue_family_index + ); } else { log::debug!("\t\t[FAILED] Graphics queue is not supported"); return None; @@ -202,7 +214,10 @@ fn check_queues_support( if !config.with_compute_queue { log::debug!("\t\t[SKIPPED] Compute queue is not required"); } else if compute_queue_family_index.is_some() { - log::debug!("\t\t[OK] Compute queue is supported"); + log::debug!( + "\t\t[OK] Compute queue is supported (family index: {:?})", + compute_queue_family_index + ); } else { log::debug!("\t\t[FAILED] Compute queue is not supported"); return None; @@ -211,7 +226,10 @@ fn check_queues_support( if !config.with_transfer_queue { log::debug!("\t\t[SKIPPED] Transfer queue is not required"); } else if transfer_queue_family_index.is_some() { - log::debug!("\t\t[OK] Transfer queue is supported"); + log::debug!( + "\t\t[OK] Transfer queue is supported (family index: {:?})", + transfer_queue_family_index + ); } else { log::debug!("\t\t[FAILED] Transfer queue is not supported"); return None; @@ -224,11 +242,11 @@ fn check_queues_support( }) } -fn check_physical_device( +fn check_physical_device_support( world: &World, physical_device: &Arc, config: &VulkanConfig, -) -> Option { +) -> Option<(DeviceExtensions, PickedQueuesInfo)> { log::debug!("Checking physical device"); log::debug!("\tProperties"); log::debug!("\t\tName: {}", physical_device.properties().device_name); @@ -242,33 +260,54 @@ fn check_physical_device( let device_extensions = check_device_extensions_support(physical_device, config)?; let picked_queues_info = check_queues_support(world, physical_device, config)?; - let mut queue_create_infos = vec![]; + Some((device_extensions, picked_queues_info)) +} + +fn create_device( + config: &VulkanConfig, + physical_device: &Arc, + device_extensions: DeviceExtensions, + picked_queues_info: &PickedQueuesInfo, +) -> PickedDevice { + let mut queue_create_infos = HashMap::::new(); if config.with_graphics_queue { - queue_create_infos.push(QueueCreateInfo { - queue_family_index: picked_queues_info.graphics_queue_family_index.unwrap(), - ..Default::default() - }); + let entry = queue_create_infos + .entry(picked_queues_info.graphics_queue_family_index.unwrap()) + .or_insert(QueueCreateInfo { + queue_family_index: picked_queues_info.graphics_queue_family_index.unwrap(), + ..Default::default() + }); + + entry.queues.push(1.0); } if config.with_compute_queue { - queue_create_infos.push(QueueCreateInfo { - queue_family_index: picked_queues_info.compute_queue_family_index.unwrap(), - ..Default::default() - }); + let entry = queue_create_infos + .entry(picked_queues_info.compute_queue_family_index.unwrap()) + .or_insert(QueueCreateInfo { + queue_family_index: picked_queues_info.compute_queue_family_index.unwrap(), + ..Default::default() + }); + + entry.queues.push(1.0); } if config.with_transfer_queue { - queue_create_infos.push(QueueCreateInfo { - queue_family_index: picked_queues_info.transfer_queue_family_index.unwrap(), - ..Default::default() - }); + let entry = queue_create_infos + .entry(picked_queues_info.transfer_queue_family_index.unwrap()) + .or_insert(QueueCreateInfo { + queue_family_index: picked_queues_info.transfer_queue_family_index.unwrap(), + ..Default::default() + }); + + entry.queues.push(1.0); } let (device, mut queues) = Device::new( physical_device.clone(), DeviceCreateInfo { - queue_create_infos, + queue_create_infos: queue_create_infos.values().cloned().collect(), enabled_extensions: device_extensions, enabled_features: config.device_features, ..Default::default() @@ -292,10 +331,10 @@ fn check_physical_device( transfer_queue = queues.next(); } - Some(PickedDevice { + PickedDevice { device, graphics_queue, compute_queue, transfer_queue, - }) + } } diff --git a/crates/engine_vulkan/src/vulkan_context.rs b/crates/engine_vulkan/src/vulkan_context.rs deleted file mode 100644 index 08ff1ac..0000000 --- a/crates/engine_vulkan/src/vulkan_context.rs +++ /dev/null @@ -1,76 +0,0 @@ -use std::{any::Any, sync::Arc}; - -use bevy_app::App; -use bevy_ecs::resource::Resource; -use engine_window::raw_handle::DisplayHandleWrapper; -use vulkano::{ - command_buffer::{ - AutoCommandBufferBuilder, CommandBufferUsage, PrimaryAutoCommandBuffer, - allocator::StandardCommandBufferAllocator, - }, - descriptor_set::allocator::StandardDescriptorSetAllocator, - device::{Device, Queue}, - instance::Instance, - memory::allocator::StandardMemoryAllocator, - swapchain::Surface, -}; -use winit::raw_window_handle::{HasDisplayHandle, HasWindowHandle}; - -use super::utils; - -#[derive(Resource)] -pub struct VulkanContext { - pub instance: Arc, - pub device: Arc, - pub graphics_queue: Arc, - - pub memory_allocator: Arc, - pub command_buffer_allocator: Arc, - pub descriptor_set_allocator: Arc, -} - -impl VulkanContext { - pub fn create_surface( - &self, - window: Arc, - ) -> Arc { - Surface::from_window(self.instance.clone(), window).unwrap() - } - - pub fn create_render_builder(&self) -> AutoCommandBufferBuilder { - AutoCommandBufferBuilder::primary( - self.command_buffer_allocator.clone(), - self.graphics_queue.queue_family_index(), - CommandBufferUsage::OneTimeSubmit, - ) - .unwrap() - } -} - -impl From<&App> for VulkanContext { - fn from(app: &App) -> Self { - let (device, mut queues) = utils::pick_graphics_device(&instance, &display_handle.0); - let graphics_queue = queues.next().unwrap(); - - let memory_allocator = Arc::new(StandardMemoryAllocator::new_default(device.clone())); - - let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new( - device.clone(), - Default::default(), - )); - - let descriptor_set_allocator = Arc::new(StandardDescriptorSetAllocator::new( - device.clone(), - Default::default(), - )); - - Self { - instance: instance.clone(), - device, - graphics_queue, - memory_allocator, - command_buffer_allocator, - descriptor_set_allocator, - } - } -}