use std::borrow::Cow;
use std::error;
use std::ffi::CStr;
use std::ffi::CString;
use std::fmt;
use std::mem;
use std::ptr;
use std::slice;
use std::sync::Arc;
use smallvec::SmallVec;
use instance::loader;
use instance::loader::LoadingError;
use check_errors;
use Error;
use OomError;
use VulkanObject;
use VulkanPointers;
use vk;
use features::Features;
use version::Version;
use instance::{InstanceExtensions, RawInstanceExtensions};
pub struct Instance {
instance: vk::Instance,
physical_devices: Vec<PhysicalDeviceInfos>,
vk: vk::InstancePointers,
extensions: InstanceExtensions,
layers: SmallVec<[CString; 16]>,
}
impl Instance {
pub fn new<'a, L, Ext>(app_infos: Option<&ApplicationInfo>, extensions: Ext,
layers: L) -> Result<Arc<Instance>, InstanceCreationError>
where L: IntoIterator<Item = &'a &'a str>,
Ext: Into<RawInstanceExtensions>,
{
let layers = layers.into_iter().map(|&layer| {
CString::new(layer).unwrap()
}).collect::<SmallVec<[_; 16]>>();
Instance::new_inner(app_infos, extensions.into(), layers)
}
fn new_inner(app_infos: Option<&ApplicationInfo>, extensions: RawInstanceExtensions,
layers: SmallVec<[CString; 16]>) -> Result<Arc<Instance>, InstanceCreationError>
{
let def = Default::default();
let app_infos = match app_infos {
Some(a) => Some(a),
None => Some(&def)
};
let app_infos_strings = if let Some(app_infos) = app_infos {
Some((
app_infos.application_name.clone().map(|n| CString::new(n.as_bytes().to_owned()).unwrap()),
app_infos.engine_name.clone().map(|n| CString::new(n.as_bytes().to_owned()).unwrap())
))
} else {
None
};
let app_infos = if let Some(app_infos) = app_infos {
Some(vk::ApplicationInfo {
sType: vk::STRUCTURE_TYPE_APPLICATION_INFO,
pNext: ptr::null(),
pApplicationName: app_infos_strings.as_ref().unwrap().0.as_ref().map(|s| s.as_ptr()).unwrap_or(ptr::null()),
applicationVersion: app_infos.application_version.map(|v| v.into_vulkan_version()).unwrap_or(0),
pEngineName: app_infos_strings.as_ref().unwrap().1.as_ref().map(|s| s.as_ptr()).unwrap_or(ptr::null()),
engineVersion: app_infos.engine_version.map(|v| v.into_vulkan_version()).unwrap_or(0),
apiVersion: Version { major: 1, minor: 0, patch: 0 }.into_vulkan_version(), })
} else {
None
};
let layers_ptr = layers.iter().map(|layer| {
layer.as_ptr()
}).collect::<SmallVec<[_; 16]>>();
let extensions_list = extensions.iter().map(|extension| {
extension.as_ptr()
}).collect::<SmallVec<[_; 32]>>();
let entry_points = try!(loader::entry_points());
let instance = unsafe {
let mut output = mem::uninitialized();
let infos = vk::InstanceCreateInfo {
sType: vk::STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
pNext: ptr::null(),
flags: 0,
pApplicationInfo: if let Some(app) = app_infos.as_ref() {
app as *const _
} else {
ptr::null()
},
enabledLayerCount: layers_ptr.len() as u32,
ppEnabledLayerNames: layers_ptr.as_ptr(),
enabledExtensionCount: extensions_list.len() as u32,
ppEnabledExtensionNames: extensions_list.as_ptr(),
};
try!(check_errors(entry_points.CreateInstance(&infos, ptr::null(), &mut output)));
output
};
let vk = {
let f = loader::static_functions().unwrap(); vk::InstancePointers::load(|name| unsafe {
mem::transmute(f.GetInstanceProcAddr(instance, name.as_ptr()))
})
};
let physical_devices: Vec<vk::PhysicalDevice> = unsafe {
let mut num = 0;
try!(check_errors(vk.EnumeratePhysicalDevices(instance, &mut num, ptr::null_mut())));
let mut devices = Vec::with_capacity(num as usize);
try!(check_errors(vk.EnumeratePhysicalDevices(instance, &mut num,
devices.as_mut_ptr())));
devices.set_len(num as usize);
devices
};
let extensions: InstanceExtensions = (&extensions).into();
let physical_devices = if extensions.khr_get_physical_device_properties2 {
Instance::init_physical_devices2(&vk, physical_devices, &extensions)
} else {
Instance::init_physical_devices(&vk, physical_devices)
};
Ok(Arc::new(Instance {
instance: instance,
physical_devices: physical_devices,
vk: vk,
extensions: extensions,
layers: layers,
}))
}
fn init_physical_devices(vk: &vk::InstancePointers, physical_devices: Vec<vk::PhysicalDevice>)
-> Vec<PhysicalDeviceInfos> {
let mut output = Vec::with_capacity(physical_devices.len());
for device in physical_devices.into_iter() {
let properties: vk::PhysicalDeviceProperties = unsafe {
let mut output = mem::uninitialized();
vk.GetPhysicalDeviceProperties(device, &mut output);
output
};
let queue_families = unsafe {
let mut num = 0;
vk.GetPhysicalDeviceQueueFamilyProperties(device, &mut num, ptr::null_mut());
let mut families = Vec::with_capacity(num as usize);
vk.GetPhysicalDeviceQueueFamilyProperties(device, &mut num,
families.as_mut_ptr());
families.set_len(num as usize);
families
};
let memory: vk::PhysicalDeviceMemoryProperties = unsafe {
let mut output = mem::uninitialized();
vk.GetPhysicalDeviceMemoryProperties(device, &mut output);
output
};
let available_features: vk::PhysicalDeviceFeatures = unsafe {
let mut output = mem::uninitialized();
vk.GetPhysicalDeviceFeatures(device, &mut output);
output
};
output.push(PhysicalDeviceInfos {
device: device,
properties: properties,
memory: memory,
queue_families: queue_families,
available_features: Features::from(available_features),
});
}
output
}
fn init_physical_devices2(vk: &vk::InstancePointers, physical_devices: Vec<vk::PhysicalDevice>,
extensions: &InstanceExtensions) -> Vec<PhysicalDeviceInfos> {
let mut output = Vec::with_capacity(physical_devices.len());
for device in physical_devices.into_iter() {
let properties: vk::PhysicalDeviceProperties = unsafe {
let mut output = vk::PhysicalDeviceProperties2KHR {
sType: vk::STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR,
pNext: ptr::null_mut(),
properties: mem::uninitialized(),
};
vk.GetPhysicalDeviceProperties2KHR(device, &mut output);
output.properties
};
let queue_families = unsafe {
let mut num = 0;
vk.GetPhysicalDeviceQueueFamilyProperties2KHR(device, &mut num, ptr::null_mut());
let mut families = (0 .. num).map(|_| {
vk::QueueFamilyProperties2KHR {
sType: vk::STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR,
pNext: ptr::null_mut(),
queueFamilyProperties: mem::uninitialized(),
}
}).collect::<Vec<_>>();
vk.GetPhysicalDeviceQueueFamilyProperties2KHR(device, &mut num,
families.as_mut_ptr());
families.into_iter().map(|family| family.queueFamilyProperties).collect()
};
let memory: vk::PhysicalDeviceMemoryProperties = unsafe {
let mut output = vk::PhysicalDeviceMemoryProperties2KHR {
sType: vk::STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR,
pNext: ptr::null_mut(),
memoryProperties: mem::uninitialized(),
};
vk.GetPhysicalDeviceMemoryProperties2KHR(device, &mut output);
output.memoryProperties
};
let available_features: vk::PhysicalDeviceFeatures = unsafe {
let mut output = vk::PhysicalDeviceFeatures2KHR {
sType: vk::STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR,
pNext: ptr::null_mut(),
features: mem::uninitialized(),
};
vk.GetPhysicalDeviceFeatures2KHR(device, &mut output);
output.features
};
output.push(PhysicalDeviceInfos {
device: device,
properties: properties,
memory: memory,
queue_families: queue_families,
available_features: Features::from(available_features),
});
}
output
}
#[inline]
pub fn loaded_extensions(&self) -> &InstanceExtensions {
&self.extensions
}
#[doc(hidden)]
#[inline]
pub fn loaded_layers(&self) -> slice::Iter<CString> {
self.layers.iter()
}
}
impl fmt::Debug for Instance {
#[inline]
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(fmt, "<Vulkan instance {:?}>", self.instance)
}
}
unsafe impl VulkanObject for Instance {
type Object = vk::Instance;
#[inline]
fn internal_object(&self) -> vk::Instance {
self.instance
}
}
impl VulkanPointers for Instance {
type Pointers = vk::InstancePointers;
#[inline]
fn pointers(&self) -> &vk::InstancePointers {
&self.vk
}
}
impl Drop for Instance {
#[inline]
fn drop(&mut self) {
unsafe {
self.vk.DestroyInstance(self.instance, ptr::null());
}
}
}
#[derive(Debug, Clone)]
pub struct ApplicationInfo<'a> {
pub application_name: Option<Cow<'a, str>>,
pub application_version: Option<Version>,
pub engine_name: Option<Cow<'a, str>>,
pub engine_version: Option<Version>,
}
impl<'a> ApplicationInfo<'a> {
pub fn from_cargo_toml() -> ApplicationInfo<'a> {
let version = Version {
major: env!("CARGO_PKG_VERSION_MAJOR").parse().unwrap(),
minor: env!("CARGO_PKG_VERSION_MINOR").parse().unwrap(),
patch: env!("CARGO_PKG_VERSION_PATCH").parse().unwrap(),
};
let name = env!("CARGO_PKG_NAME");
ApplicationInfo {
application_name: Some(name.into()),
application_version: Some(version),
engine_name: None,
engine_version: None,
}
}
}
impl<'a> Default for ApplicationInfo<'a> {
fn default() -> ApplicationInfo<'a> {
ApplicationInfo::from_cargo_toml()
}
}
#[derive(Clone, Debug)]
pub enum InstanceCreationError {
LoadingError(LoadingError),
OomError(OomError),
InitializationFailed,
LayerNotPresent,
ExtensionNotPresent,
IncompatibleDriver,
}
impl error::Error for InstanceCreationError {
#[inline]
fn description(&self) -> &str {
match *self {
InstanceCreationError::LoadingError(_) => "failed to load the Vulkan shared library",
InstanceCreationError::OomError(_) => "not enough memory available",
InstanceCreationError::InitializationFailed => "initialization failed",
InstanceCreationError::LayerNotPresent => "layer not present",
InstanceCreationError::ExtensionNotPresent => "extension not present",
InstanceCreationError::IncompatibleDriver => "incompatible driver",
}
}
#[inline]
fn cause(&self) -> Option<&error::Error> {
match *self {
InstanceCreationError::LoadingError(ref err) => Some(err),
InstanceCreationError::OomError(ref err) => Some(err),
_ => None
}
}
}
impl fmt::Display for InstanceCreationError {
#[inline]
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(fmt, "{}", error::Error::description(self))
}
}
impl From<OomError> for InstanceCreationError {
#[inline]
fn from(err: OomError) -> InstanceCreationError {
InstanceCreationError::OomError(err)
}
}
impl From<LoadingError> for InstanceCreationError {
#[inline]
fn from(err: LoadingError) -> InstanceCreationError {
InstanceCreationError::LoadingError(err)
}
}
impl From<Error> for InstanceCreationError {
#[inline]
fn from(err: Error) -> InstanceCreationError {
match err {
err @ Error::OutOfHostMemory => InstanceCreationError::OomError(OomError::from(err)),
err @ Error::OutOfDeviceMemory => InstanceCreationError::OomError(OomError::from(err)),
Error::InitializationFailed => InstanceCreationError::InitializationFailed,
Error::LayerNotPresent => InstanceCreationError::LayerNotPresent,
Error::ExtensionNotPresent => InstanceCreationError::ExtensionNotPresent,
Error::IncompatibleDriver => InstanceCreationError::IncompatibleDriver,
_ => panic!("unexpected error: {:?}", err)
}
}
}
struct PhysicalDeviceInfos {
device: vk::PhysicalDevice,
properties: vk::PhysicalDeviceProperties,
queue_families: Vec<vk::QueueFamilyProperties>,
memory: vk::PhysicalDeviceMemoryProperties,
available_features: Features,
}
#[derive(Debug, Copy, Clone)]
pub struct PhysicalDevice<'a> {
instance: &'a Arc<Instance>,
device: usize,
}
impl<'a> PhysicalDevice<'a> {
#[inline]
pub fn enumerate(instance: &'a Arc<Instance>) -> PhysicalDevicesIter<'a> {
PhysicalDevicesIter {
instance: instance,
current_id: 0,
}
}
#[inline]
pub fn from_index(instance: &'a Arc<Instance>, index: usize) -> Option<PhysicalDevice<'a>> {
if instance.physical_devices.len() > index {
Some(PhysicalDevice {
instance: instance,
device: index,
})
} else {
None
}
}
#[inline]
pub fn instance(&self) -> &'a Arc<Instance> {
&self.instance
}
#[inline]
pub fn index(&self) -> usize {
self.device
}
#[inline]
pub fn name(&self) -> String { unsafe {
let val = self.infos().properties.deviceName;
let val = CStr::from_ptr(val.as_ptr());
val.to_str().expect("physical device name contained non-UTF8 characters").to_owned()
}
}
#[inline]
pub fn ty(&self) -> PhysicalDeviceType {
match self.instance.physical_devices[self.device].properties.deviceType {
vk::PHYSICAL_DEVICE_TYPE_OTHER => PhysicalDeviceType::Other,
vk::PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU => PhysicalDeviceType::IntegratedGpu,
vk::PHYSICAL_DEVICE_TYPE_DISCRETE_GPU => PhysicalDeviceType::DiscreteGpu,
vk::PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU => PhysicalDeviceType::VirtualGpu,
vk::PHYSICAL_DEVICE_TYPE_CPU => PhysicalDeviceType::Cpu,
_ => panic!("Unrecognized Vulkan device type")
}
}
#[inline]
pub fn api_version(&self) -> Version {
let val = self.infos().properties.apiVersion;
Version::from_vulkan_version(val)
}
#[inline]
pub fn supported_features(&self) -> &'a Features {
&self.infos().available_features
}
#[inline]
pub fn queue_families(&self) -> QueueFamiliesIter<'a> {
QueueFamiliesIter {
physical_device: *self,
current_id: 0,
}
}
#[inline]
pub fn queue_family_by_id(&self, id: u32) -> Option<QueueFamily<'a>> {
if (id as usize) < self.infos().queue_families.len() {
Some(QueueFamily {
physical_device: *self,
id: id,
})
} else {
None
}
}
#[inline]
pub fn memory_types(&self) -> MemoryTypesIter<'a> {
MemoryTypesIter {
physical_device: *self,
current_id: 0,
}
}
#[inline]
pub fn memory_type_by_id(&self, id: u32) -> Option<MemoryType<'a>> {
if id < self.infos().memory.memoryTypeCount {
Some(MemoryType {
physical_device: *self,
id: id,
})
} else {
None
}
}
#[inline]
pub fn memory_heaps(&self) -> MemoryHeapsIter<'a> {
MemoryHeapsIter {
physical_device: *self,
current_id: 0,
}
}
#[inline]
pub fn memory_heap_by_id(&self, id: u32) -> Option<MemoryHeap<'a>> {
if id < self.infos().memory.memoryHeapCount {
Some(MemoryHeap {
physical_device: *self,
id: id,
})
} else {
None
}
}
#[inline]
pub fn limits(&self) -> Limits<'a> {
Limits { device: *self }
}
#[inline]
pub fn driver_version(&self) -> u32 {
self.infos().properties.driverVersion
}
#[inline]
pub fn pci_device_id(&self) -> u32 {
self.infos().properties.deviceID
}
#[inline]
pub fn pci_vendor_id(&self) -> u32 {
self.infos().properties.vendorID
}
#[inline]
pub fn uuid(&self) -> &[u8; 16] { &self.infos().properties.pipelineCacheUUID
}
#[inline]
fn infos(&self) -> &'a PhysicalDeviceInfos {
&self.instance.physical_devices[self.device]
}
}
unsafe impl<'a> VulkanObject for PhysicalDevice<'a> {
type Object = vk::PhysicalDevice;
#[inline]
fn internal_object(&self) -> vk::PhysicalDevice {
self.infos().device
}
}
#[derive(Debug, Clone)]
pub struct PhysicalDevicesIter<'a> {
instance: &'a Arc<Instance>,
current_id: usize,
}
impl<'a> Iterator for PhysicalDevicesIter<'a> {
type Item = PhysicalDevice<'a>;
#[inline]
fn next(&mut self) -> Option<PhysicalDevice<'a>> {
if self.current_id >= self.instance.physical_devices.len() {
return None;
}
let dev = PhysicalDevice {
instance: self.instance,
device: self.current_id,
};
self.current_id += 1;
Some(dev)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.instance.physical_devices.len() - self.current_id;
(len, Some(len))
}
}
impl<'a> ExactSizeIterator for PhysicalDevicesIter<'a> {
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[repr(u32)]
pub enum PhysicalDeviceType {
IntegratedGpu = 1,
DiscreteGpu = 2,
VirtualGpu = 3,
Cpu = 4,
Other = 0,
}
#[derive(Debug, Copy, Clone)]
pub struct QueueFamily<'a> {
physical_device: PhysicalDevice<'a>,
id: u32,
}
impl<'a> QueueFamily<'a> {
#[inline]
pub fn physical_device(&self) -> PhysicalDevice<'a> {
self.physical_device
}
#[inline]
pub fn id(&self) -> u32 {
self.id
}
#[inline]
pub fn queues_count(&self) -> usize {
self.physical_device.infos().queue_families[self.id as usize].queueCount as usize
}
#[inline]
pub fn supports_graphics(&self) -> bool {
(self.flags() & vk::QUEUE_GRAPHICS_BIT) != 0
}
#[inline]
pub fn supports_compute(&self) -> bool {
(self.flags() & vk::QUEUE_COMPUTE_BIT) != 0
}
#[inline]
pub fn supports_transfers(&self) -> bool {
(self.flags() & vk::QUEUE_TRANSFER_BIT) != 0
}
#[inline]
pub fn supports_sparse_binding(&self) -> bool {
(self.flags() & vk::QUEUE_SPARSE_BINDING_BIT) != 0
}
#[inline]
fn flags(&self) -> u32 {
self.physical_device.infos().queue_families[self.id as usize].queueFlags
}
}
#[derive(Debug, Clone)]
pub struct QueueFamiliesIter<'a> {
physical_device: PhysicalDevice<'a>,
current_id: u32,
}
impl<'a> Iterator for QueueFamiliesIter<'a> {
type Item = QueueFamily<'a>;
#[inline]
fn next(&mut self) -> Option<QueueFamily<'a>> {
if self.current_id as usize >= self.physical_device.infos().queue_families.len() {
return None;
}
let dev = QueueFamily {
physical_device: self.physical_device,
id: self.current_id,
};
self.current_id += 1;
Some(dev)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.physical_device.infos().queue_families.len();
let remain = len - self.current_id as usize;
(remain, Some(remain))
}
}
impl<'a> ExactSizeIterator for QueueFamiliesIter<'a> {}
#[derive(Debug, Copy, Clone)]
pub struct MemoryType<'a> {
physical_device: PhysicalDevice<'a>,
id: u32,
}
impl<'a> MemoryType<'a> {
#[inline]
pub fn physical_device(&self) -> PhysicalDevice<'a> {
self.physical_device
}
#[inline]
pub fn id(&self) -> u32 {
self.id
}
#[inline]
pub fn heap(&self) -> MemoryHeap<'a> {
let heap_id = self.physical_device.infos().memory.memoryTypes[self.id as usize].heapIndex;
MemoryHeap { physical_device: self.physical_device, id: heap_id }
}
#[inline]
pub fn is_device_local(&self) -> bool {
(self.flags() & vk::MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0
}
#[inline]
pub fn is_host_visible(&self) -> bool {
(self.flags() & vk::MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0
}
#[inline]
pub fn is_host_coherent(&self) -> bool {
(self.flags() & vk::MEMORY_PROPERTY_HOST_COHERENT_BIT) != 0
}
#[inline]
pub fn is_host_cached(&self) -> bool {
(self.flags() & vk::MEMORY_PROPERTY_HOST_CACHED_BIT) != 0
}
#[inline]
pub fn is_lazily_allocated(&self) -> bool {
(self.flags() & vk::MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) != 0
}
#[inline]
fn flags(&self) -> u32 {
self.physical_device.infos().memory.memoryTypes[self.id as usize].propertyFlags
}
}
#[derive(Debug, Clone)]
pub struct MemoryTypesIter<'a> {
physical_device: PhysicalDevice<'a>,
current_id: u32,
}
impl<'a> Iterator for MemoryTypesIter<'a> {
type Item = MemoryType<'a>;
#[inline]
fn next(&mut self) -> Option<MemoryType<'a>> {
if self.current_id >= self.physical_device.infos().memory.memoryTypeCount {
return None;
}
let dev = MemoryType {
physical_device: self.physical_device,
id: self.current_id,
};
self.current_id += 1;
Some(dev)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.physical_device.infos().memory.memoryTypeCount;
let remain = (len - self.current_id) as usize;
(remain, Some(remain))
}
}
impl<'a> ExactSizeIterator for MemoryTypesIter<'a> {}
#[derive(Debug, Copy, Clone)]
pub struct MemoryHeap<'a> {
physical_device: PhysicalDevice<'a>,
id: u32,
}
impl<'a> MemoryHeap<'a> {
#[inline]
pub fn physical_device(&self) -> PhysicalDevice<'a> {
self.physical_device
}
#[inline]
pub fn id(&self) -> u32 {
self.id
}
#[inline]
pub fn size(&self) -> usize {
self.physical_device.infos().memory.memoryHeaps[self.id as usize].size as usize
}
#[inline]
pub fn is_device_local(&self) -> bool {
let flags = self.physical_device.infos().memory.memoryHeaps[self.id as usize].flags;
(flags & vk::MEMORY_HEAP_DEVICE_LOCAL_BIT) != 0
}
}
#[derive(Debug, Clone)]
pub struct MemoryHeapsIter<'a> {
physical_device: PhysicalDevice<'a>,
current_id: u32,
}
impl<'a> Iterator for MemoryHeapsIter<'a> {
type Item = MemoryHeap<'a>;
#[inline]
fn next(&mut self) -> Option<MemoryHeap<'a>> {
if self.current_id >= self.physical_device.infos().memory.memoryHeapCount {
return None;
}
let dev = MemoryHeap {
physical_device: self.physical_device,
id: self.current_id,
};
self.current_id += 1;
Some(dev)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.physical_device.infos().memory.memoryHeapCount;
let remain = (len - self.current_id) as usize;
(remain, Some(remain))
}
}
impl<'a> ExactSizeIterator for MemoryHeapsIter<'a> {}
pub struct Limits<'a> {
device: PhysicalDevice<'a>,
}
macro_rules! limits_impl {
($($name:ident: $t:ty => $target:ident,)*) => (
impl<'a> Limits<'a> {
$(
#[inline]
pub fn $name(&self) -> $t {
self.device.infos().properties.limits.$target
}
)*
}
)
}
limits_impl!{
max_image_dimension_1d: u32 => maxImageDimension1D,
max_image_dimension_2d: u32 => maxImageDimension2D,
max_image_dimension_3d: u32 => maxImageDimension3D,
max_image_dimension_cube: u32 => maxImageDimensionCube,
max_image_array_layers: u32 => maxImageArrayLayers,
max_texel_buffer_elements: u32 => maxTexelBufferElements,
max_uniform_buffer_range: u32 => maxUniformBufferRange,
max_storage_buffer_range: u32 => maxStorageBufferRange,
max_push_constants_size: u32 => maxPushConstantsSize,
max_memory_allocation_count: u32 => maxMemoryAllocationCount,
max_sampler_allocation_count: u32 => maxSamplerAllocationCount,
buffer_image_granularity: u64 => bufferImageGranularity,
sparse_address_space_size: u64 => sparseAddressSpaceSize,
max_bound_descriptor_sets: u32 => maxBoundDescriptorSets,
max_per_stage_descriptor_samplers: u32 => maxPerStageDescriptorSamplers,
max_per_stage_descriptor_uniform_buffers: u32 => maxPerStageDescriptorUniformBuffers,
max_per_stage_descriptor_storage_buffers: u32 => maxPerStageDescriptorStorageBuffers,
max_per_stage_descriptor_sampled_images: u32 => maxPerStageDescriptorSampledImages,
max_per_stage_descriptor_storage_images: u32 => maxPerStageDescriptorStorageImages,
max_per_stage_descriptor_input_attachments: u32 => maxPerStageDescriptorInputAttachments,
max_per_stage_resources: u32 => maxPerStageResources,
max_descriptor_set_samplers: u32 => maxDescriptorSetSamplers,
max_descriptor_set_uniform_buffers: u32 => maxDescriptorSetUniformBuffers,
max_descriptor_set_uniform_buffers_dynamic: u32 => maxDescriptorSetUniformBuffersDynamic,
max_descriptor_set_storage_buffers: u32 => maxDescriptorSetStorageBuffers,
max_descriptor_set_storage_buffers_dynamic: u32 => maxDescriptorSetStorageBuffersDynamic,
max_descriptor_set_sampled_images: u32 => maxDescriptorSetSampledImages,
max_descriptor_set_storage_images: u32 => maxDescriptorSetStorageImages,
max_descriptor_set_input_attachments: u32 => maxDescriptorSetInputAttachments,
max_vertex_input_attributes: u32 => maxVertexInputAttributes,
max_vertex_input_bindings: u32 => maxVertexInputBindings,
max_vertex_input_attribute_offset: u32 => maxVertexInputAttributeOffset,
max_vertex_input_binding_stride: u32 => maxVertexInputBindingStride,
max_vertex_output_components: u32 => maxVertexOutputComponents,
max_tessellation_generation_level: u32 => maxTessellationGenerationLevel,
max_tessellation_patch_size: u32 => maxTessellationPatchSize,
max_tessellation_control_per_vertex_input_components: u32 => maxTessellationControlPerVertexInputComponents,
max_tessellation_control_per_vertex_output_components: u32 => maxTessellationControlPerVertexOutputComponents,
max_tessellation_control_per_patch_output_components: u32 => maxTessellationControlPerPatchOutputComponents,
max_tessellation_control_total_output_components: u32 => maxTessellationControlTotalOutputComponents,
max_tessellation_evaluation_input_components: u32 => maxTessellationEvaluationInputComponents,
max_tessellation_evaluation_output_components: u32 => maxTessellationEvaluationOutputComponents,
max_geometry_shader_invocations: u32 => maxGeometryShaderInvocations,
max_geometry_input_components: u32 => maxGeometryInputComponents,
max_geometry_output_components: u32 => maxGeometryOutputComponents,
max_geometry_output_vertices: u32 => maxGeometryOutputVertices,
max_geometry_total_output_components: u32 => maxGeometryTotalOutputComponents,
max_fragment_input_components: u32 => maxFragmentInputComponents,
max_fragment_output_attachments: u32 => maxFragmentOutputAttachments,
max_fragment_dual_src_attachments: u32 => maxFragmentDualSrcAttachments,
max_fragment_combined_output_resources: u32 => maxFragmentCombinedOutputResources,
max_compute_shared_memory_size: u32 => maxComputeSharedMemorySize,
max_compute_work_group_count: [u32; 3] => maxComputeWorkGroupCount,
max_compute_work_group_invocations: u32 => maxComputeWorkGroupInvocations,
max_compute_work_group_size: [u32; 3] => maxComputeWorkGroupSize,
sub_pixel_precision_bits: u32 => subPixelPrecisionBits,
sub_texel_precision_bits: u32 => subTexelPrecisionBits,
mipmap_precision_bits: u32 => mipmapPrecisionBits,
max_draw_indexed_index_value: u32 => maxDrawIndexedIndexValue,
max_draw_indirect_count: u32 => maxDrawIndirectCount,
max_sampler_lod_bias: f32 => maxSamplerLodBias,
max_sampler_anisotropy: f32 => maxSamplerAnisotropy,
max_viewports: u32 => maxViewports,
max_viewport_dimensions: [u32; 2] => maxViewportDimensions,
viewport_bounds_range: [f32; 2] => viewportBoundsRange,
viewport_sub_pixel_bits: u32 => viewportSubPixelBits,
min_memory_map_alignment: usize => minMemoryMapAlignment,
min_texel_buffer_offset_alignment: u64 => minTexelBufferOffsetAlignment,
min_uniform_buffer_offset_alignment: u64 => minUniformBufferOffsetAlignment,
min_storage_buffer_offset_alignment: u64 => minStorageBufferOffsetAlignment,
min_texel_offset: i32 => minTexelOffset,
max_texel_offset: u32 => maxTexelOffset,
min_texel_gather_offset: i32 => minTexelGatherOffset,
max_texel_gather_offset: u32 => maxTexelGatherOffset,
min_interpolation_offset: f32 => minInterpolationOffset,
max_interpolation_offset: f32 => maxInterpolationOffset,
sub_pixel_interpolation_offset_bits: u32 => subPixelInterpolationOffsetBits,
max_framebuffer_width: u32 => maxFramebufferWidth,
max_framebuffer_height: u32 => maxFramebufferHeight,
max_framebuffer_layers: u32 => maxFramebufferLayers,
framebuffer_color_sample_counts: u32 => framebufferColorSampleCounts, framebuffer_depth_sample_counts: u32 => framebufferDepthSampleCounts, framebuffer_stencil_sample_counts: u32 => framebufferStencilSampleCounts, framebuffer_no_attachments_sample_counts: u32 => framebufferNoAttachmentsSampleCounts, max_color_attachments: u32 => maxColorAttachments,
sampled_image_color_sample_counts: u32 => sampledImageColorSampleCounts, sampled_image_integer_sample_counts: u32 => sampledImageIntegerSampleCounts, sampled_image_depth_sample_counts: u32 => sampledImageDepthSampleCounts, sampled_image_stencil_sample_counts: u32 => sampledImageStencilSampleCounts, storage_image_sample_counts: u32 => storageImageSampleCounts, max_sample_mask_words: u32 => maxSampleMaskWords,
timestamp_compute_and_graphics: u32 => timestampComputeAndGraphics, timestamp_period: f32 => timestampPeriod,
max_clip_distances: u32 => maxClipDistances,
max_cull_distances: u32 => maxCullDistances,
max_combined_clip_and_cull_distances: u32 => maxCombinedClipAndCullDistances,
discrete_queue_priorities: u32 => discreteQueuePriorities,
point_size_range: [f32; 2] => pointSizeRange,
line_width_range: [f32; 2] => lineWidthRange,
point_size_granularity: f32 => pointSizeGranularity,
line_width_granularity: f32 => lineWidthGranularity,
strict_lines: u32 => strictLines, standard_sample_locations: u32 => standardSampleLocations, optimal_buffer_copy_offset_alignment: u64 => optimalBufferCopyOffsetAlignment,
optimal_buffer_copy_row_pitch_alignment: u64 => optimalBufferCopyRowPitchAlignment,
non_coherent_atom_size: u64 => nonCoherentAtomSize,
}
#[cfg(test)]
mod tests {
use instance;
#[test]
fn create_instance() {
let _ = instance!();
}
#[test]
fn queue_family_by_id() {
let instance = instance!();
let phys = match instance::PhysicalDevice::enumerate(&instance).next() {
Some(p) => p,
None => return
};
let queue_family = match phys.queue_families().next() {
Some(q) => q,
None => return
};
let by_id = phys.queue_family_by_id(queue_family.id()).unwrap();
assert_eq!(by_id.id(), queue_family.id());
}
}