173 lines
5.3 KiB
Rust
173 lines
5.3 KiB
Rust
use std::{
|
|
ffi::{CStr, CString},
|
|
sync::Arc,
|
|
};
|
|
|
|
use ash::{Entry, ext, vk};
|
|
use raw_window_handle::RawDisplayHandle;
|
|
|
|
use crate::{
|
|
device::{Extension, get_extensions, get_layers},
|
|
make_extension,
|
|
};
|
|
|
|
pub struct DebugUtilsCreateInfo {
|
|
pub severity: vk::DebugUtilsMessageSeverityFlagsEXT,
|
|
pub message_type: vk::DebugUtilsMessageTypeFlagsEXT,
|
|
}
|
|
|
|
pub struct InstanceInner {
|
|
pub raw: ash::Instance,
|
|
pub entry: Entry,
|
|
pub(crate) _debug_utils: DebugUtils,
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub struct Instance {
|
|
pub(crate) inner: Arc<InstanceInner>,
|
|
}
|
|
|
|
impl core::fmt::Debug for Instance {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
f.debug_struct("Instance")
|
|
.field("raw", &self.inner.raw.handle())
|
|
.finish_non_exhaustive()
|
|
}
|
|
}
|
|
|
|
pub struct InstanceDesc<'a> {
|
|
pub app_name: Option<&'a str>,
|
|
pub app_version: u32,
|
|
pub instance_extensions: &'a [&'a CStr],
|
|
pub layer_settings: &'a [vk::LayerSettingEXT<'a>],
|
|
pub layers: &'a [&'a CStr],
|
|
pub display_handle: Option<RawDisplayHandle>,
|
|
}
|
|
|
|
impl Instance {
|
|
pub fn new<'a>(desc: &InstanceDesc<'a>) -> crate::Result<Self> {
|
|
let entry = unsafe { ash::Entry::load()? };
|
|
|
|
let app_name = desc
|
|
.app_name
|
|
.and_then(|name| CString::new(name).ok())
|
|
.unwrap_or(c"ShooterGame".to_owned());
|
|
|
|
let version =
|
|
unsafe { entry.try_enumerate_instance_version()? }.unwrap_or(vk::API_VERSION_1_0);
|
|
|
|
let app_info = vk::ApplicationInfo::default()
|
|
.api_version(if version < vk::API_VERSION_1_1 {
|
|
vk::API_VERSION_1_0
|
|
} else {
|
|
// ash doesn't support 1.4 yet
|
|
vk::API_VERSION_1_3
|
|
})
|
|
.application_name(&app_name)
|
|
.application_version(desc.app_version)
|
|
.engine_name(c"Bevy Engine")
|
|
.engine_version(vk::make_api_version(0, 0, 1, 0));
|
|
|
|
let mut validation_info =
|
|
vk::LayerSettingsCreateInfoEXT::default().settings(desc.layer_settings);
|
|
|
|
let layers = match get_layers(&entry, desc.layers.to_vec()) {
|
|
Ok(layers) => layers,
|
|
Err((supported, unsupported)) => {
|
|
tracing::error!(
|
|
"Some requested layers were not supported by instance:\nSupported: {:?}\nUnsupported: {:?}",
|
|
supported,
|
|
unsupported
|
|
);
|
|
supported
|
|
}
|
|
};
|
|
|
|
let mut requested_extensions = desc
|
|
.instance_extensions
|
|
.iter()
|
|
.map(|name| Extension { name, version: 0 })
|
|
.collect::<Vec<_>>();
|
|
|
|
requested_extensions.push(make_extension!(ext::debug_utils as 1));
|
|
#[cfg(debug_assertions)]
|
|
requested_extensions.push(make_extension!(ext::layer_settings));
|
|
|
|
let (extensions, unsupported_extensions) =
|
|
get_extensions(&entry, &layers, requested_extensions, desc.display_handle)?;
|
|
|
|
if !unsupported_extensions.is_empty() {
|
|
tracing::error!(
|
|
"extensions were requested but not supported by instance: {:?}",
|
|
unsupported_extensions
|
|
);
|
|
}
|
|
|
|
let layers = layers
|
|
.iter()
|
|
.map(|layer| layer.as_ptr())
|
|
.collect::<Vec<_>>();
|
|
let extensions = extensions
|
|
.iter()
|
|
.map(|ext| ext.name.as_ptr())
|
|
.collect::<Vec<_>>();
|
|
|
|
let create_info = vk::InstanceCreateInfo::default()
|
|
.application_info(&app_info)
|
|
.enabled_extension_names(&extensions)
|
|
.enabled_layer_names(&layers)
|
|
.push_next(&mut validation_info);
|
|
|
|
tracing::debug!(
|
|
"Creating instance:\napp_info: {app_info:#?}\ncreate_info: {create_info:#?}"
|
|
);
|
|
|
|
let instance = unsafe { entry.create_instance(&create_info, None)? };
|
|
|
|
let debug_utils = {
|
|
let debug_info = vk::DebugUtilsMessengerCreateInfoEXT::default()
|
|
.message_severity(
|
|
vk::DebugUtilsMessageSeverityFlagsEXT::ERROR
|
|
| vk::DebugUtilsMessageSeverityFlagsEXT::WARNING
|
|
| vk::DebugUtilsMessageSeverityFlagsEXT::INFO,
|
|
)
|
|
.message_type(
|
|
vk::DebugUtilsMessageTypeFlagsEXT::GENERAL
|
|
| vk::DebugUtilsMessageTypeFlagsEXT::VALIDATION
|
|
| vk::DebugUtilsMessageTypeFlagsEXT::PERFORMANCE,
|
|
)
|
|
.pfn_user_callback(Some(crate::debug::debug_callback));
|
|
|
|
let instance = ext::debug_utils::Instance::new(&entry, &instance);
|
|
let messenger = unsafe { instance.create_debug_utils_messenger(&debug_info, None)? };
|
|
|
|
crate::DebugUtils {
|
|
instance,
|
|
messenger,
|
|
}
|
|
};
|
|
|
|
let instance = Arc::new(InstanceInner {
|
|
raw: instance,
|
|
_debug_utils: debug_utils,
|
|
entry,
|
|
});
|
|
|
|
Ok(Self { inner: instance })
|
|
}
|
|
}
|
|
|
|
pub(crate) struct DebugUtils {
|
|
pub instance: ext::debug_utils::Instance,
|
|
pub messenger: vk::DebugUtilsMessengerEXT,
|
|
}
|
|
|
|
impl Drop for DebugUtils {
|
|
fn drop(&mut self) {
|
|
unsafe {
|
|
self.instance
|
|
.destroy_debug_utils_messenger(self.messenger, None);
|
|
}
|
|
}
|
|
}
|