vulkano_test/crates/engine_vulkan/src/queues.rs
Florian RICHER 15565d03c1
Some checks failed
Build legacy Nix package on Ubuntu / build (push) Failing after 8m56s
engine_vulkan: Fix allocate more queue as available and add different priorities
2025-05-24 17:02:01 +02:00

176 lines
5.6 KiB
Rust

use std::{collections::HashMap, sync::Arc};
use engine_window::raw_handle::DisplayHandleWrapper;
use vulkano::device::{
QueueCreateInfo, QueueFamilyProperties, QueueFlags, physical::PhysicalDevice,
};
#[derive(Debug)]
pub enum VulkanQueueFamilyStatus {
Unused,
NotSupported,
Supported(u32),
}
impl VulkanQueueFamilyStatus {
pub fn can_be_set(&self) -> bool {
match self {
VulkanQueueFamilyStatus::NotSupported => true,
_ => false,
}
}
}
/// Convert a boolean to a VulkanQueueFamilyStatus as default value
impl From<bool> for VulkanQueueFamilyStatus {
fn from(value: bool) -> Self {
if value {
VulkanQueueFamilyStatus::NotSupported
} else {
VulkanQueueFamilyStatus::Unused
}
}
}
/// Convert a DisplayHandleWrapper Option to a VulkanQueueFamilyStatus as default value
impl From<Option<&DisplayHandleWrapper>> for VulkanQueueFamilyStatus {
fn from(value: Option<&DisplayHandleWrapper>) -> Self {
if value.is_some() {
VulkanQueueFamilyStatus::NotSupported
} else {
VulkanQueueFamilyStatus::Unused
}
}
}
#[derive(Debug)]
pub struct VulkanQueueFamilyIndices {
pub graphics_queue_family_index: VulkanQueueFamilyStatus,
pub compute_queue_family_index: VulkanQueueFamilyStatus,
pub transfer_queue_family_index: VulkanQueueFamilyStatus,
}
impl From<VulkanQueueFamilyIndices> for Vec<(VulkanQueueFamilyStatus, f32)> {
fn from(indices: VulkanQueueFamilyIndices) -> Self {
vec![
(indices.graphics_queue_family_index, 1.0),
(indices.compute_queue_family_index, 0.5),
(indices.transfer_queue_family_index, 0.5),
]
}
}
impl From<VulkanQueueFamilyIndices> for Vec<QueueCreateInfo> {
fn from(indices: VulkanQueueFamilyIndices) -> Self {
let mut queue_create_infos = HashMap::<u32, QueueCreateInfo>::new();
let statuses: Vec<(VulkanQueueFamilyStatus, f32)> = indices.into();
for (status, priority) in statuses.iter() {
match status {
VulkanQueueFamilyStatus::Supported(index) => {
let entry = queue_create_infos.entry(*index).or_insert(QueueCreateInfo {
queue_family_index: *index,
queues: Vec::new(),
..Default::default()
});
entry.queues.push(*priority);
}
_ => {}
}
}
queue_create_infos
.into_iter()
.map(|(_, value)| value)
.collect()
}
}
/// Convert a VulkanQueuesQuery to a VulkanQueuesFamilyIndices as default value
impl<'a> From<&'a VulkanQueuesQuery<'a>> for VulkanQueueFamilyIndices {
fn from(query: &'a VulkanQueuesQuery<'a>) -> Self {
VulkanQueueFamilyIndices {
graphics_queue_family_index: query.with_graphics_queue.into(),
compute_queue_family_index: query.with_compute_queue.into(),
transfer_queue_family_index: query.with_transfer_queue.into(),
}
}
}
pub struct VulkanQueuesQuery<'a> {
pub with_surface: Option<&'a DisplayHandleWrapper>,
pub with_graphics_queue: bool,
pub with_compute_queue: bool,
pub with_transfer_queue: bool,
}
pub fn find_queues_family_indices(
physical_device: &Arc<PhysicalDevice>,
query: &VulkanQueuesQuery,
) -> VulkanQueueFamilyIndices {
let mut indices: VulkanQueueFamilyIndices = query.into();
for (i, queue_family_properties) in physical_device.queue_family_properties().iter().enumerate()
{
let mut available_queue_count = queue_family_properties.queue_count;
if indices.graphics_queue_family_index.can_be_set()
&& check_queue_support(queue_family_properties, QueueFlags::GRAPHICS)
&& available_queue_count > 0
{
if query.with_surface.is_none()
|| check_presentation_support(
physical_device,
i as u32,
&query.with_surface.as_ref().unwrap(),
)
{
indices.graphics_queue_family_index = VulkanQueueFamilyStatus::Supported(i as u32);
available_queue_count -= 1;
}
}
if indices.compute_queue_family_index.can_be_set()
&& check_queue_support(queue_family_properties, QueueFlags::COMPUTE)
&& available_queue_count > 0
{
indices.compute_queue_family_index = VulkanQueueFamilyStatus::Supported(i as u32);
available_queue_count -= 1;
}
if indices.transfer_queue_family_index.can_be_set()
&& check_queue_support(queue_family_properties, QueueFlags::TRANSFER)
&& available_queue_count > 0
{
indices.transfer_queue_family_index = VulkanQueueFamilyStatus::Supported(i as u32);
}
if !indices.graphics_queue_family_index.can_be_set()
&& !indices.compute_queue_family_index.can_be_set()
&& !indices.transfer_queue_family_index.can_be_set()
{
break;
}
}
return indices;
}
fn check_presentation_support(
physical_device: &Arc<PhysicalDevice>,
queue_family_index: u32,
surface: &DisplayHandleWrapper,
) -> bool {
physical_device
.presentation_support(queue_family_index, &surface.0)
.unwrap()
}
fn check_queue_support(
queue_family_property: &QueueFamilyProperties,
queue_flags: QueueFlags,
) -> bool {
queue_family_property.queue_flags.intersects(queue_flags)
}