diff options
Diffstat (limited to 'src/instance/layers.rs')
-rw-r--r-- | src/instance/layers.rs | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/src/instance/layers.rs b/src/instance/layers.rs new file mode 100644 index 0000000..6c56090 --- /dev/null +++ b/src/instance/layers.rs @@ -0,0 +1,262 @@ +// Copyright (c) 2016 The vulkano developers +// Licensed under the Apache License, Version 2.0 +// <LICENSE-APACHE or +// https://www.apache.org/licenses/LICENSE-2.0> or the MIT +// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, +// at your option. All files in the project carrying such +// notice may not be copied, modified, or distributed except +// according to those terms. + +use std::error; +use std::ffi::CStr; +use std::fmt; +use std::ptr; +use std::vec::IntoIter; + +use crate::check_errors; +use crate::instance::loader; +use crate::instance::loader::LoadingError; +use crate::Error; +use crate::OomError; +use crate::Version; + +/// Queries the list of layers that are available when creating an instance. +/// +/// On success, this function returns an iterator that produces +/// [`LayerProperties`](struct.LayerProperties.html) objects. In order to enable a layer, you need +/// to pass its name (returned by `LayerProperties::name()`) when creating the +/// [`Instance`](struct.Instance.html). +/// +/// This function returns an error if it failed to load the Vulkan library. +/// +/// > **Note**: It is possible that one of the layers enumerated here is no longer available when +/// > you create the `Instance`. This will lead to an error when calling `Instance::new`. The +/// > author isn't aware of any situation where this would happen, but it is theoretically possible +/// > according to the specifications. +/// +/// # Example +/// +/// ```no_run +/// use vulkano::instance; +/// +/// for layer in instance::layers_list().unwrap() { +/// println!("Available layer: {}", layer.name()); +/// } +/// ``` +pub fn layers_list() -> Result<LayersIterator, LayersListError> { + layers_list_from_loader(loader::auto_loader()?) +} + +/// Same as `layers_list()`, but allows specifying a loader. +pub fn layers_list_from_loader<L>( + ptrs: &loader::FunctionPointers<L>, +) -> Result<LayersIterator, LayersListError> +where + L: loader::Loader, +{ + unsafe { + let fns = ptrs.fns(); + + let mut num = 0; + check_errors( + fns.v1_0 + .enumerate_instance_layer_properties(&mut num, ptr::null_mut()), + )?; + + let mut layers: Vec<ash::vk::LayerProperties> = Vec::with_capacity(num as usize); + check_errors({ + fns.v1_0 + .enumerate_instance_layer_properties(&mut num, layers.as_mut_ptr()) + })?; + layers.set_len(num as usize); + + Ok(LayersIterator { + iter: layers.into_iter(), + }) + } +} + +/// Properties of a layer. +#[derive(Clone)] +pub struct LayerProperties { + props: ash::vk::LayerProperties, +} + +impl LayerProperties { + /// Returns the name of the layer. + /// + /// If you want to enable this layer on an instance, you need to pass this value to + /// `Instance::new`. + /// + /// # Example + /// + /// ```no_run + /// use vulkano::instance; + /// + /// for layer in instance::layers_list().unwrap() { + /// println!("Layer name: {}", layer.name()); + /// } + /// ``` + #[inline] + pub fn name(&self) -> &str { + unsafe { + CStr::from_ptr(self.props.layer_name.as_ptr()) + .to_str() + .unwrap() + } + } + + /// Returns a description of the layer. + /// + /// This description is chosen by the layer itself. + /// + /// # Example + /// + /// ```no_run + /// use vulkano::instance; + /// + /// for layer in instance::layers_list().unwrap() { + /// println!("Layer description: {}", layer.description()); + /// } + /// ``` + #[inline] + pub fn description(&self) -> &str { + unsafe { + CStr::from_ptr(self.props.description.as_ptr()) + .to_str() + .unwrap() + } + } + + /// Returns the version of Vulkan supported by this layer. + /// + /// # Example + /// + /// ```no_run + /// use vulkano::instance; + /// use vulkano::instance::Version; + /// + /// for layer in instance::layers_list().unwrap() { + /// if layer.vulkan_version() >= Version::major_minor(2, 0) { + /// println!("Layer {} requires Vulkan 2.0", layer.name()); + /// } + /// } + /// ``` + #[inline] + pub fn vulkan_version(&self) -> Version { + Version::from(self.props.spec_version) + } + + /// Returns an implementation-specific version number for this layer. + /// + /// The number is chosen by the layer itself. It can be used for bug reports for example. + /// + /// # Example + /// + /// ```no_run + /// use vulkano::instance; + /// + /// for layer in instance::layers_list().unwrap() { + /// println!("Layer {} - Version: {}", layer.name(), layer.implementation_version()); + /// } + /// ``` + #[inline] + pub fn implementation_version(&self) -> u32 { + self.props.implementation_version + } +} + +/// Error that can happen when loading the list of layers. +#[derive(Clone, Debug)] +pub enum LayersListError { + /// Failed to load the Vulkan shared library. + LoadingError(LoadingError), + /// Not enough memory. + OomError(OomError), +} + +impl error::Error for LayersListError { + #[inline] + fn source(&self) -> Option<&(dyn error::Error + 'static)> { + match *self { + LayersListError::LoadingError(ref err) => Some(err), + LayersListError::OomError(ref err) => Some(err), + } + } +} + +impl fmt::Display for LayersListError { + #[inline] + fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!( + fmt, + "{}", + match *self { + LayersListError::LoadingError(_) => "failed to load the Vulkan shared library", + LayersListError::OomError(_) => "not enough memory available", + } + ) + } +} + +impl From<OomError> for LayersListError { + #[inline] + fn from(err: OomError) -> LayersListError { + LayersListError::OomError(err) + } +} + +impl From<LoadingError> for LayersListError { + #[inline] + fn from(err: LoadingError) -> LayersListError { + LayersListError::LoadingError(err) + } +} + +impl From<Error> for LayersListError { + #[inline] + fn from(err: Error) -> LayersListError { + match err { + err @ Error::OutOfHostMemory => LayersListError::OomError(OomError::from(err)), + err @ Error::OutOfDeviceMemory => LayersListError::OomError(OomError::from(err)), + _ => panic!("unexpected error: {:?}", err), + } + } +} + +/// Iterator that produces the list of layers that are available. +// TODO: #[derive(Debug, Clone)] +pub struct LayersIterator { + iter: IntoIter<ash::vk::LayerProperties>, +} + +impl Iterator for LayersIterator { + type Item = LayerProperties; + + #[inline] + fn next(&mut self) -> Option<LayerProperties> { + self.iter.next().map(|p| LayerProperties { props: p }) + } + + #[inline] + fn size_hint(&self) -> (usize, Option<usize>) { + self.iter.size_hint() + } +} + +impl ExactSizeIterator for LayersIterator {} + +#[cfg(test)] +mod tests { + use crate::instance; + + #[test] + fn layers_list() { + let mut list = match instance::layers_list() { + Ok(l) => l, + Err(_) => return, + }; + + while let Some(_) = list.next() {} + } +} |