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:
parent
7951b05ab3
commit
18174e42e9
2 changed files with 77 additions and 114 deletions
|
@ -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 {
|
||||
.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()
|
||||
})
|
||||
.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 {
|
||||
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 {
|
||||
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 {
|
||||
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,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,76 +0,0 @@
|
|||
use std::{any::Any, sync::Arc};
|
||||
|
||||
use bevy_app::App;
|
||||
use bevy_ecs::resource::Resource;
|
||||
use engine_window::raw_handle::DisplayHandleWrapper;
|
||||
use vulkano::{
|
||||
command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, PrimaryAutoCommandBuffer,
|
||||
allocator::StandardCommandBufferAllocator,
|
||||
},
|
||||
descriptor_set::allocator::StandardDescriptorSetAllocator,
|
||||
device::{Device, Queue},
|
||||
instance::Instance,
|
||||
memory::allocator::StandardMemoryAllocator,
|
||||
swapchain::Surface,
|
||||
};
|
||||
use winit::raw_window_handle::{HasDisplayHandle, HasWindowHandle};
|
||||
|
||||
use super::utils;
|
||||
|
||||
#[derive(Resource)]
|
||||
pub struct VulkanContext {
|
||||
pub instance: Arc<Instance>,
|
||||
pub device: Arc<Device>,
|
||||
pub graphics_queue: Arc<Queue>,
|
||||
|
||||
pub memory_allocator: Arc<StandardMemoryAllocator>,
|
||||
pub command_buffer_allocator: Arc<StandardCommandBufferAllocator>,
|
||||
pub descriptor_set_allocator: Arc<StandardDescriptorSetAllocator>,
|
||||
}
|
||||
|
||||
impl VulkanContext {
|
||||
pub fn create_surface(
|
||||
&self,
|
||||
window: Arc<impl HasWindowHandle + HasDisplayHandle + Any + Send + Sync>,
|
||||
) -> Arc<Surface> {
|
||||
Surface::from_window(self.instance.clone(), window).unwrap()
|
||||
}
|
||||
|
||||
pub fn create_render_builder(&self) -> AutoCommandBufferBuilder<PrimaryAutoCommandBuffer> {
|
||||
AutoCommandBufferBuilder::primary(
|
||||
self.command_buffer_allocator.clone(),
|
||||
self.graphics_queue.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&App> for VulkanContext {
|
||||
fn from(app: &App) -> Self {
|
||||
let (device, mut queues) = utils::pick_graphics_device(&instance, &display_handle.0);
|
||||
let graphics_queue = queues.next().unwrap();
|
||||
|
||||
let memory_allocator = Arc::new(StandardMemoryAllocator::new_default(device.clone()));
|
||||
|
||||
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
|
||||
let descriptor_set_allocator = Arc::new(StandardDescriptorSetAllocator::new(
|
||||
device.clone(),
|
||||
Default::default(),
|
||||
));
|
||||
|
||||
Self {
|
||||
instance: instance.clone(),
|
||||
device,
|
||||
graphics_queue,
|
||||
memory_allocator,
|
||||
command_buffer_allocator,
|
||||
descriptor_set_allocator,
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue