Add window surface, fix rendering of logical device on mac

This commit is contained in:
Timothy Warren 2023-04-05 15:41:32 -04:00
parent 9713441c2e
commit 2c5928dac4
3 changed files with 71 additions and 10 deletions

View File

@ -14,5 +14,5 @@ png = "0.17"
pretty_env_logger = "0.4"
thiserror = "1"
tobj = { version = "3", features = ["log"] }
vulkanalia = { version = "=0.16.0", features = ["libloading", "window"] }
vulkanalia = { version = "=0.16.0", features = ["libloading", "window", "provisional"] }
winit = "0.27"

View File

@ -8,6 +8,8 @@ use ::thiserror::Error;
use ::vulkanalia::loader::{LibloadingLoader, LIBRARY};
use ::vulkanalia::prelude::v1_0::*;
use ::vulkanalia::vk::ExtDebugUtilsExtension;
use ::vulkanalia::vk::KhrSurfaceExtension;
use ::vulkanalia::window as vk_window;
use ::winit::window::Window;
/// Our Vulkan app.
@ -26,6 +28,7 @@ impl App {
let entry = Entry::new(loader).map_err(|b| anyhow!("{}", b))?;
let mut data = AppData::default();
let instance = create_instance(window, &entry, &mut data)?;
data.surface = vk_window::create_surface(&instance, window)?;
pick_physical_device(&instance, &mut data)?;
let device = create_logical_device(&instance, &mut data)?;
@ -51,6 +54,7 @@ impl App {
.destroy_debug_utils_messenger_ext(self.data.messenger, None);
}
self.instance.destroy_surface_khr(self.data.surface, None);
self.instance.destroy_instance(None);
}
}
@ -58,9 +62,13 @@ impl App {
/// The Vulkan handles and associated properties used by our Vulkan app.
#[derive(Clone, Debug, Default)]
pub struct AppData {
surface: vk::SurfaceKHR,
// Debug
messenger: vk::DebugUtilsMessengerEXT,
// Physical Device / Logical Device
physical_device: vk::PhysicalDevice,
graphics_queue: vk::Queue,
present_queue: vk::Queue,
}
#[derive(Debug, Error)]
@ -70,6 +78,7 @@ pub struct SuitabilityError(pub &'static str);
#[derive(Copy, Clone, Debug)]
pub(crate) struct QueueFamilyIndicies {
graphics: u32,
present: u32,
}
impl QueueFamilyIndicies {
@ -85,8 +94,20 @@ impl QueueFamilyIndicies {
.position(|p| p.queue_flags.contains(vk::QueueFlags::GRAPHICS))
.map(|i| i as u32);
if let Some(graphics) = graphics {
Ok(Self { graphics })
let mut present = None;
for (index, properties) in properties.iter().enumerate() {
if instance.get_physical_device_surface_support_khr(
physical_device,
index as u32,
data.surface,
)? {
present = Some(index as u32);
break;
}
}
if let (Some(graphics), Some(present)) = (graphics, present) {
Ok(Self { graphics, present })
} else {
Err(anyhow!(SuitabilityError(
"Missing required queue families."

View File

@ -37,6 +37,7 @@ pub(super) unsafe fn create_instance(
entry: &Entry,
data: &mut AppData,
) -> Result<Instance> {
// Application Info
let application_info = vk::ApplicationInfo::builder()
.application_name(b"Vulkan Tutorial\0")
.application_version(vk::make_version(1, 0, 0))
@ -44,6 +45,7 @@ pub(super) unsafe fn create_instance(
.engine_version(vk::make_version(1, 0, 0))
.api_version(vk::make_version(1, 0, 0));
// Layers
let available_layers = entry
.enumerate_instance_layer_properties()?
.iter()
@ -60,6 +62,7 @@ pub(super) unsafe fn create_instance(
Vec::new()
};
// Extensions
let mut extensions = vk_window::get_required_instance_extensions(window)
.iter()
.map(|e| e.as_ptr())
@ -75,11 +78,17 @@ pub(super) unsafe fn create_instance(
.any(|e| e.extension_name == vk::KHR_PORTABILITY_ENUMERATION_EXTENSION.name)
{
extensions.push(vk::KHR_PORTABILITY_ENUMERATION_EXTENSION.name.as_ptr());
extensions.push(
vk::KHR_GET_PHYSICAL_DEVICE_PROPERTIES2_EXTENSION
.name
.as_ptr(),
);
vk::InstanceCreateFlags::ENUMERATE_PORTABILITY_KHR
} else {
vk::InstanceCreateFlags::empty()
};
// Create
let mut info = vk::InstanceCreateInfo::builder()
.application_info(&application_info)
.enabled_layer_names(&layers)
@ -97,6 +106,11 @@ pub(super) unsafe fn create_instance(
let instance = entry.create_instance(&info, None)?;
// Messenger
if VALIDATION_ENABLED {
data.messenger = instance.create_debug_utils_messenger_ext(&debug_info, None)?;
}
Ok(instance)
}
@ -133,30 +147,56 @@ pub(super) unsafe fn create_logical_device(
instance: &Instance,
data: &mut AppData,
) -> Result<Device> {
// Queue Create Infos
let indices = QueueFamilyIndicies::get(instance, data, data.physical_device)?;
let queue_priorities = &[1.0];
let queue_info = vk::DeviceQueueCreateInfo::builder()
.queue_family_index(indices.graphics)
.queue_priorities(queue_priorities);
let mut unique_indices = HashSet::new();
unique_indices.insert(indices.graphics);
unique_indices.insert(indices.present);
let queue_priorities = &[1.0];
let queue_infos = unique_indices
.iter()
.map(|i| {
vk::DeviceQueueCreateInfo::builder()
.queue_family_index(*i)
.queue_priorities(queue_priorities)
})
.collect::<Vec<_>>();
// Layers
let layers = if VALIDATION_ENABLED {
vec![VALIDATION_LAYER.as_ptr()]
} else {
vec![]
};
// Extensions
let extension_names = if instance
.enumerate_device_extension_properties(data.physical_device, None)?
.iter()
.any(|e| e.extension_name == vk::KHR_PORTABILITY_SUBSET_EXTENSION.name)
{
vec![vk::KHR_PORTABILITY_SUBSET_EXTENSION.name.as_ptr()]
} else {
vec![]
};
// Features
let features = vk::PhysicalDeviceFeatures::builder();
let queue_infos = &[queue_info];
// Create
let info = vk::DeviceCreateInfo::builder()
.queue_create_infos(queue_infos)
.queue_create_infos(&queue_infos)
.enabled_layer_names(&layers)
.enabled_features(&features);
.enabled_features(&features)
.enabled_extension_names(&extension_names);
let device = instance.create_device(data.physical_device, &info, None)?;
// Queues
data.graphics_queue = device.get_device_queue(indices.graphics, 0);
data.present_queue = device.get_device_queue(indices.present, 0);
Ok(device)
}