#![cfg_attr(not(feature = "Implements"), allow(dead_code))]
use vk::*;
use std::ffi::CString;
use VkHandle;
#[cfg(feature = "Implements")] use VkResultHandler;
#[cfg(feature = "Implements")] use std::ptr::{null, null_mut};
#[cfg( feature = "Multithreaded") ] use std::sync::Arc as RefCounter;
#[cfg(not(feature = "Multithreaded"))] use std::rc::Rc as RefCounter;
#[cfg(not(feature = "Multithreaded"))] struct LazyCell<T>(::std::cell::RefCell<Option<T>>);
#[cfg(feature = "Multithreaded")] struct LazyCell<T>(::std::sync::RwLock<Option<T>>);
impl<T> LazyCell<T>
{
pub fn new() -> Self
{
#[cfg(feature = "Multithreaded")] { LazyCell(::std::sync::RwLock::new(None)) }
#[cfg(not(feature = "Multithreaded"))] { LazyCell(::std::cell::RefCell::new(None)) }
}
#[cfg(not(feature = "Multithreaded"))]
pub fn get<F: FnOnce() -> T>(&self, initializer: F) -> ::std::cell::Ref<T>
{
if self.0.borrow().is_none() { *self.0.borrow_mut() = Some(initializer()); }
::std::cell::Ref::map(self.0.borrow(), |o| o.as_ref().unwrap())
}
#[cfg(feature = "Multithreaded")]
pub fn get<F: FnOnce() -> T>(&self, initializer: F) -> ::std::sync::RwLockReadGuard<T>
{
if self.0.read().is_none() { *self.0.write() = Some(initializer()); }
::std::sync::RwLockReadGuard::map(self.0.read(), |o| o.as_ref().unwrap())
}
}
struct InstanceCell
{
n: VkInstance, vk_create_descriptor_update_template: LazyCell<PFN_vkCreateDescriptorUpdateTemplate>,
vk_destroy_descriptor_update_template: LazyCell<PFN_vkDestroyDescriptorUpdateTemplate>
}
#[derive(Clone)] pub struct Instance(RefCounter<InstanceCell>);
#[cfg(feature = "Multithreaded")] unsafe impl Sync for Instance {}
pub struct PhysicalDevice(VkPhysicalDevice, Instance);
pub struct IterPhysicalDevices<'i>(Vec<VkPhysicalDevice>, usize, &'i Instance);
impl<'i> Iterator for IterPhysicalDevices<'i>
{
type Item = PhysicalDevice;
fn next(&mut self) -> Option<PhysicalDevice>
{
if self.0.len() <= self.1 { None }
else { self.1 += 1; Some(PhysicalDevice(self.0[self.1 - 1], self.2.clone())) }
}
fn size_hint(&self) -> (usize, Option<usize>) { (self.0.len(), Some(self.0.len())) }
}
impl<'i> ExactSizeIterator for IterPhysicalDevices<'i>
{
fn len(&self) -> usize { self.0.len() }
}
impl<'i> DoubleEndedIterator for IterPhysicalDevices<'i>
{
fn next_back(&mut self) -> Option<PhysicalDevice>
{
if self.0.len() <= self.1 { None } else { self.0.pop().map(|p| PhysicalDevice(p, self.2.clone())) }
}
}
#[cfg(feature = "Implements")]
impl Drop for InstanceCell { fn drop(&mut self) { unsafe { vkDestroyInstance(self.n, ::std::ptr::null()); } } }
impl VkHandle for Instance { type Handle = VkInstance; fn native_ptr(&self) -> VkInstance { self.0.n } }
impl VkHandle for PhysicalDevice { type Handle = VkPhysicalDevice; fn native_ptr(&self) -> VkPhysicalDevice { self.0 } }
pub struct InstanceBuilder
{
app_name: CString, engine_name: CString, extensions: Vec<CString>, layers: Vec<CString>,
appinfo: VkApplicationInfo, cinfo: VkInstanceCreateInfo
}
impl InstanceBuilder
{
pub fn new(app_name: &str, app_version: (u32, u32, u32), engine_name: &str, engine_version: (u32, u32, u32)) -> Self
{
InstanceBuilder
{
app_name: CString::new(app_name).unwrap(), engine_name: CString::new(engine_name).unwrap(),
extensions: Vec::new(), layers: Vec::new(), appinfo: VkApplicationInfo
{
applicationVersion: VK_MAKE_VERSION!(app_version.0, app_version.1, app_version.2),
engineVersion: VK_MAKE_VERSION!(engine_version.0, engine_version.1, engine_version.2),
.. Default::default()
}, cinfo: VkInstanceCreateInfo { .. Default::default() }
}
}
pub fn add_extension(&mut self, extension: &str) -> &mut Self
{
self.extensions.push(CString::new(extension).unwrap()); self
}
pub fn add_extension_zerotermed(&mut self, extension: &str) -> &mut Self
{
self.extensions.push(unsafe { ::std::ffi::CStr::from_ptr(extension.as_ptr() as *const _) }.to_owned()); self
}
pub fn add_extensions<'s, Extensions: IntoIterator<Item = &'s str>>(&mut self, extensions: Extensions) -> &mut Self
{
for ex in extensions { self.add_extension(ex); } self
}
pub fn add_layer(&mut self, layer: &str) -> &mut Self
{
self.layers.push(CString::new(layer).unwrap()); self
}
pub fn add_layers<'s, Layers: IntoIterator<Item = &'s str>>(&mut self, layers: Layers) -> &mut Self
{
for l in layers { self.add_layer(l); } self
}
#[cfg(feature = "Implements")]
pub fn create(&mut self) -> ::Result<Instance>
{
let layers: Vec<_> = self.layers.iter().map(|x| x.as_ptr()).collect();
let extensions: Vec<_> = self.extensions.iter().map(|x| x.as_ptr()).collect();
self.appinfo.pApplicationName = self.app_name.as_ptr(); self.appinfo.pEngineName = self.engine_name.as_ptr();
self.cinfo.enabledLayerCount = layers.len() as _; self.cinfo.ppEnabledLayerNames = layers.as_ptr();
self.cinfo.enabledExtensionCount = extensions.len() as _; self.cinfo.ppEnabledExtensionNames = extensions.as_ptr();
self.cinfo.pApplicationInfo = &self.appinfo;
let mut h = VK_NULL_HANDLE as _;
unsafe { vkCreateInstance(&self.cinfo, ::std::ptr::null(), &mut h) }.into_result().map(|_| Instance(RefCounter::new(InstanceCell
{
n: h, vk_create_descriptor_update_template: LazyCell::new(), vk_destroy_descriptor_update_template: LazyCell::new()
})))
}
}
#[cfg(feature = "Implements")]
impl Instance
{
pub fn extra_procedure<F: ::fnconv::FnTransmute>(&self, name: &str) -> Option<F>
{
if name.is_empty() { None }
else
{
let p = unsafe { vkGetInstanceProcAddr(self.native_ptr(), CString::new(name).unwrap().as_ptr()) };
p.map(|f| unsafe { ::fnconv::FnTransmute::from_fn(f) })
}
}
pub fn enumerate_physical_devices(&self) -> ::Result<Vec<PhysicalDevice>>
{
self.iter_physical_devices().map(|iter| iter.collect())
}
pub fn iter_physical_devices(&self) -> ::Result<IterPhysicalDevices>
{
let mut n = 0;
unsafe { vkEnumeratePhysicalDevices(self.native_ptr(), &mut n, null_mut()).into_result()?; }
let mut v = Vec::with_capacity(n as _); unsafe { v.set_len(n as _); }
unsafe { vkEnumeratePhysicalDevices(self.native_ptr(), &mut n, v.as_mut_ptr()).into_result()?; }
Ok(IterPhysicalDevices(v, 0, self))
}
pub fn enumerate_layer_properties() -> ::Result<Vec<VkLayerProperties>>
{
let mut n = 0;
unsafe { vkEnumerateInstanceLayerProperties(&mut n, null_mut()) }.into_result()?;
let mut v = Vec::with_capacity(n as _); unsafe { v.set_len(n as _) };
unsafe { vkEnumerateInstanceLayerProperties(&mut n, v.as_mut_ptr()) }.into_result().map(|_| v)
}
pub fn enumerate_extension_properties(layer_name: Option<&str>) -> ::Result<Vec<VkExtensionProperties>>
{
let cn = layer_name.map(|s| CString::new(s).unwrap());
let cptr = cn.as_ref().map(|s| s.as_ptr()).unwrap_or(null());
let mut n = 0;
unsafe { vkEnumerateInstanceExtensionProperties(cptr, &mut n, null_mut()) }.into_result()?;
let mut v = Vec::with_capacity(n as _); unsafe { v.set_len(n as _) };
unsafe { vkEnumerateInstanceExtensionProperties(cptr, &mut n, v.as_mut_ptr()) }.into_result().map(|_| v)
}
}
#[cfg(feature = "Implements")]
impl Instance
{
pub(crate) unsafe fn create_descriptor_update_template(&self, device: VkDevice, info: &VkDescriptorUpdateTemplateCreateInfo,
alloc: *const VkAllocationCallbacks, handle: &mut VkDescriptorUpdateTemplate) -> VkResult
{
let f = self.0.vk_create_descriptor_update_template
.get(|| self.extra_procedure("vkCreateDescriptorUpdateTemplate").unwrap());
f(device, info, alloc, handle)
}
pub(crate) unsafe fn destroy_descriptor_update_template(&self, device: VkDevice, handle: VkDescriptorUpdateTemplate,
alloc: *const VkAllocationCallbacks)
{
let f = self.0.vk_destroy_descriptor_update_template
.get(|| self.extra_procedure("vkDestroyDescriptorUpdateTemplate").unwrap());
f(device, handle, alloc)
}
}
#[cfg(feature = "Implements")]
impl PhysicalDevice
{
pub fn parent(&self) -> &Instance { &self.1 }
pub fn features(&self) -> VkPhysicalDeviceFeatures
{
let mut p = unsafe { ::std::mem::uninitialized() };
unsafe { vkGetPhysicalDeviceFeatures(self.0, &mut p) }; p
}
pub fn format_properties(&self, format: VkFormat) -> VkFormatProperties
{
let mut p = unsafe { ::std::mem::uninitialized() };
unsafe { vkGetPhysicalDeviceFormatProperties(self.0, format, &mut p) }; p
}
pub fn image_format_properties(&self, format: VkFormat, itype: VkImageType, tiling: VkImageTiling,
usage: ::ImageUsage, flags: ::ImageFlags) -> ::Result<VkImageFormatProperties>
{
let mut p = unsafe { ::std::mem::uninitialized() };
unsafe { vkGetPhysicalDeviceImageFormatProperties(self.0, format, itype, tiling, usage.0, flags.0, &mut p) }
.into_result().map(|_| p)
}
pub fn properties(&self) -> VkPhysicalDeviceProperties
{
let mut p = unsafe { ::std::mem::uninitialized() };
unsafe { vkGetPhysicalDeviceProperties(self.0, &mut p) }; p
}
pub fn queue_family_properties(&self) -> ::QueueFamilies
{
let mut n = 0;
unsafe { vkGetPhysicalDeviceQueueFamilyProperties(self.0, &mut n, null_mut()) };
let mut v = Vec::with_capacity(n as _); unsafe { v.set_len(n as _) };
unsafe { vkGetPhysicalDeviceQueueFamilyProperties(self.0, &mut n, v.as_mut_ptr()) }; ::QueueFamilies(v)
}
pub fn memory_properties(&self) -> MemoryProperties
{
let mut p = unsafe { ::std::mem::uninitialized() };
unsafe { vkGetPhysicalDeviceMemoryProperties(self.0, &mut p) }; MemoryProperties(p)
}
pub fn sparse_image_format_properties(&self, format: VkFormat, itype: VkImageType, samples: VkSampleCountFlags,
usage: ::ImageUsage, tiling: VkImageTiling) -> Vec<VkSparseImageFormatProperties>
{
let mut n = 0;
unsafe { vkGetPhysicalDeviceSparseImageFormatProperties(self.0, format, itype, samples, usage.0, tiling, &mut n, ::std::ptr::null_mut()) };
let mut v = Vec::with_capacity(n as _); unsafe { v.set_len(n as _) };
unsafe { vkGetPhysicalDeviceSparseImageFormatProperties(self.0, format, itype, samples, usage.0, tiling, &mut n, v.as_mut_ptr()) };
v
}
#[cfg(feature = "VK_EXT_sample_locations")]
pub fn multisample_properties(&self, samples: VkSampleCountFlags) -> VkMultisamplePropertiesEXT
{
let mut r = unsafe { ::std::mem::uninitialized() };
unsafe { vkGetPhysicalDeviceMultisamplePropertiesEXT(self.0, samples, &mut r) };
return r;
}
}
#[cfg(all(feature = "Implements", feature = "VK_KHR_surface"))]
impl PhysicalDevice
{
pub fn surface_support(&self, queue_family: u32, surface: &::Surface) -> ::Result<bool>
{
let mut f = false as _;
unsafe { vkGetPhysicalDeviceSurfaceSupportKHR(self.0, queue_family, surface.native_ptr(), &mut f) }.into_result().map(|_| f != 0)
}
pub fn surface_capabilities(&self, surface: &::Surface) -> ::Result<VkSurfaceCapabilitiesKHR>
{
let mut s = unsafe { ::std::mem::uninitialized() };
unsafe { vkGetPhysicalDeviceSurfaceCapabilitiesKHR(self.0, surface.native_ptr(), &mut s) }.into_result().map(|_| s)
}
pub fn surface_formats(&self, surface: &::Surface) -> ::Result<Vec<VkSurfaceFormatKHR>>
{
let mut n = 0;
unsafe { vkGetPhysicalDeviceSurfaceFormatsKHR(self.0, surface.native_ptr(), &mut n, ::std::ptr::null_mut()) }.into_result()?;
let mut v = Vec::with_capacity(n as _); unsafe { v.set_len(n as _) };
unsafe { vkGetPhysicalDeviceSurfaceFormatsKHR(self.0, surface.native_ptr(), &mut n, v.as_mut_ptr()) }.into_result().map(|_| v)
}
pub fn surface_present_modes(&self, surface: &::Surface) -> ::Result<Vec<::PresentMode>>
{
let mut n = 0;
unsafe { vkGetPhysicalDeviceSurfacePresentModesKHR(self.0, surface.native_ptr(), &mut n, ::std::ptr::null_mut()) }.into_result()?;
let mut v = Vec::with_capacity(n as _); unsafe { v.set_len(n as _) };
unsafe { vkGetPhysicalDeviceSurfacePresentModesKHR(self.0, surface.native_ptr(), &mut n, v.as_mut_ptr()) }.into_result()
.map(|_| unsafe { ::std::mem::transmute(v) })
}
}
#[cfg(feature = "Implements")]
impl PhysicalDevice
{
#[cfg(feature = "VK_KHR_xlib_surface")]
pub fn xlib_presentation_support(&self, queue_family: u32, display: *mut ::x11::xlib::Display, visual: ::x11::xlib::VisualID) -> bool
{
unsafe { vkGetPhysicalDeviceXlibPresentationSupportKHR(self.0, queue_family, display, visual) != 0 }
}
#[cfg(feature = "VK_KHR_xcb_surface")]
pub fn xcb_presentation_support(&self, queue_family: u32, connection: *mut ::xcb::ffi::xcb_connection_t, visual: ::xcb::ffi::xcb_visualid_t) -> bool
{
unsafe { vkGetPhysicalDeviceXcbPresentationSupportKHR(self.0, queue_family, connection, visual) != 0 }
}
#[cfg(feature = "VK_KHR_wayland_surface")]
pub fn wayland_presentation_support(&self, queue_family: u32, display: *mut ::wayland_client::sys::wl_display) -> bool
{
unsafe { vkGetPhysicalDeviceWaylandPresentationSupportKHR(self.0, queue_family, display) != 0 }
}
#[cfg(feature = "VK_KHR_win32_surface")]
pub fn win32_presentation_support(&self, queue_family: u32) -> bool
{
unsafe { vkGetPhysicalDeviceWin32PresentationSupportKHR(self.0, queue_family) != 0 }
}
}
#[cfg(all(feature = "VK_KHR_display", feature = "Implements"))]
impl PhysicalDevice
{
pub fn display_properties(&self) -> ::Result<Vec<VkDisplayPropertiesKHR>>
{
let mut n = 0;
unsafe { vkGetPhysicalDeviceDisplayPropertiesKHR(self.0, &mut n, ::std::ptr::null_mut()) }.into_result()?;
let mut v = Vec::with_capacity(n as _); unsafe { v.set_len(n as _) };
unsafe { vkGetPhysicalDeviceDisplayPropertiesKHR(self.0, &mut n, v.as_mut_ptr()) }.into_result().map(|_| v)
}
pub fn display_plane_properties(&self) -> ::Result<Vec<VkDisplayPlanePropertiesKHR>>
{
let mut n = 0;
unsafe { vkGetPhysicalDeviceDisplayPlanePropertiesKHR(self.0, &mut n, ::std::ptr::null_mut()) }.into_result()?;
let mut v = Vec::with_capacity(n as _); unsafe { v.set_len(n as _) };
unsafe { vkGetPhysicalDeviceDisplayPlanePropertiesKHR(self.0, &mut n, v.as_mut_ptr()) }.into_result().map(|_| v)
}
pub fn display_plane_supported_displays(&self, index: u32) -> ::Result<Vec<VkDisplayKHR>>
{
let mut n = 0;
unsafe { vkGetDisplayPlaneSupportedDisplaysKHR(self.0, index, &mut n, ::std::ptr::null_mut()) }.into_result()?;
let mut v = Vec::with_capacity(n as _); unsafe { v.set_len(n as _) };
unsafe { vkGetDisplayPlaneSupportedDisplaysKHR(self.0, index, &mut n, v.as_mut_ptr()) }.into_result().map(|_| v)
}
pub fn display_mode_properties(&self, display: VkDisplayKHR) -> ::Result<Vec<VkDisplayModePropertiesKHR>>
{
let mut n = 0;
unsafe { vkGetDisplayModePropertiesKHR(self.0, display, &mut n, ::std::ptr::null_mut()) }.into_result()?;
let mut v = Vec::with_capacity(n as _); unsafe { v.set_len(n as _) };
unsafe { vkGetDisplayModePropertiesKHR(self.0, display, &mut n, v.as_mut_ptr()) }.into_result().map(|_| v)
}
pub fn new_display_mode(&self, display: VkDisplayKHR, region: ::Extent2D, refresh_rate: u32) -> ::Result<VkDisplayModeKHR>
{
let cinfo = VkDisplayModeCreateInfoKHR
{
parameters: VkDisplayModeParametersKHR { visibleRegion: unsafe { ::std::mem::transmute(region) }, refreshRate: refresh_rate },
.. Default::default()
};
let mut h = VK_NULL_HANDLE as _;
unsafe { vkCreateDisplayModeKHR(self.0, display, &cinfo, ::std::ptr::null(), &mut h) }.into_result().map(|_| h)
}
pub fn display_plane_capabilities(&self, mode: VkDisplayModeKHR, plane_index: u32) -> ::Result<VkDisplayPlaneCapabilitiesKHR>
{
let mut s = unsafe { ::std::mem::uninitialized() };
unsafe { vkGetDisplayPlaneCapabilitiesKHR(self.0, mode, plane_index, &mut s) }.into_result().map(|_| s)
}
}
pub struct MemoryProperties(VkPhysicalDeviceMemoryProperties);
impl MemoryProperties
{
#[allow(non_snake_case)]
pub fn find_type_index(&self, mask: MemoryPropertyFlags, exclude: MemoryPropertyFlags) -> Option<u32>
{
self.0.memoryTypes[..self.0.memoryTypeCount as usize].iter()
.position(|&VkMemoryType { propertyFlags, .. }| (propertyFlags & mask.0) != 0 && (propertyFlags & exclude.0) == 0)
.map(|x| x as u32)
}
pub fn find_device_local_index(&self) -> Option<u32> { self.find_type_index(MemoryPropertyFlags::DEVICE_LOCAL, MemoryPropertyFlags::LAZILY_ALLOCATED) }
pub fn find_lazily_allocated_device_local_index(&self) -> Option<u32> { self.find_type_index(MemoryPropertyFlags::DEVICE_LOCAL.lazily_allocated(), MemoryPropertyFlags::EMPTY) }
pub fn find_host_visible_index(&self) -> Option<u32> { self.find_type_index(MemoryPropertyFlags::HOST_VISIBLE, MemoryPropertyFlags::EMPTY) }
pub fn is_coherent(&self, index: u32) -> bool { (self.0.memoryTypes[index as usize].propertyFlags & MemoryPropertyFlags::HOST_COHERENT.0) != 0 }
pub fn is_cached(&self, index: u32) -> bool { (self.0.memoryTypes[index as usize].propertyFlags & MemoryPropertyFlags::HOST_CACHED.0) != 0 }
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct MemoryPropertyFlags(VkMemoryPropertyFlags);
impl MemoryPropertyFlags
{
pub const EMPTY: Self = MemoryPropertyFlags(0);
pub const DEVICE_LOCAL: Self = MemoryPropertyFlags(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
pub const HOST_VISIBLE: Self = MemoryPropertyFlags(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
pub const HOST_COHERENT: Self = MemoryPropertyFlags(VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
pub const HOST_CACHED: Self = MemoryPropertyFlags(VK_MEMORY_PROPERTY_HOST_CACHED_BIT);
pub const LAZILY_ALLOCATED: Self = MemoryPropertyFlags(VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT);
pub fn device_local(mut self) -> Self { self.0 |= Self::DEVICE_LOCAL.0; self }
pub fn host_visible(mut self) -> Self { self.0 |= Self::HOST_VISIBLE.0; self }
pub fn host_coherent(mut self) -> Self { self.0 |= Self::HOST_COHERENT.0; self }
pub fn host_cached(mut self) -> Self { self.0 |= Self::HOST_CACHED.0; self }
pub fn lazily_allocated(mut self) -> Self { self.0 |= Self::LAZILY_ALLOCATED.0; self }
}