• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2016 The vulkano developers
2 // Licensed under the Apache License, Version 2.0
3 // <LICENSE-APACHE or
4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT
5 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
6 // at your option. All files in the project carrying such
7 // notice may not be copied, modified, or distributed except
8 // according to those terms.
9 
10 use std::error;
11 use std::ffi::CStr;
12 use std::fmt;
13 use std::ptr;
14 use std::vec::IntoIter;
15 
16 use crate::check_errors;
17 use crate::instance::loader;
18 use crate::instance::loader::LoadingError;
19 use crate::Error;
20 use crate::OomError;
21 use crate::Version;
22 
23 /// Queries the list of layers that are available when creating an instance.
24 ///
25 /// On success, this function returns an iterator that produces
26 /// [`LayerProperties`](struct.LayerProperties.html) objects. In order to enable a layer, you need
27 /// to pass its name (returned by `LayerProperties::name()`) when creating the
28 /// [`Instance`](struct.Instance.html).
29 ///
30 /// This function returns an error if it failed to load the Vulkan library.
31 ///
32 /// > **Note**: It is possible that one of the layers enumerated here is no longer available when
33 /// > you create the `Instance`. This will lead to an error when calling `Instance::new`. The
34 /// > author isn't aware of any situation where this would happen, but it is theoretically possible
35 /// > according to the specifications.
36 ///
37 /// # Example
38 ///
39 /// ```no_run
40 /// use vulkano::instance;
41 ///
42 /// for layer in instance::layers_list().unwrap() {
43 ///     println!("Available layer: {}", layer.name());
44 /// }
45 /// ```
layers_list() -> Result<LayersIterator, LayersListError>46 pub fn layers_list() -> Result<LayersIterator, LayersListError> {
47     layers_list_from_loader(loader::auto_loader()?)
48 }
49 
50 /// Same as `layers_list()`, but allows specifying a loader.
layers_list_from_loader<L>( ptrs: &loader::FunctionPointers<L>, ) -> Result<LayersIterator, LayersListError> where L: loader::Loader,51 pub fn layers_list_from_loader<L>(
52     ptrs: &loader::FunctionPointers<L>,
53 ) -> Result<LayersIterator, LayersListError>
54 where
55     L: loader::Loader,
56 {
57     unsafe {
58         let fns = ptrs.fns();
59 
60         let mut num = 0;
61         check_errors(
62             fns.v1_0
63                 .enumerate_instance_layer_properties(&mut num, ptr::null_mut()),
64         )?;
65 
66         let mut layers: Vec<ash::vk::LayerProperties> = Vec::with_capacity(num as usize);
67         check_errors({
68             fns.v1_0
69                 .enumerate_instance_layer_properties(&mut num, layers.as_mut_ptr())
70         })?;
71         layers.set_len(num as usize);
72 
73         Ok(LayersIterator {
74             iter: layers.into_iter(),
75         })
76     }
77 }
78 
79 /// Properties of a layer.
80 #[derive(Clone)]
81 pub struct LayerProperties {
82     props: ash::vk::LayerProperties,
83 }
84 
85 impl LayerProperties {
86     /// Returns the name of the layer.
87     ///
88     /// If you want to enable this layer on an instance, you need to pass this value to
89     /// `Instance::new`.
90     ///
91     /// # Example
92     ///
93     /// ```no_run
94     /// use vulkano::instance;
95     ///
96     /// for layer in instance::layers_list().unwrap() {
97     ///     println!("Layer name: {}", layer.name());
98     /// }
99     /// ```
100     #[inline]
name(&self) -> &str101     pub fn name(&self) -> &str {
102         unsafe {
103             CStr::from_ptr(self.props.layer_name.as_ptr())
104                 .to_str()
105                 .unwrap()
106         }
107     }
108 
109     /// Returns a description of the layer.
110     ///
111     /// This description is chosen by the layer itself.
112     ///
113     /// # Example
114     ///
115     /// ```no_run
116     /// use vulkano::instance;
117     ///
118     /// for layer in instance::layers_list().unwrap() {
119     ///     println!("Layer description: {}", layer.description());
120     /// }
121     /// ```
122     #[inline]
description(&self) -> &str123     pub fn description(&self) -> &str {
124         unsafe {
125             CStr::from_ptr(self.props.description.as_ptr())
126                 .to_str()
127                 .unwrap()
128         }
129     }
130 
131     /// Returns the version of Vulkan supported by this layer.
132     ///
133     /// # Example
134     ///
135     /// ```no_run
136     /// use vulkano::instance;
137     /// use vulkano::instance::Version;
138     ///
139     /// for layer in instance::layers_list().unwrap() {
140     ///     if layer.vulkan_version() >= Version::major_minor(2, 0) {
141     ///         println!("Layer {} requires Vulkan 2.0", layer.name());
142     ///     }
143     /// }
144     /// ```
145     #[inline]
vulkan_version(&self) -> Version146     pub fn vulkan_version(&self) -> Version {
147         Version::from(self.props.spec_version)
148     }
149 
150     /// Returns an implementation-specific version number for this layer.
151     ///
152     /// The number is chosen by the layer itself. It can be used for bug reports for example.
153     ///
154     /// # Example
155     ///
156     /// ```no_run
157     /// use vulkano::instance;
158     ///
159     /// for layer in instance::layers_list().unwrap() {
160     ///     println!("Layer {} - Version: {}", layer.name(), layer.implementation_version());
161     /// }
162     /// ```
163     #[inline]
implementation_version(&self) -> u32164     pub fn implementation_version(&self) -> u32 {
165         self.props.implementation_version
166     }
167 }
168 
169 /// Error that can happen when loading the list of layers.
170 #[derive(Clone, Debug)]
171 pub enum LayersListError {
172     /// Failed to load the Vulkan shared library.
173     LoadingError(LoadingError),
174     /// Not enough memory.
175     OomError(OomError),
176 }
177 
178 impl error::Error for LayersListError {
179     #[inline]
source(&self) -> Option<&(dyn error::Error + 'static)>180     fn source(&self) -> Option<&(dyn error::Error + 'static)> {
181         match *self {
182             LayersListError::LoadingError(ref err) => Some(err),
183             LayersListError::OomError(ref err) => Some(err),
184         }
185     }
186 }
187 
188 impl fmt::Display for LayersListError {
189     #[inline]
fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error>190     fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
191         write!(
192             fmt,
193             "{}",
194             match *self {
195                 LayersListError::LoadingError(_) => "failed to load the Vulkan shared library",
196                 LayersListError::OomError(_) => "not enough memory available",
197             }
198         )
199     }
200 }
201 
202 impl From<OomError> for LayersListError {
203     #[inline]
from(err: OomError) -> LayersListError204     fn from(err: OomError) -> LayersListError {
205         LayersListError::OomError(err)
206     }
207 }
208 
209 impl From<LoadingError> for LayersListError {
210     #[inline]
from(err: LoadingError) -> LayersListError211     fn from(err: LoadingError) -> LayersListError {
212         LayersListError::LoadingError(err)
213     }
214 }
215 
216 impl From<Error> for LayersListError {
217     #[inline]
from(err: Error) -> LayersListError218     fn from(err: Error) -> LayersListError {
219         match err {
220             err @ Error::OutOfHostMemory => LayersListError::OomError(OomError::from(err)),
221             err @ Error::OutOfDeviceMemory => LayersListError::OomError(OomError::from(err)),
222             _ => panic!("unexpected error: {:?}", err),
223         }
224     }
225 }
226 
227 /// Iterator that produces the list of layers that are available.
228 // TODO: #[derive(Debug, Clone)]
229 pub struct LayersIterator {
230     iter: IntoIter<ash::vk::LayerProperties>,
231 }
232 
233 impl Iterator for LayersIterator {
234     type Item = LayerProperties;
235 
236     #[inline]
next(&mut self) -> Option<LayerProperties>237     fn next(&mut self) -> Option<LayerProperties> {
238         self.iter.next().map(|p| LayerProperties { props: p })
239     }
240 
241     #[inline]
size_hint(&self) -> (usize, Option<usize>)242     fn size_hint(&self) -> (usize, Option<usize>) {
243         self.iter.size_hint()
244     }
245 }
246 
247 impl ExactSizeIterator for LayersIterator {}
248 
249 #[cfg(test)]
250 mod tests {
251     use crate::instance;
252 
253     #[test]
layers_list()254     fn layers_list() {
255         let mut list = match instance::layers_list() {
256             Ok(l) => l,
257             Err(_) => return,
258         };
259 
260         while let Some(_) = list.next() {}
261     }
262 }
263