2023-01-03 16:55:35 +11:00
|
|
|
use ash::vk;
|
2023-01-10 14:54:54 +11:00
|
|
|
use std::ffi::CStr;
|
2023-01-03 16:55:35 +11:00
|
|
|
|
|
|
|
pub struct QueueFamilyIndices {
|
|
|
|
graphics_family: Option<u32>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl QueueFamilyIndices {
|
|
|
|
pub fn is_complete(&self) -> bool {
|
|
|
|
self.graphics_family.is_some()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn graphics_family(&self) -> u32 {
|
|
|
|
self.graphics_family.unwrap()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn pick_physical_device(instance: &ash::Instance) -> vk::PhysicalDevice {
|
|
|
|
let physical_devices = unsafe {
|
|
|
|
instance
|
|
|
|
.enumerate_physical_devices()
|
|
|
|
.expect("Failed to enumerate Physical Devices!")
|
|
|
|
};
|
|
|
|
|
|
|
|
let mut result = None;
|
|
|
|
for &physical_device in physical_devices.iter() {
|
|
|
|
if is_physical_device_suitable(instance, physical_device) {
|
|
|
|
if result.is_none() {
|
|
|
|
result = Some(physical_device)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
match result {
|
|
|
|
None => panic!("Failed to find a suitable GPU!"),
|
|
|
|
Some(physical_device) => physical_device,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn is_physical_device_suitable(
|
|
|
|
instance: &ash::Instance,
|
|
|
|
physical_device: vk::PhysicalDevice,
|
|
|
|
) -> bool {
|
|
|
|
let device_properties = unsafe { instance.get_physical_device_properties(physical_device) };
|
|
|
|
let device_features = unsafe { instance.get_physical_device_features(physical_device) };
|
|
|
|
let device_queue_families =
|
|
|
|
unsafe { instance.get_physical_device_queue_family_properties(physical_device) };
|
|
|
|
|
|
|
|
let device_type = match device_properties.device_type {
|
|
|
|
vk::PhysicalDeviceType::CPU => "Cpu",
|
|
|
|
vk::PhysicalDeviceType::INTEGRATED_GPU => "Integrated GPU",
|
|
|
|
vk::PhysicalDeviceType::DISCRETE_GPU => "Discrete GPU",
|
|
|
|
vk::PhysicalDeviceType::VIRTUAL_GPU => "Virtual GPU",
|
|
|
|
vk::PhysicalDeviceType::OTHER => "Unknown",
|
|
|
|
_ => panic!(),
|
|
|
|
};
|
|
|
|
|
|
|
|
let device_name = unsafe { CStr::from_ptr(device_properties.device_name.as_ptr()) };
|
|
|
|
let device_name = device_name.to_string_lossy();
|
|
|
|
println!(
|
|
|
|
"\tDevice Name: {}, id: {}, type: {}",
|
|
|
|
device_name, device_properties.device_id, device_type
|
|
|
|
);
|
|
|
|
|
2023-01-10 14:54:54 +11:00
|
|
|
println!("\tAPI Version: {}", device_properties.api_version);
|
2023-01-03 16:55:35 +11:00
|
|
|
|
|
|
|
println!("\tSupport Queue Family: {}", device_queue_families.len());
|
|
|
|
println!("\t\tQueue Count | Graphics, Compute, Transfer, Sparse Binding");
|
|
|
|
for queue_family in device_queue_families.iter() {
|
2023-01-10 14:54:54 +11:00
|
|
|
let is_graphics_support = if queue_family.queue_flags.contains(vk::QueueFlags::GRAPHICS) {
|
2023-01-03 16:55:35 +11:00
|
|
|
"support"
|
|
|
|
} else {
|
|
|
|
"unsupport"
|
|
|
|
};
|
|
|
|
let is_compute_support = if queue_family.queue_flags.contains(vk::QueueFlags::COMPUTE) {
|
|
|
|
"support"
|
|
|
|
} else {
|
|
|
|
"unsupport"
|
|
|
|
};
|
2023-01-10 14:54:54 +11:00
|
|
|
let is_transfer_support = if queue_family.queue_flags.contains(vk::QueueFlags::TRANSFER) {
|
2023-01-03 16:55:35 +11:00
|
|
|
"support"
|
|
|
|
} else {
|
|
|
|
"unsupport"
|
|
|
|
};
|
|
|
|
let is_sparse_support = if queue_family
|
|
|
|
.queue_flags
|
|
|
|
.contains(vk::QueueFlags::SPARSE_BINDING)
|
|
|
|
{
|
|
|
|
"support"
|
|
|
|
} else {
|
|
|
|
"unsupport"
|
|
|
|
};
|
|
|
|
|
|
|
|
println!(
|
|
|
|
"\t\t{}\t | {}, {}, {}, {}",
|
|
|
|
queue_family.queue_count,
|
|
|
|
is_graphics_support,
|
|
|
|
is_compute_support,
|
|
|
|
is_transfer_support,
|
|
|
|
is_sparse_support
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
// there are plenty of features
|
|
|
|
println!(
|
|
|
|
"\tGeometry Shader support: {}",
|
|
|
|
if device_features.geometry_shader == 1 {
|
|
|
|
"support"
|
|
|
|
} else {
|
|
|
|
"unsupported"
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
let indices = find_queue_family(instance, physical_device);
|
|
|
|
|
|
|
|
return indices.is_complete();
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn find_queue_family(
|
|
|
|
instance: &ash::Instance,
|
|
|
|
physical_device: vk::PhysicalDevice,
|
|
|
|
) -> QueueFamilyIndices {
|
|
|
|
let queue_families =
|
|
|
|
unsafe { instance.get_physical_device_queue_family_properties(physical_device) };
|
|
|
|
|
|
|
|
let mut queue_family_indices = QueueFamilyIndices {
|
|
|
|
graphics_family: None,
|
|
|
|
};
|
|
|
|
|
|
|
|
let mut index = 0;
|
|
|
|
for queue_family in queue_families.iter() {
|
|
|
|
if queue_family.queue_count > 0
|
|
|
|
&& queue_family.queue_flags.contains(vk::QueueFlags::GRAPHICS)
|
|
|
|
{
|
|
|
|
queue_family_indices.graphics_family = Some(index);
|
|
|
|
}
|
|
|
|
|
|
|
|
if queue_family_indices.is_complete() {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
index += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
queue_family_indices
|
2023-01-10 14:54:54 +11:00
|
|
|
}
|