• 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 crate::instance::loader::LoadingError;
11 use crate::Error;
12 use crate::OomError;
13 use crate::Version;
14 use std::error;
15 use std::fmt;
16 
17 macro_rules! extensions {
18     (
19         $sname:ident,
20         $($member:ident => {
21             doc: $doc:expr,
22             raw: $raw:expr,
23             requires_core: $requires_core:expr,
24             requires_device_extensions: [$($requires_device_extension:ident),*],
25             requires_instance_extensions: [$($requires_instance_extension:ident),*]$(,)?
26         },)*
27     ) => (
28         /// List of extensions that are enabled or available.
29         #[derive(Copy, Clone, PartialEq, Eq)]
30         pub struct $sname {
31             $(
32                 #[doc = $doc]
33                 pub $member: bool,
34             )*
35 
36             /// This field ensures that an instance of this `Extensions` struct
37             /// can only be created through Vulkano functions and the update
38             /// syntax. This way, extensions can be added to Vulkano without
39             /// breaking existing code.
40             pub _unbuildable: crate::extensions::Unbuildable,
41         }
42 
43         impl $sname {
44             /// Returns an `Extensions` object with all members set to `false`.
45             #[inline]
46             pub const fn none() -> $sname {
47                 $sname {
48                     $($member: false,)*
49                     _unbuildable: crate::extensions::Unbuildable(())
50                 }
51             }
52 
53             /// Returns true if `self` is a superset of the parameter.
54             ///
55             /// That is, for each extension of the parameter that is true, the corresponding value
56             /// in self is true as well.
57             pub fn is_superset_of(&self, other: &$sname) -> bool {
58                 $((self.$member == true || other.$member == false))&&+
59             }
60 
61             /// Returns the union of this list and another list.
62             #[inline]
63             pub const fn union(&self, other: &$sname) -> $sname {
64                 $sname {
65                     $(
66                         $member: self.$member || other.$member,
67                     )*
68                     _unbuildable: crate::extensions::Unbuildable(())
69                 }
70             }
71 
72             /// Returns the intersection of this list and another list.
73             #[inline]
74             pub const fn intersection(&self, other: &$sname) -> $sname {
75                 $sname {
76                     $(
77                         $member: self.$member && other.$member,
78                     )*
79                     _unbuildable: crate::extensions::Unbuildable(())
80                 }
81             }
82 
83             /// Returns the difference of another list from this list.
84             #[inline]
85             pub const fn difference(&self, other: &$sname) -> $sname {
86                 $sname {
87                     $(
88                         $member: self.$member && !other.$member,
89                     )*
90                     _unbuildable: crate::extensions::Unbuildable(())
91                 }
92             }
93         }
94 
95         impl std::fmt::Debug for $sname {
96             #[allow(unused_assignments)]
97             fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
98                 write!(f, "[")?;
99 
100                 let mut first = true;
101 
102                 $(
103                     if self.$member {
104                         if !first { write!(f, ", ")? }
105                         else { first = false; }
106                         f.write_str(std::str::from_utf8($raw).unwrap())?;
107                     }
108                 )*
109 
110                 write!(f, "]")
111             }
112         }
113 
114         impl<'a, I> From<I> for $sname where I: IntoIterator<Item = &'a std::ffi::CStr> {
115             fn from(names: I) -> Self {
116                 let mut extensions = Self::none();
117                 for name in names {
118                     match name.to_bytes() {
119                         $(
120                             $raw => { extensions.$member = true; }
121                         )*
122                         _ => (),
123                     }
124                 }
125                 extensions
126             }
127         }
128 
129         impl<'a> From<&'a $sname> for Vec<std::ffi::CString> {
130             fn from(x: &'a $sname) -> Self {
131                 let mut data = Self::new();
132                 $(if x.$member { data.push(std::ffi::CString::new(&$raw[..]).unwrap()); })*
133                 data
134             }
135         }
136     );
137 }
138 
139 /// Error that can happen when loading the list of layers.
140 #[derive(Clone, Debug)]
141 pub enum SupportedExtensionsError {
142     /// Failed to load the Vulkan shared library.
143     LoadingError(LoadingError),
144     /// Not enough memory.
145     OomError(OomError),
146 }
147 
148 impl error::Error for SupportedExtensionsError {
149     #[inline]
source(&self) -> Option<&(dyn error::Error + 'static)>150     fn source(&self) -> Option<&(dyn error::Error + 'static)> {
151         match *self {
152             SupportedExtensionsError::LoadingError(ref err) => Some(err),
153             SupportedExtensionsError::OomError(ref err) => Some(err),
154         }
155     }
156 }
157 
158 impl fmt::Display for SupportedExtensionsError {
159     #[inline]
fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error>160     fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
161         write!(
162             fmt,
163             "{}",
164             match *self {
165                 SupportedExtensionsError::LoadingError(_) =>
166                     "failed to load the Vulkan shared library",
167                 SupportedExtensionsError::OomError(_) => "not enough memory available",
168             }
169         )
170     }
171 }
172 
173 impl From<OomError> for SupportedExtensionsError {
174     #[inline]
from(err: OomError) -> SupportedExtensionsError175     fn from(err: OomError) -> SupportedExtensionsError {
176         SupportedExtensionsError::OomError(err)
177     }
178 }
179 
180 impl From<LoadingError> for SupportedExtensionsError {
181     #[inline]
from(err: LoadingError) -> SupportedExtensionsError182     fn from(err: LoadingError) -> SupportedExtensionsError {
183         SupportedExtensionsError::LoadingError(err)
184     }
185 }
186 
187 impl From<Error> for SupportedExtensionsError {
188     #[inline]
from(err: Error) -> SupportedExtensionsError189     fn from(err: Error) -> SupportedExtensionsError {
190         match err {
191             err @ Error::OutOfHostMemory => SupportedExtensionsError::OomError(OomError::from(err)),
192             err @ Error::OutOfDeviceMemory => {
193                 SupportedExtensionsError::OomError(OomError::from(err))
194             }
195             _ => panic!("unexpected error: {:?}", err),
196         }
197     }
198 }
199 
200 /// An error that can happen when enabling an extension on an instance or device.
201 #[derive(Clone, Copy, Debug)]
202 pub struct ExtensionRestrictionError {
203     /// The extension in question.
204     pub extension: &'static str,
205     /// The restriction that was not met.
206     pub restriction: ExtensionRestriction,
207 }
208 
209 impl error::Error for ExtensionRestrictionError {}
210 
211 impl fmt::Display for ExtensionRestrictionError {
212     #[inline]
fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error>213     fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
214         write!(
215             fmt,
216             "a restriction for the extension {} was not met: {}",
217             self.extension, self.restriction,
218         )
219     }
220 }
221 
222 #[derive(Clone, Copy, Debug)]
223 pub enum ExtensionRestriction {
224     /// Not supported by the loader or physical device.
225     NotSupported,
226     /// Requires a minimum Vulkan API version.
227     RequiresCore(Version),
228     /// Requires a device extension to be enabled.
229     RequiresDeviceExtension(&'static str),
230     /// Requires an instance extension to be enabled.
231     RequiresInstanceExtension(&'static str),
232     /// Required to be enabled by the physical device.
233     RequiredIfSupported,
234     /// Requires a device extension to be disabled.
235     ConflictsDeviceExtension(&'static str),
236 }
237 
238 impl fmt::Display for ExtensionRestriction {
239     #[inline]
fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error>240     fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
241         match *self {
242             ExtensionRestriction::NotSupported => {
243                 write!(fmt, "not supported by the loader or physical device")
244             }
245             ExtensionRestriction::RequiresCore(version) => {
246                 write!(
247                     fmt,
248                     "requires Vulkan API version {}.{}",
249                     version.major, version.minor
250                 )
251             }
252             ExtensionRestriction::RequiresDeviceExtension(ext) => {
253                 write!(fmt, "requires device extension {} to be enabled", ext)
254             }
255             ExtensionRestriction::RequiresInstanceExtension(ext) => {
256                 write!(fmt, "requires instance extension {} to be enabled", ext)
257             }
258             ExtensionRestriction::RequiredIfSupported => {
259                 write!(fmt, "required to be enabled by the physical device")
260             }
261             ExtensionRestriction::ConflictsDeviceExtension(ext) => {
262                 write!(fmt, "requires device extension {} to be disabled", ext)
263             }
264         }
265     }
266 }
267 
268 /// This helper type can only be instantiated inside this module.
269 #[doc(hidden)]
270 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
271 pub struct Unbuildable(pub(crate) ());
272