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