From 9c358806be3afc65bc7fa7ebdeaf6c0b34051807 Mon Sep 17 00:00:00 2001 From: Rua Date: Tue, 15 Oct 2024 20:42:15 +0200 Subject: [PATCH] Add a transfer queue to `VulkanoContext` (#2573) * Add a transfer queue to `VulkanoContext` * Might as well --- vulkano-util/src/context.rs | 99 ++++++++++++++++++++++++------------- 1 file changed, 66 insertions(+), 33 deletions(-) diff --git a/vulkano-util/src/context.rs b/vulkano-util/src/context.rs index 28dfbcab..a99610da 100644 --- a/vulkano-util/src/context.rs +++ b/vulkano-util/src/context.rs @@ -93,8 +93,7 @@ pub struct VulkanoContext { instance: Arc, _debug_utils_messenger: Option, device: Arc, - graphics_queue: Arc, - compute_queue: Arc, + queues: Queues, memory_allocator: Arc, } @@ -166,20 +165,18 @@ impl VulkanoContext { } // Create device - let (device, graphics_queue, compute_queue) = Self::create_device( + let (device, queues) = Self::create_device( physical_device, config.device_extensions, config.device_features, ); - let memory_allocator = Arc::new(StandardMemoryAllocator::new_default(device.clone())); Self { instance, _debug_utils_messenger, device, - graphics_queue, - compute_queue, + queues, memory_allocator, } } @@ -190,7 +187,7 @@ impl VulkanoContext { physical_device: Arc, device_extensions: DeviceExtensions, device_features: DeviceFeatures, - ) -> (Arc, Arc, Arc) { + ) -> (Arc, Queues) { let queue_family_graphics = physical_device .queue_family_properties() .iter() @@ -209,25 +206,37 @@ impl VulkanoContext { q.queue_flags.intersects(QueueFlags::COMPUTE) && *i != queue_family_graphics }) .map(|(i, _)| i); - let is_separate_compute_queue = queue_family_compute.is_some(); + // Try finding a separate queue for transfer + let queue_family_transfer = physical_device + .queue_family_properties() + .iter() + .enumerate() + .map(|(i, q)| (i as u32, q)) + .find(|(_i, q)| { + q.queue_flags.intersects(QueueFlags::TRANSFER) + && !q + .queue_flags + .intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE) + }) + .map(|(i, _)| i); - let queue_create_infos = if let Some(queue_family_compute) = queue_family_compute { - vec![ - QueueCreateInfo { - queue_family_index: queue_family_graphics, - ..Default::default() - }, - QueueCreateInfo { - queue_family_index: queue_family_compute, - ..Default::default() - }, - ] - } else { - vec![QueueCreateInfo { + let queue_create_infos: Vec<_> = [ + Some(QueueCreateInfo { queue_family_index: queue_family_graphics, ..Default::default() - }] - }; + }), + queue_family_compute.map(|queue_family_index| QueueCreateInfo { + queue_family_index, + ..Default::default() + }), + queue_family_transfer.map(|queue_family_index| QueueCreateInfo { + queue_family_index, + ..Default::default() + }), + ] + .into_iter() + .flatten() + .collect(); let (device, mut queues) = { Device::new( @@ -241,13 +250,24 @@ impl VulkanoContext { ) .expect("failed to create device") }; - let gfx_queue = queues.next().unwrap(); - let compute_queue = if is_separate_compute_queue { - queues.next().unwrap() - } else { - gfx_queue.clone() - }; - (device, gfx_queue, compute_queue) + + let graphics_queue = queues.next().unwrap(); + let compute_queue = queue_family_compute + .is_some() + .then(|| queues.next().unwrap()) + .unwrap_or(graphics_queue.clone()); + let transfer_queue = queue_family_transfer + .is_some() + .then(|| queues.next().unwrap()); + + ( + device, + Queues { + graphics_queue, + compute_queue, + transfer_queue, + }, + ) } /// Returns the name of the device. @@ -286,15 +306,22 @@ impl VulkanoContext { /// Returns the graphics queue. #[inline] pub fn graphics_queue(&self) -> &Arc { - &self.graphics_queue + &self.queues.graphics_queue } /// Returns the compute queue. /// - /// Depending on your device, this might be the same as graphics queue. + /// Depending on your device, this might be the same as the graphics queue. #[inline] pub fn compute_queue(&self) -> &Arc { - &self.compute_queue + &self.queues.compute_queue + } + + /// Returns the transfer queue, if the device has a queue family that is dedicated for + /// transfers (does not support graphics or compute). + #[inline] + pub fn transfer_queue(&self) -> Option<&Arc> { + self.queues.transfer_queue.as_ref() } /// Returns the memory allocator. @@ -303,3 +330,9 @@ impl VulkanoContext { &self.memory_allocator } } + +struct Queues { + graphics_queue: Arc, + compute_queue: Arc, + transfer_queue: Option>, +}