Add a transfer queue to VulkanoContext (#2573)

* Add a transfer queue to `VulkanoContext`

* Might as well
This commit is contained in:
Rua 2024-10-15 20:42:15 +02:00 committed by GitHub
parent a270468960
commit 9c358806be
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -93,8 +93,7 @@ pub struct VulkanoContext {
instance: Arc<Instance>, instance: Arc<Instance>,
_debug_utils_messenger: Option<DebugUtilsMessenger>, _debug_utils_messenger: Option<DebugUtilsMessenger>,
device: Arc<Device>, device: Arc<Device>,
graphics_queue: Arc<Queue>, queues: Queues,
compute_queue: Arc<Queue>,
memory_allocator: Arc<StandardMemoryAllocator>, memory_allocator: Arc<StandardMemoryAllocator>,
} }
@ -166,20 +165,18 @@ impl VulkanoContext {
} }
// Create device // Create device
let (device, graphics_queue, compute_queue) = Self::create_device( let (device, queues) = Self::create_device(
physical_device, physical_device,
config.device_extensions, config.device_extensions,
config.device_features, config.device_features,
); );
let memory_allocator = Arc::new(StandardMemoryAllocator::new_default(device.clone())); let memory_allocator = Arc::new(StandardMemoryAllocator::new_default(device.clone()));
Self { Self {
instance, instance,
_debug_utils_messenger, _debug_utils_messenger,
device, device,
graphics_queue, queues,
compute_queue,
memory_allocator, memory_allocator,
} }
} }
@ -190,7 +187,7 @@ impl VulkanoContext {
physical_device: Arc<PhysicalDevice>, physical_device: Arc<PhysicalDevice>,
device_extensions: DeviceExtensions, device_extensions: DeviceExtensions,
device_features: DeviceFeatures, device_features: DeviceFeatures,
) -> (Arc<Device>, Arc<Queue>, Arc<Queue>) { ) -> (Arc<Device>, Queues) {
let queue_family_graphics = physical_device let queue_family_graphics = physical_device
.queue_family_properties() .queue_family_properties()
.iter() .iter()
@ -209,25 +206,37 @@ impl VulkanoContext {
q.queue_flags.intersects(QueueFlags::COMPUTE) && *i != queue_family_graphics q.queue_flags.intersects(QueueFlags::COMPUTE) && *i != queue_family_graphics
}) })
.map(|(i, _)| i); .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 { let queue_create_infos: Vec<_> = [
vec![ Some(QueueCreateInfo {
QueueCreateInfo {
queue_family_index: queue_family_graphics,
..Default::default()
},
QueueCreateInfo {
queue_family_index: queue_family_compute,
..Default::default()
},
]
} else {
vec![QueueCreateInfo {
queue_family_index: queue_family_graphics, queue_family_index: queue_family_graphics,
..Default::default() ..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) = { let (device, mut queues) = {
Device::new( Device::new(
@ -241,13 +250,24 @@ impl VulkanoContext {
) )
.expect("failed to create device") .expect("failed to create device")
}; };
let gfx_queue = queues.next().unwrap();
let compute_queue = if is_separate_compute_queue { let graphics_queue = queues.next().unwrap();
queues.next().unwrap() let compute_queue = queue_family_compute
} else { .is_some()
gfx_queue.clone() .then(|| queues.next().unwrap())
}; .unwrap_or(graphics_queue.clone());
(device, gfx_queue, compute_queue) 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. /// Returns the name of the device.
@ -286,15 +306,22 @@ impl VulkanoContext {
/// Returns the graphics queue. /// Returns the graphics queue.
#[inline] #[inline]
pub fn graphics_queue(&self) -> &Arc<Queue> { pub fn graphics_queue(&self) -> &Arc<Queue> {
&self.graphics_queue &self.queues.graphics_queue
} }
/// Returns the compute 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] #[inline]
pub fn compute_queue(&self) -> &Arc<Queue> { pub fn compute_queue(&self) -> &Arc<Queue> {
&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<Queue>> {
self.queues.transfer_queue.as_ref()
} }
/// Returns the memory allocator. /// Returns the memory allocator.
@ -303,3 +330,9 @@ impl VulkanoContext {
&self.memory_allocator &self.memory_allocator
} }
} }
struct Queues {
graphics_queue: Arc<Queue>,
compute_queue: Arc<Queue>,
transfer_queue: Option<Arc<Queue>>,
}