use crate::*;
use alloc::sync::Arc;
use alloc::vec::Vec;
use core::ffi::CStr;
use sys::loader;
#[derive(Debug, Clone)]
pub struct Vulkan {
sys: Arc<loader::Vulkan>,
}
impl Vulkan {
pub unsafe fn new() -> core::result::Result<Self, loader::LoadingError> {
Ok(Self {
sys: unsafe { loader::Vulkan::new()? },
})
}
pub fn from_sys(sys: Arc<loader::Vulkan>) -> core::result::Result<Self, loader::LoadingError> {
Ok(Self { sys })
}
pub unsafe fn from_vkGetInstanceProcAddr(
vkGetInstanceProcAddr: sys::FN_vkGetInstanceProcAddr,
) -> core::result::Result<Self, loader::LoadingError> {
Ok(Self {
sys: unsafe {
loader::Vulkan::from_entry(loader::Entry::from_vkGetInstanceProcAddr(
vkGetInstanceProcAddr,
))?
},
})
}
pub fn sys(&self) -> &Arc<loader::Vulkan> {
&self.sys
}
}
#[cfg(feature = "linked")]
#[cfg_attr(docsrs, doc(cfg(feature = "linked")))]
impl Vulkan {
pub fn linked() -> core::result::Result<Self, loader::LoadingError> {
Ok(Self {
sys: unsafe { loader::Vulkan::from_entry(loader::Entry::linked())? },
})
}
}
#[cfg(feature = "loaded")]
#[cfg_attr(docsrs, doc(cfg(feature = "loaded")))]
impl Vulkan {
pub fn load() -> core::result::Result<Self, loader::LoadingError> {
Ok(Self {
sys: unsafe { loader::Vulkan::from_entry(loader::Entry::load()?)? },
})
}
pub fn load_from(
path: impl libloading::AsFilename,
) -> core::result::Result<Self, loader::LoadingError> {
Ok(Self {
sys: unsafe { loader::Vulkan::from_entry(loader::Entry::load_from(path)?)? },
})
}
}
impl Vulkan {
pub unsafe fn get_instance_proc_addr<'a>(
&self,
inst: Option<vk::Instance>,
name: &CStr,
) -> Option<ProcAddr> {
unsafe { self.sys.GetInstanceProcAddr(inst.sys(), name.as_ptr()) }
}
pub unsafe fn enumerate_instance_version(&self) -> Result<u32> {
unsafe {
let mut version = 0;
self.sys
.EnumerateInstanceVersion(&mut version)
.vk()
.result(|| Some(version))
}
}
pub unsafe fn enumerate_instance_extension_properties(
&self,
layer_name: Option<&CStr>,
properties: Option<&mut Vec<vk::ExtensionProperties>>,
) -> Result<(u32, vk::Result)> {
unsafe {
let p_layer_name = layer_name.map(|a| a.as_ptr()).unwrap_or_default();
let mut len = 0;
self.sys
.EnumerateInstanceExtensionProperties(p_layer_name, &mut len, core::ptr::null_mut())
.vk()
.result_multi(|| Some(()))?;
if let Some(properties) = properties {
properties.reserve(len as usize);
let start = properties.as_mut_ptr().add(properties.len()).cast();
let r = self
.sys
.EnumerateInstanceExtensionProperties(p_layer_name, &mut len, start)
.vk()
.result_multi(|| Some(len))?;
properties.set_len(properties.len() + r.0 as usize);
Ok(r)
} else {
Ok((len, vk::Result::Success))
}
}
}
pub unsafe fn enumerate_instance_layer_properties(
&self,
properties: Option<&mut Vec<vk::LayerProperties>>,
) -> Result<(u32, vk::Result)> {
unsafe {
let mut len = 0;
self.sys
.EnumerateInstanceLayerProperties(&mut len, core::ptr::null_mut())
.vk()
.result_multi(|| Some(()))?;
if let Some(properties) = properties {
properties.reserve(len as usize);
let start = properties.as_mut_ptr().add(properties.len()).cast();
let r = self
.sys
.EnumerateInstanceLayerProperties(&mut len, start)
.vk()
.result_multi(|| Some(len))?;
properties.set_len(properties.len() + r.0 as usize);
Ok(r)
} else {
Ok((len, vk::Result::Success))
}
}
}
pub unsafe fn create_instance(
&'_ self,
create_info: &vk::InstanceCreateInfo,
) -> Result<vk::Instance> {
unsafe {
let mut instance = sys::VkInstance::null();
self.sys
.CreateInstance(create_info.abi(), Default::default(), &mut instance)
.vk()
.result(|| instance.vk())
}
}
}