use super::vulkan_global_api::{proc_loader, read_into_vec};
use crate::IVulkanInstance;
use ash::vk;
use std::ffi::CStr;
use std::ptr;
use std::sync::Arc;
pub struct VulkanInstanceApi {
instance: Arc<dyn IVulkanInstance>,
fp: ash::InstanceFnV1_0,
fp_1_1: ash::InstanceFnV1_1,
device_fp: ash::DeviceFnV1_0,
surface: ash::khr::surface::InstanceFn,
debug_utils: ash::ext::debug_utils::InstanceFn,
}
impl VulkanInstanceApi {
pub fn new(instance: Arc<dyn IVulkanInstance>) -> Self {
let handle = instance.handle();
let lookup = |name: &str| instance.get_instance_proc_address(handle, name);
let fp = ash::InstanceFnV1_0::load(proc_loader(lookup));
let fp_1_1 = ash::InstanceFnV1_1::load(proc_loader(lookup));
let device_fp = ash::DeviceFnV1_0::load(proc_loader(lookup));
let surface = ash::khr::surface::InstanceFn::load(proc_loader(lookup));
let debug_utils = ash::ext::debug_utils::InstanceFn::load(proc_loader(lookup));
Self { instance, fp, fp_1_1, device_fp, surface, debug_utils }
}
pub fn instance(&self) -> &Arc<dyn IVulkanInstance> {
&self.instance
}
pub fn create_debug_utils_messenger_ext(
&self,
instance: vk::Instance,
create_info: &vk::DebugUtilsMessengerCreateInfoEXT<'_>,
) -> Result<vk::DebugUtilsMessengerEXT, vk::Result> {
let mut messenger = vk::DebugUtilsMessengerEXT::null();
let result = unsafe {
(self.debug_utils.create_debug_utils_messenger_ext)(instance, create_info, ptr::null(), &mut messenger)
};
match result {
vk::Result::SUCCESS => Ok(messenger),
error => Err(error),
}
}
pub fn enumerate_physical_devices(&self, instance: vk::Instance) -> Result<Vec<vk::PhysicalDevice>, vk::Result> {
read_into_vec(|count, data| unsafe { (self.fp.enumerate_physical_devices)(instance, count, data) })
}
pub fn get_physical_device_properties(&self, physical_device: vk::PhysicalDevice) -> vk::PhysicalDeviceProperties {
let mut properties = vk::PhysicalDeviceProperties::default();
unsafe { (self.fp.get_physical_device_properties)(physical_device, &mut properties) };
properties
}
pub fn enumerate_device_extension_properties(
&self,
physical_device: vk::PhysicalDevice,
) -> Result<Vec<vk::ExtensionProperties>, vk::Result> {
read_into_vec(|count, data| unsafe {
(self.fp.enumerate_device_extension_properties)(physical_device, ptr::null(), count, data)
})
}
pub fn get_physical_device_surface_support_khr(
&self,
physical_device: vk::PhysicalDevice,
queue_family_index: u32,
surface: vk::SurfaceKHR,
) -> Result<bool, vk::Result> {
let mut supported = vk::FALSE;
let result = unsafe {
(self.surface.get_physical_device_surface_support_khr)(
physical_device,
queue_family_index,
surface,
&mut supported,
)
};
match result {
vk::Result::SUCCESS => Ok(supported != vk::FALSE),
error => Err(error),
}
}
pub fn get_physical_device_queue_family_properties(
&self,
physical_device: vk::PhysicalDevice,
) -> Vec<vk::QueueFamilyProperties> {
read_into_vec(|count, data| unsafe {
(self.fp.get_physical_device_queue_family_properties)(physical_device, count, data);
vk::Result::SUCCESS
})
.unwrap_or_default()
}
pub fn create_device(
&self,
physical_device: vk::PhysicalDevice,
create_info: &vk::DeviceCreateInfo<'_>,
) -> Result<vk::Device, vk::Result> {
let mut device = vk::Device::null();
let result = unsafe { (self.fp.create_device)(physical_device, create_info, ptr::null(), &mut device) };
match result {
vk::Result::SUCCESS => Ok(device),
error => Err(error),
}
}
pub fn destroy_device(&self, device: vk::Device) {
unsafe { (self.device_fp.destroy_device)(device, ptr::null()) };
}
pub fn get_device_queue(&self, device: vk::Device, queue_family_index: u32, queue_index: u32) -> vk::Queue {
let mut queue = vk::Queue::null();
unsafe { (self.device_fp.get_device_queue)(device, queue_family_index, queue_index, &mut queue) };
queue
}
pub fn get_device_proc_addr(&self, device: vk::Device, name: &CStr) -> isize {
let address = unsafe { (self.fp.get_device_proc_addr)(device, name.as_ptr()) };
address.map_or(0, |address| address as usize as isize)
}
pub fn destroy_surface_khr(&self, instance: vk::Instance, surface: vk::SurfaceKHR) {
unsafe { (self.surface.destroy_surface_khr)(instance, surface, ptr::null()) };
}
pub fn get_physical_device_surface_formats_khr(
&self,
physical_device: vk::PhysicalDevice,
surface: vk::SurfaceKHR,
) -> Result<Vec<vk::SurfaceFormatKHR>, vk::Result> {
read_into_vec(|count, data| unsafe {
(self.surface.get_physical_device_surface_formats_khr)(physical_device, surface, count, data)
})
}
pub fn get_physical_device_memory_properties(
&self,
physical_device: vk::PhysicalDevice,
) -> vk::PhysicalDeviceMemoryProperties {
let mut properties = vk::PhysicalDeviceMemoryProperties::default();
unsafe { (self.fp.get_physical_device_memory_properties)(physical_device, &mut properties) };
properties
}
pub fn get_physical_device_surface_capabilities_khr(
&self,
physical_device: vk::PhysicalDevice,
surface: vk::SurfaceKHR,
) -> Result<vk::SurfaceCapabilitiesKHR, vk::Result> {
let mut capabilities = vk::SurfaceCapabilitiesKHR::default();
let result = unsafe {
(self.surface.get_physical_device_surface_capabilities_khr)(physical_device, surface, &mut capabilities)
};
match result {
vk::Result::SUCCESS => Ok(capabilities),
error => Err(error),
}
}
pub fn get_physical_device_surface_present_modes_khr(
&self,
physical_device: vk::PhysicalDevice,
surface: vk::SurfaceKHR,
) -> Result<Vec<vk::PresentModeKHR>, vk::Result> {
read_into_vec(|count, data| unsafe {
(self.surface.get_physical_device_surface_present_modes_khr)(physical_device, surface, count, data)
})
}
pub fn get_physical_device_properties2(
&self,
physical_device: vk::PhysicalDevice,
properties: &mut vk::PhysicalDeviceProperties2<'_>,
) {
unsafe { (self.fp_1_1.get_physical_device_properties2)(physical_device, properties) };
}
}