Some checks failed
Build legacy Nix package on Ubuntu / build (push) Failing after 0s
Refactor Vulkan instance and physical device formatting for better clarity. Added formatter utilities to encapsulate version and property formatting. Updated logging to use the new formatted output for improved debug readability.
129 lines
No EOL
3.9 KiB
Rust
129 lines
No EOL
3.9 KiB
Rust
use std::ffi::{c_char, CString};
|
|
use std::fmt::{Debug, Display, Formatter};
|
|
use ash::{Instance, vk, Entry};
|
|
use ash::khr::surface;
|
|
use winit::raw_window_handle::{HasDisplayHandle, HasWindowHandle};
|
|
use crate::vulkan::utils::formatter::format_instance_layer;
|
|
use crate::vulkan::utils::layers::{use_layers, LayersSelector};
|
|
use crate::vulkan::vk_surface::VkSurface;
|
|
use crate::vulkan::VkPhysicalDevice;
|
|
|
|
pub struct VkInstance {
|
|
entry: Entry,
|
|
handle: Instance,
|
|
}
|
|
|
|
impl VkInstance {
|
|
pub fn new(
|
|
required_extensions: &Vec<*const c_char>,
|
|
) -> Self {
|
|
let entry = Entry::linked();
|
|
|
|
// Layers
|
|
let layers = use_layers(
|
|
&entry,
|
|
LayersSelector::SpecificLayers(vec![
|
|
"VK_LAYER_KHRONOS_validation",
|
|
"VK_LAYER_MANGOHUD_overlay_x86_64",
|
|
"VK_LAYER_NV_optimus"
|
|
])
|
|
);
|
|
let layers_raw = layers.iter().map(|s| s.as_ptr()).collect::<Vec<_>>();
|
|
|
|
// App Info
|
|
let app_name = CString::new("VulkanTriangle").unwrap();
|
|
let appinfo = vk::ApplicationInfo::default()
|
|
.application_name(app_name.as_c_str())
|
|
.application_version(0)
|
|
.engine_name(app_name.as_c_str())
|
|
.engine_version(0)
|
|
.api_version(vk::make_api_version(0, 1, 0, 0));
|
|
|
|
let create_flags = if cfg!(any(target_os = "macos", target_os = "ios")) {
|
|
vk::InstanceCreateFlags::ENUMERATE_PORTABILITY_KHR
|
|
} else {
|
|
vk::InstanceCreateFlags::default()
|
|
};
|
|
|
|
// Instance Info
|
|
let create_info = vk::InstanceCreateInfo::default()
|
|
.application_info(&appinfo)
|
|
.enabled_layer_names(&layers_raw)
|
|
.enabled_extension_names(&required_extensions)
|
|
.flags(create_flags);
|
|
|
|
let instance: Instance = unsafe {
|
|
entry
|
|
.create_instance(&create_info, None)
|
|
.expect("Instance creation error")
|
|
};
|
|
|
|
Self {
|
|
entry,
|
|
handle: instance
|
|
}
|
|
}
|
|
|
|
pub fn get_physical_devices(&self) -> Vec<VkPhysicalDevice> {
|
|
let physical_devices = unsafe { self.handle.enumerate_physical_devices() };
|
|
physical_devices
|
|
.unwrap_or_default()
|
|
.iter().map(|physical_device| VkPhysicalDevice::new(&self.handle, *physical_device))
|
|
.collect()
|
|
}
|
|
|
|
pub fn create_surface(
|
|
&self,
|
|
window: &crate::display::Window
|
|
) -> anyhow::Result<VkSurface> {
|
|
let window_handle = window.handle()
|
|
.ok_or_else(|| anyhow::anyhow!("Window handle is not available."))?;
|
|
|
|
let surface_loader = surface::Instance::new(&self.entry, &self.handle);
|
|
|
|
let surface = unsafe {
|
|
ash_window::create_surface(
|
|
&self.entry,
|
|
&self.handle,
|
|
window_handle.display_handle()?.as_raw(),
|
|
window_handle.window_handle()?.as_raw(),
|
|
None,
|
|
)?
|
|
};
|
|
|
|
Ok(VkSurface::new(
|
|
surface_loader,
|
|
surface,
|
|
))
|
|
}
|
|
}
|
|
|
|
impl Drop for VkInstance {
|
|
fn drop(&mut self) {
|
|
unsafe {
|
|
self.handle.destroy_instance(None);
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Display for VkInstance {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
writeln!(f, "")?;
|
|
|
|
let instance_layers = unsafe { self.entry.enumerate_instance_layer_properties().unwrap_or_default() };
|
|
writeln!(f, "Instance layers ({}) :", instance_layers.len())?;
|
|
for instance_layer in &instance_layers {
|
|
writeln!(f, "{}", format_instance_layer(instance_layer))?;
|
|
}
|
|
writeln!(f, "")?;
|
|
|
|
let physical_devices = self.get_physical_devices();
|
|
writeln!(f, "Physical Devices ({}) :", physical_devices.len())?;
|
|
for physical_device in physical_devices {
|
|
writeln!(f, "{physical_device}")?;
|
|
}
|
|
writeln!(f, "")?;
|
|
|
|
Ok(())
|
|
}
|
|
} |