use smallvec::SmallVec;
use std::borrow::Cow;
use std::error;
use std::ffi::CStr;
use std::ffi::CString;
use std::fmt;
use std::mem;
use std::ops::Deref;
use std::ptr;
use std::slice;
use std::sync::Arc;
use Error;
use OomError;
use VulkanObject;
use check_errors;
use instance::limits::Limits;
use instance::loader;
use instance::loader::FunctionPointers;
use instance::loader::Loader;
use instance::loader::LoadingError;
use vk;
use instance::{InstanceExtensions, RawInstanceExtensions};
use version::Version;
use features::Features;
pub struct Instance {
instance: vk::Instance,
physical_devices: Vec<PhysicalDeviceInfos>,
vk: vk::InstancePointers,
extensions: InstanceExtensions,
layers: SmallVec<[CString; 16]>,
function_pointers: OwnedOrRef<FunctionPointers<Box<dyn Loader + Send + Sync>>>,
}
impl ::std::panic::UnwindSafe for Instance {
}
impl ::std::panic::RefUnwindSafe for Instance {
}
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 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,
OwnedOrRef::Ref(loader::auto_loader()?))
}
pub fn with_loader<'a, L, Ext>(loader: FunctionPointers<Box<dyn Loader + Send + Sync>>,
app_infos: Option<&ApplicationInfo>, extensions: Ext, layers: L)
-> Result<Arc<Instance>, InstanceCreationError>
where L: IntoIterator<Item = &'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,
OwnedOrRef::Owned(loader))
}
fn new_inner(app_infos: Option<&ApplicationInfo>, extensions: RawInstanceExtensions,
layers: SmallVec<[CString; 16]>,
function_pointers: OwnedOrRef<FunctionPointers<Box<dyn Loader + Send + Sync>>>)
-> 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 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(),
};
let entry_points = function_pointers.entry_points();
check_errors(entry_points.CreateInstance(&infos, ptr::null(), &mut output))?;
output
};
let vk = {
vk::InstancePointers::load(|name| unsafe {
mem::transmute(function_pointers.get_instance_proc_addr(instance, name.as_ptr()))
})
};
let physical_devices: Vec<vk::PhysicalDevice> = unsafe {
let mut num = 0;
check_errors(vk.EnumeratePhysicalDevices(instance, &mut num, ptr::null_mut()))?;
let mut devices = Vec::with_capacity(num as usize);
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,
function_pointers: function_pointers,
}))
}
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_vulkan_features(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_vulkan_features(available_features),
});
}
output
}
#[inline]
pub(crate) fn pointers(&self) -> &vk::InstancePointers {
&self.vk
}
#[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;
const TYPE: vk::DebugReportObjectTypeEXT = vk::DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT;
#[inline]
fn internal_object(&self) -> vk::Instance {
self.instance
}
}
impl Drop for Instance {
#[inline]
fn drop(&mut self) {
unsafe {
self.vk.DestroyInstance(self.instance, ptr::null());
}
}
}
enum OwnedOrRef<T: 'static> {
Owned(T),
Ref(&'static T),
}
impl<T> Deref for OwnedOrRef<T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
match *self {
OwnedOrRef::Owned(ref v) => v,
OwnedOrRef::Ref(v) => v,
}
}
}
#[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> {
#[deprecated(note = "Please use the `app_info_from_cargo_toml!` macro instead")]
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,
}
}
}
#[macro_export]
macro_rules! app_info_from_cargo_toml {
() => {{
let version = $crate::instance::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");
$crate::instance::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 {
application_name: None,
application_version: None,
engine_name: None,
engine_version: None,
}
}
}
#[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<&dyn 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::from_vk_limits(&self.infos().properties.limits)
}
#[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;
const TYPE: vk::DebugReportObjectTypeEXT = vk::DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT;
#[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 timestamp_valid_bits(&self) -> Option<u32> {
let value = self.physical_device.infos().queue_families[self.id as usize].timestampValidBits;
if value == 0 {
None
} else {
Some(value)
}
}
#[inline]
pub fn min_image_transfer_granularity(&self) -> [u32; 3] {
let ref granularity = self.physical_device.infos().queue_families[self.id as usize]
.minImageTransferGranularity;
[granularity.width, granularity.height, granularity.depth]
}
#[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 explicitly_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> {
}
#[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());
}
}