• 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::check_errors;
11 pub use crate::extensions::{
12     ExtensionRestriction, ExtensionRestrictionError, SupportedExtensionsError,
13 };
14 use crate::instance::loader;
15 use crate::instance::loader::LoadingError;
16 use std::ffi::CStr;
17 use std::ptr;
18 
19 macro_rules! instance_extensions {
20     (
21         $($member:ident => {
22             doc: $doc:expr,
23             raw: $raw:expr,
24             requires_core: $requires_core:expr,
25             requires_instance_extensions: [$($requires_instance_extension:ident),*]$(,)?
26         },)*
27     ) => (
28         extensions! {
29             InstanceExtensions,
30             $($member => {
31                 doc: $doc,
32                 raw: $raw,
33                 requires_core: $requires_core,
34                 requires_device_extensions: [],
35                 requires_instance_extensions: [$($requires_instance_extension),*],
36             },)*
37         }
38 
39         impl InstanceExtensions {
40             /// Checks enabled extensions against the instance version and each other.
41             pub(super) fn check_requirements(
42                 &self,
43                 supported: &InstanceExtensions,
44                 api_version: crate::Version,
45             ) -> Result<(), crate::extensions::ExtensionRestrictionError> {
46                 $(
47                     if self.$member {
48                         if !supported.$member {
49                             return Err(crate::extensions::ExtensionRestrictionError {
50                                 extension: stringify!($member),
51                                 restriction: crate::extensions::ExtensionRestriction::NotSupported,
52                             });
53                         }
54 
55                         if api_version < $requires_core {
56                             return Err(crate::extensions::ExtensionRestrictionError {
57                                 extension: stringify!($member),
58                                 restriction: crate::extensions::ExtensionRestriction::RequiresCore($requires_core),
59                             });
60                         } else {
61                             $(
62                                 if !self.$requires_instance_extension {
63                                     return Err(crate::extensions::ExtensionRestrictionError {
64                                         extension: stringify!($member),
65                                         restriction: crate::extensions::ExtensionRestriction::RequiresInstanceExtension(stringify!($requires_instance_extension)),
66                                     });
67                                 }
68                             )*
69                         }
70                     }
71                 )*
72                 Ok(())
73             }
74         }
75     );
76 }
77 
78 pub use crate::autogen::InstanceExtensions;
79 pub(crate) use instance_extensions;
80 
81 impl InstanceExtensions {
82     /// See the docs of supported_by_core().
supported_by_core_raw() -> Result<Self, SupportedExtensionsError>83     pub fn supported_by_core_raw() -> Result<Self, SupportedExtensionsError> {
84         InstanceExtensions::supported_by_core_raw_with_loader(loader::auto_loader()?)
85     }
86 
87     /// Returns an `InstanceExtensions` object with extensions supported by the core driver.
supported_by_core() -> Result<Self, LoadingError>88     pub fn supported_by_core() -> Result<Self, LoadingError> {
89         match InstanceExtensions::supported_by_core_raw() {
90             Ok(l) => Ok(l),
91             Err(SupportedExtensionsError::LoadingError(e)) => Err(e),
92             Err(SupportedExtensionsError::OomError(e)) => panic!("{:?}", e),
93         }
94     }
95 
96     /// Same as `supported_by_core`, but allows specifying a loader.
supported_by_core_with_loader<L>( ptrs: &loader::FunctionPointers<L>, ) -> Result<Self, LoadingError> where L: loader::Loader,97     pub fn supported_by_core_with_loader<L>(
98         ptrs: &loader::FunctionPointers<L>,
99     ) -> Result<Self, LoadingError>
100     where
101         L: loader::Loader,
102     {
103         match InstanceExtensions::supported_by_core_raw_with_loader(ptrs) {
104             Ok(l) => Ok(l),
105             Err(SupportedExtensionsError::LoadingError(e)) => Err(e),
106             Err(SupportedExtensionsError::OomError(e)) => panic!("{:?}", e),
107         }
108     }
109 
110     /// See the docs of supported_by_core().
supported_by_core_raw_with_loader<L>( ptrs: &loader::FunctionPointers<L>, ) -> Result<Self, SupportedExtensionsError> where L: loader::Loader,111     pub fn supported_by_core_raw_with_loader<L>(
112         ptrs: &loader::FunctionPointers<L>,
113     ) -> Result<Self, SupportedExtensionsError>
114     where
115         L: loader::Loader,
116     {
117         let fns = ptrs.fns();
118 
119         let properties: Vec<ash::vk::ExtensionProperties> = unsafe {
120             let mut num = 0;
121             check_errors(fns.v1_0.enumerate_instance_extension_properties(
122                 ptr::null(),
123                 &mut num,
124                 ptr::null_mut(),
125             ))?;
126 
127             let mut properties = Vec::with_capacity(num as usize);
128             check_errors(fns.v1_0.enumerate_instance_extension_properties(
129                 ptr::null(),
130                 &mut num,
131                 properties.as_mut_ptr(),
132             ))?;
133             properties.set_len(num as usize);
134             properties
135         };
136 
137         Ok(Self::from(properties.iter().map(|property| unsafe {
138             CStr::from_ptr(property.extension_name.as_ptr())
139         })))
140     }
141 }
142 
143 #[cfg(test)]
144 mod tests {
145     use crate::instance::InstanceExtensions;
146     use std::ffi::CString;
147 
148     #[test]
empty_extensions()149     fn empty_extensions() {
150         let i: Vec<CString> = (&InstanceExtensions::none()).into();
151         assert!(i.iter().next().is_none());
152     }
153 }
154