engine_vulkan: Refactor queue finding
Some checks failed
Build legacy Nix package on Ubuntu / build (push) Failing after 8m39s
Some checks failed
Build legacy Nix package on Ubuntu / build (push) Failing after 8m39s
This commit is contained in:
parent
9ea8721346
commit
4676b1b5b8
5 changed files with 202 additions and 160 deletions
|
@ -1,13 +1,12 @@
|
||||||
use std::{collections::HashMap, sync::Arc};
|
use std::sync::Arc;
|
||||||
|
|
||||||
use bevy_ecs::world::World;
|
use bevy_ecs::world::World;
|
||||||
use engine_window::raw_handle::DisplayHandleWrapper;
|
use engine_window::raw_handle::DisplayHandleWrapper;
|
||||||
use vulkano::{
|
use vulkano::{
|
||||||
VulkanError,
|
|
||||||
command_buffer::allocator::StandardCommandBufferAllocator,
|
command_buffer::allocator::StandardCommandBufferAllocator,
|
||||||
descriptor_set::allocator::StandardDescriptorSetAllocator,
|
descriptor_set::allocator::StandardDescriptorSetAllocator,
|
||||||
device::{
|
device::{
|
||||||
Device, DeviceCreateInfo, DeviceExtensions, Queue, QueueCreateInfo, QueueFlags,
|
Device, DeviceCreateInfo, DeviceExtensions, Queue,
|
||||||
physical::{PhysicalDevice, PhysicalDeviceType},
|
physical::{PhysicalDevice, PhysicalDeviceType},
|
||||||
},
|
},
|
||||||
memory::allocator::StandardMemoryAllocator,
|
memory::allocator::StandardMemoryAllocator,
|
||||||
|
@ -16,6 +15,7 @@ use vulkano::{
|
||||||
use crate::{
|
use crate::{
|
||||||
VulkanCommandBufferAllocator, VulkanComputeQueue, VulkanConfig, VulkanDescriptorSetAllocator,
|
VulkanCommandBufferAllocator, VulkanComputeQueue, VulkanConfig, VulkanDescriptorSetAllocator,
|
||||||
VulkanDevice, VulkanGraphicsQueue, VulkanInstance, VulkanMemoryAllocator, VulkanTransferQueue,
|
VulkanDevice, VulkanGraphicsQueue, VulkanInstance, VulkanMemoryAllocator, VulkanTransferQueue,
|
||||||
|
queues::{VulkanQueueFamilyIndices, VulkanQueuesQuery, find_queues_family_indices},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn create_and_insert_device(world: &mut World, config: &VulkanConfig) {
|
pub fn create_and_insert_device(world: &mut World, config: &VulkanConfig) {
|
||||||
|
@ -101,12 +101,12 @@ fn pick_physical_device(world: &World, config: &VulkanConfig) -> Option<PickedDe
|
||||||
_ => 5,
|
_ => 5,
|
||||||
})
|
})
|
||||||
.take()
|
.take()
|
||||||
.and_then(|(p, (device_extensions, picked_queues_info))| {
|
.and_then(|(p, (device_extensions, queue_family_indices))| {
|
||||||
Some(create_device(
|
Some(create_device(
|
||||||
config,
|
config,
|
||||||
&p,
|
&p,
|
||||||
device_extensions,
|
device_extensions,
|
||||||
&picked_queues_info,
|
queue_family_indices,
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -138,121 +138,11 @@ fn check_device_extensions_support(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PickedQueuesInfo {
|
|
||||||
graphics_queue_family_index: Option<u32>,
|
|
||||||
compute_queue_family_index: Option<u32>,
|
|
||||||
transfer_queue_family_index: Option<u32>,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_queues_support(
|
|
||||||
world: &World,
|
|
||||||
physical_device: &Arc<PhysicalDevice>,
|
|
||||||
config: &VulkanConfig,
|
|
||||||
) -> Option<PickedQueuesInfo> {
|
|
||||||
let mut graphics_queue_family_index: Option<u32> = None;
|
|
||||||
let mut compute_queue_family_index: Option<u32> = None;
|
|
||||||
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 && graphics_queue_family_index.is_none() {
|
|
||||||
let graphics_supported = queue_family_property
|
|
||||||
.queue_flags
|
|
||||||
.intersects(QueueFlags::GRAPHICS);
|
|
||||||
|
|
||||||
let presentation_valid = if config.with_window_surface {
|
|
||||||
let display_handle = world
|
|
||||||
.get_resource::<DisplayHandleWrapper>()
|
|
||||||
.expect("DisplayHandleWrapper must be added before VulkanPlugin");
|
|
||||||
|
|
||||||
physical_device
|
|
||||||
.presentation_support(i as u32, &display_handle.0)
|
|
||||||
.expect("Failed to check presentation support")
|
|
||||||
} else {
|
|
||||||
true
|
|
||||||
};
|
|
||||||
|
|
||||||
if graphics_supported && presentation_valid {
|
|
||||||
graphics_queue_family_index = Some(i as u32);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if config.with_compute_queue && compute_queue_family_index.is_none() {
|
|
||||||
let compute_supported = queue_family_property
|
|
||||||
.queue_flags
|
|
||||||
.intersects(QueueFlags::COMPUTE);
|
|
||||||
|
|
||||||
if compute_supported {
|
|
||||||
compute_queue_family_index = Some(i as u32);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if config.with_transfer_queue && transfer_queue_family_index.is_none() {
|
|
||||||
let transfer_supported = queue_family_property
|
|
||||||
.queue_flags
|
|
||||||
.intersects(QueueFlags::TRANSFER);
|
|
||||||
|
|
||||||
if transfer_supported {
|
|
||||||
transfer_queue_family_index = Some(i as u32);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!config.with_graphics_queue || graphics_queue_family_index.is_some())
|
|
||||||
&& (!config.with_compute_queue || compute_queue_family_index.is_some())
|
|
||||||
&& (!config.with_transfer_queue || transfer_queue_family_index.is_some())
|
|
||||||
{
|
|
||||||
// We found all required queues, no need to continue iterating
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 (family index: {:?})",
|
|
||||||
graphics_queue_family_index
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
log::debug!("\t\t[FAILED] Graphics queue is not supported");
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 (family index: {:?})",
|
|
||||||
compute_queue_family_index
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
log::debug!("\t\t[FAILED] Compute queue is not supported");
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 (family index: {:?})",
|
|
||||||
transfer_queue_family_index
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
log::debug!("\t\t[FAILED] Transfer queue is not supported");
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(PickedQueuesInfo {
|
|
||||||
graphics_queue_family_index,
|
|
||||||
compute_queue_family_index,
|
|
||||||
transfer_queue_family_index,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_physical_device_support(
|
fn check_physical_device_support(
|
||||||
world: &World,
|
world: &World,
|
||||||
physical_device: &Arc<PhysicalDevice>,
|
physical_device: &Arc<PhysicalDevice>,
|
||||||
config: &VulkanConfig,
|
config: &VulkanConfig,
|
||||||
) -> Option<(DeviceExtensions, PickedQueuesInfo)> {
|
) -> Option<(DeviceExtensions, VulkanQueueFamilyIndices)> {
|
||||||
log::debug!("Checking physical device");
|
log::debug!("Checking physical device");
|
||||||
log::debug!("\tProperties");
|
log::debug!("\tProperties");
|
||||||
log::debug!("\t\tName: {}", physical_device.properties().device_name);
|
log::debug!("\t\tName: {}", physical_device.properties().device_name);
|
||||||
|
@ -264,56 +154,34 @@ fn check_physical_device_support(
|
||||||
log::debug!("\tRequired supports checking report");
|
log::debug!("\tRequired supports checking report");
|
||||||
|
|
||||||
let device_extensions = check_device_extensions_support(physical_device, config)?;
|
let device_extensions = check_device_extensions_support(physical_device, config)?;
|
||||||
let picked_queues_info = check_queues_support(world, physical_device, config)?;
|
|
||||||
|
|
||||||
Some((device_extensions, picked_queues_info))
|
let display_handle = world
|
||||||
|
.get_resource::<DisplayHandleWrapper>()
|
||||||
|
.expect("DisplayHandleWrapper must be added before VulkanPlugin");
|
||||||
|
|
||||||
|
let queue_support_query = VulkanQueuesQuery {
|
||||||
|
with_surface: Some(&display_handle),
|
||||||
|
with_graphics_queue: config.with_graphics_queue,
|
||||||
|
with_compute_queue: config.with_compute_queue,
|
||||||
|
with_transfer_queue: config.with_transfer_queue,
|
||||||
|
};
|
||||||
|
|
||||||
|
let queue_family_indices = find_queues_family_indices(physical_device, &queue_support_query);
|
||||||
|
log::debug!("\t\tQueue family indices: {:#?}", queue_family_indices);
|
||||||
|
|
||||||
|
Some((device_extensions, queue_family_indices))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_device(
|
fn create_device(
|
||||||
config: &VulkanConfig,
|
config: &VulkanConfig,
|
||||||
physical_device: &Arc<PhysicalDevice>,
|
physical_device: &Arc<PhysicalDevice>,
|
||||||
device_extensions: DeviceExtensions,
|
device_extensions: DeviceExtensions,
|
||||||
picked_queues_info: &PickedQueuesInfo,
|
queue_family_indices: VulkanQueueFamilyIndices,
|
||||||
) -> PickedDevice {
|
) -> PickedDevice {
|
||||||
let mut queue_create_infos = HashMap::<u32, QueueCreateInfo>::new();
|
|
||||||
|
|
||||||
if config.with_graphics_queue {
|
|
||||||
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 {
|
|
||||||
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 {
|
|
||||||
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(
|
let (device, mut queues) = Device::new(
|
||||||
physical_device.clone(),
|
physical_device.clone(),
|
||||||
DeviceCreateInfo {
|
DeviceCreateInfo {
|
||||||
queue_create_infos: queue_create_infos.values().cloned().collect(),
|
queue_create_infos: queue_family_indices.into(),
|
||||||
enabled_extensions: device_extensions,
|
enabled_extensions: device_extensions,
|
||||||
enabled_features: config.device_features,
|
enabled_features: config.device_features,
|
||||||
..Default::default()
|
..Default::default()
|
|
@ -1,7 +1,7 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use bevy_app::{App, Plugin};
|
||||||
use bevy_ecs::resource::Resource;
|
use bevy_ecs::resource::Resource;
|
||||||
use utils::{device::create_and_insert_device, instance::create_and_insert_instance};
|
|
||||||
use vulkano::{
|
use vulkano::{
|
||||||
command_buffer::allocator::StandardCommandBufferAllocator,
|
command_buffer::allocator::StandardCommandBufferAllocator,
|
||||||
descriptor_set::allocator::StandardDescriptorSetAllocator,
|
descriptor_set::allocator::StandardDescriptorSetAllocator,
|
||||||
|
@ -10,9 +10,11 @@ use vulkano::{
|
||||||
memory::allocator::StandardMemoryAllocator,
|
memory::allocator::StandardMemoryAllocator,
|
||||||
};
|
};
|
||||||
|
|
||||||
use bevy_app::{App, Plugin};
|
mod device;
|
||||||
|
mod instance;
|
||||||
|
mod queues;
|
||||||
|
|
||||||
mod utils;
|
use crate::{device::create_and_insert_device, instance::create_and_insert_instance};
|
||||||
|
|
||||||
#[derive(Resource, Clone)]
|
#[derive(Resource, Clone)]
|
||||||
pub struct VulkanInstance(pub Arc<Instance>);
|
pub struct VulkanInstance(pub Arc<Instance>);
|
||||||
|
|
174
crates/engine_vulkan/src/queues.rs
Normal file
174
crates/engine_vulkan/src/queues.rs
Normal file
|
@ -0,0 +1,174 @@
|
||||||
|
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 present_queue_family_index: VulkanQueueFamilyStatus,
|
||||||
|
pub graphics_queue_family_index: VulkanQueueFamilyStatus,
|
||||||
|
pub compute_queue_family_index: VulkanQueueFamilyStatus,
|
||||||
|
pub transfer_queue_family_index: VulkanQueueFamilyStatus,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<VulkanQueueFamilyIndices> for Vec<VulkanQueueFamilyStatus> {
|
||||||
|
fn from(indices: VulkanQueueFamilyIndices) -> Self {
|
||||||
|
vec![
|
||||||
|
indices.present_queue_family_index,
|
||||||
|
indices.graphics_queue_family_index,
|
||||||
|
indices.compute_queue_family_index,
|
||||||
|
indices.transfer_queue_family_index,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<VulkanQueueFamilyIndices> for Vec<QueueCreateInfo> {
|
||||||
|
fn from(indices: VulkanQueueFamilyIndices) -> Self {
|
||||||
|
let mut queue_create_infos = HashMap::<u32, QueueCreateInfo>::new();
|
||||||
|
|
||||||
|
let statuses: Vec<VulkanQueueFamilyStatus> = indices.into();
|
||||||
|
|
||||||
|
for status in statuses.iter() {
|
||||||
|
match status {
|
||||||
|
VulkanQueueFamilyStatus::Supported(index) => {
|
||||||
|
let entry = queue_create_infos.entry(*index).or_insert(QueueCreateInfo {
|
||||||
|
queue_family_index: *index,
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
|
||||||
|
entry.queues.push(1.0);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
present_queue_family_index: query.with_surface.into(),
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
if indices.present_queue_family_index.can_be_set()
|
||||||
|
&& check_presentation_support(
|
||||||
|
physical_device,
|
||||||
|
i as u32,
|
||||||
|
&query.with_surface.as_ref().unwrap(),
|
||||||
|
)
|
||||||
|
{
|
||||||
|
indices.present_queue_family_index = VulkanQueueFamilyStatus::Supported(i as u32);
|
||||||
|
}
|
||||||
|
|
||||||
|
if indices.graphics_queue_family_index.can_be_set()
|
||||||
|
&& check_queue_support(queue_family_properties, QueueFlags::GRAPHICS)
|
||||||
|
{
|
||||||
|
indices.graphics_queue_family_index = VulkanQueueFamilyStatus::Supported(i as u32);
|
||||||
|
}
|
||||||
|
|
||||||
|
if indices.compute_queue_family_index.can_be_set()
|
||||||
|
&& check_queue_support(queue_family_properties, QueueFlags::COMPUTE)
|
||||||
|
{
|
||||||
|
indices.compute_queue_family_index = VulkanQueueFamilyStatus::Supported(i as u32);
|
||||||
|
}
|
||||||
|
|
||||||
|
if indices.transfer_queue_family_index.can_be_set()
|
||||||
|
&& check_queue_support(queue_family_properties, QueueFlags::TRANSFER)
|
||||||
|
{
|
||||||
|
indices.transfer_queue_family_index = VulkanQueueFamilyStatus::Supported(i as u32);
|
||||||
|
}
|
||||||
|
|
||||||
|
if !indices.present_queue_family_index.can_be_set()
|
||||||
|
&& !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)
|
||||||
|
}
|
|
@ -1,2 +0,0 @@
|
||||||
pub mod device;
|
|
||||||
pub mod instance;
|
|
Loading…
Add table
Add a link
Reference in a new issue