diff options
Diffstat (limited to 'src/instance/extensions.rs')
-rw-r--r-- | src/instance/extensions.rs | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/src/instance/extensions.rs b/src/instance/extensions.rs new file mode 100644 index 0000000..dab0b12 --- /dev/null +++ b/src/instance/extensions.rs @@ -0,0 +1,153 @@ +// Copyright (c) 2016 The vulkano developers +// Licensed under the Apache License, Version 2.0 +// <LICENSE-APACHE or +// https://www.apache.org/licenses/LICENSE-2.0> or the MIT +// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, +// at your option. All files in the project carrying such +// notice may not be copied, modified, or distributed except +// according to those terms. + +use crate::check_errors; +pub use crate::extensions::{ + ExtensionRestriction, ExtensionRestrictionError, SupportedExtensionsError, +}; +use crate::instance::loader; +use crate::instance::loader::LoadingError; +use std::ffi::CStr; +use std::ptr; + +macro_rules! instance_extensions { + ( + $($member:ident => { + doc: $doc:expr, + raw: $raw:expr, + requires_core: $requires_core:expr, + requires_instance_extensions: [$($requires_instance_extension:ident),*]$(,)? + },)* + ) => ( + extensions! { + InstanceExtensions, + $($member => { + doc: $doc, + raw: $raw, + requires_core: $requires_core, + requires_device_extensions: [], + requires_instance_extensions: [$($requires_instance_extension),*], + },)* + } + + impl InstanceExtensions { + /// Checks enabled extensions against the instance version and each other. + pub(super) fn check_requirements( + &self, + supported: &InstanceExtensions, + api_version: crate::Version, + ) -> Result<(), crate::extensions::ExtensionRestrictionError> { + $( + if self.$member { + if !supported.$member { + return Err(crate::extensions::ExtensionRestrictionError { + extension: stringify!($member), + restriction: crate::extensions::ExtensionRestriction::NotSupported, + }); + } + + if api_version < $requires_core { + return Err(crate::extensions::ExtensionRestrictionError { + extension: stringify!($member), + restriction: crate::extensions::ExtensionRestriction::RequiresCore($requires_core), + }); + } else { + $( + if !self.$requires_instance_extension { + return Err(crate::extensions::ExtensionRestrictionError { + extension: stringify!($member), + restriction: crate::extensions::ExtensionRestriction::RequiresInstanceExtension(stringify!($requires_instance_extension)), + }); + } + )* + } + } + )* + Ok(()) + } + } + ); +} + +pub use crate::autogen::InstanceExtensions; +pub(crate) use instance_extensions; + +impl InstanceExtensions { + /// See the docs of supported_by_core(). + pub fn supported_by_core_raw() -> Result<Self, SupportedExtensionsError> { + InstanceExtensions::supported_by_core_raw_with_loader(loader::auto_loader()?) + } + + /// Returns an `InstanceExtensions` object with extensions supported by the core driver. + pub fn supported_by_core() -> Result<Self, LoadingError> { + match InstanceExtensions::supported_by_core_raw() { + Ok(l) => Ok(l), + Err(SupportedExtensionsError::LoadingError(e)) => Err(e), + Err(SupportedExtensionsError::OomError(e)) => panic!("{:?}", e), + } + } + + /// Same as `supported_by_core`, but allows specifying a loader. + pub fn supported_by_core_with_loader<L>( + ptrs: &loader::FunctionPointers<L>, + ) -> Result<Self, LoadingError> + where + L: loader::Loader, + { + match InstanceExtensions::supported_by_core_raw_with_loader(ptrs) { + Ok(l) => Ok(l), + Err(SupportedExtensionsError::LoadingError(e)) => Err(e), + Err(SupportedExtensionsError::OomError(e)) => panic!("{:?}", e), + } + } + + /// See the docs of supported_by_core(). + pub fn supported_by_core_raw_with_loader<L>( + ptrs: &loader::FunctionPointers<L>, + ) -> Result<Self, SupportedExtensionsError> + where + L: loader::Loader, + { + let fns = ptrs.fns(); + + let properties: Vec<ash::vk::ExtensionProperties> = unsafe { + let mut num = 0; + check_errors(fns.v1_0.enumerate_instance_extension_properties( + ptr::null(), + &mut num, + ptr::null_mut(), + ))?; + + let mut properties = Vec::with_capacity(num as usize); + check_errors(fns.v1_0.enumerate_instance_extension_properties( + ptr::null(), + &mut num, + properties.as_mut_ptr(), + ))?; + properties.set_len(num as usize); + properties + }; + + Ok(Self::from(properties.iter().map(|property| unsafe { + CStr::from_ptr(property.extension_name.as_ptr()) + }))) + } +} + +#[cfg(test)] +mod tests { + use crate::instance::InstanceExtensions; + use std::ffi::CString; + + #[test] + fn empty_extensions() { + let i: Vec<CString> = (&InstanceExtensions::none()).into(); + assert!(i.iter().next().is_none()); + } +} |