You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

130 lines
2.8 KiB

use crate::{
hal::ErrSdl,
render::{ensure_properties, Conf, ErrNoProperty},
util::meta,
};
use ash::{
extensions::khr,
version::{EntryV1_0, InstanceV1_0},
vk, vk_make_version, InstanceError,
};
use std::{os::raw::c_char, rc::Rc};
pub struct Instance {
#[allow(dead_code)]
entry: ash::Entry,
handle: ash::Instance,
pub surface_ext: khr::Surface,
}
#[derive(Debug)]
pub enum ErrInstanceCreate {
Vk(vk::Result),
Instance(InstanceError),
NoExtension(ErrNoProperty),
Sdl(ErrSdl),
}
fn enable_instance_layers(
layers: &[*const c_char],
entry: &ash::Entry,
) -> Result<vk::InstanceCreateInfo, ErrInstanceCreate> {
if !layers.is_empty() {
let props = entry.enumerate_instance_layer_properties()?;
ensure_properties(&props, layers, |x| x.layer_name.as_ptr())?;
}
Ok(vk::InstanceCreateInfo {
enabled_layer_count: layers.len() as u32,
pp_enabled_layer_names: layers.as_ptr(),
..Default::default()
})
}
impl Instance {
pub fn create(
conf: &Conf,
entry: ash::Entry,
window: &crate::hal::Window,
) -> Result<Rc<Self>, ErrInstanceCreate> {
let exts = window.vulkan_instance_extensions()?;
let app_info = vk::ApplicationInfo {
p_engine_name: meta::ffi::name(),
api_version: vk_make_version!(1, 0, 0),
..Default::default()
};
let mut layers = Vec::new();
if conf.validation_layers {
layers.push(c_str!("VK_LAYER_KHRONOS_validation"));
}
let create_info = vk::InstanceCreateInfo {
p_application_info: &app_info,
enabled_extension_count: exts.len() as u32,
pp_enabled_extension_names: exts.as_ptr(),
..enable_instance_layers(&layers, &entry)?
};
let handle = unsafe { entry.create_instance(&create_info, None)? };
let surface_ext = khr::Surface::new(&entry, &handle);
Ok(Rc::new(Self { entry, handle, surface_ext }))
}
}
impl Drop for Instance {
fn drop(&mut self) {
unsafe {
self.handle.destroy_instance(None);
}
}
}
impl std::ops::Deref for Instance {
type Target = ash::Instance;
fn deref(&self) -> &Self::Target {
&self.handle
}
}
impl std::fmt::Display for ErrInstanceCreate {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Vk(res) => res.fmt(f),
Self::Instance(err) => err.fmt(f),
Self::NoExtension(err) => write!(f, "Missing extension: {}", err),
Self::Sdl(err) => err.fmt(f),
}
}
}
impl std::error::Error for ErrInstanceCreate {}
impl From<vk::Result> for ErrInstanceCreate {
fn from(res: vk::Result) -> Self {
Self::Vk(res)
}
}
impl From<InstanceError> for ErrInstanceCreate {
fn from(err: InstanceError) -> Self {
Self::Instance(err)
}
}
impl From<ErrNoProperty> for ErrInstanceCreate {
fn from(err: ErrNoProperty) -> Self {
Self::NoExtension(err)
}
}
impl From<ErrSdl> for ErrInstanceCreate {
fn from(err: ErrSdl) -> Self {
Self::Sdl(err)
}
}
// EOF