render_vulkan: Fixes

- Avoid create device for each physical device during support checking
- Avoid to select different queue family index and add support of creating multiple queues on same queue family
- Log select queue family index for each queue type
This commit is contained in:
Florian RICHER 2025-05-21 13:42:36 +02:00
parent 7951b05ab3
commit 18174e42e9
Signed by: florian.richer
GPG key ID: C73D37CBED7BFC77
2 changed files with 77 additions and 114 deletions

View file

@ -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<PickedDe
.get_resource::<VulkanInstance>()
.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<u32> = 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<PhysicalDevice>,
config: &VulkanConfig,
) -> Option<PickedDevice> {
) -> 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<PhysicalDevice>,
device_extensions: DeviceExtensions,
picked_queues_info: &PickedQueuesInfo,
) -> PickedDevice {
let mut queue_create_infos = HashMap::<u32, QueueCreateInfo>::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,
})
}
}