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