// Copyright (c) 2016 The vulkano developers // Licensed under the Apache License, Version 2.0 // or the MIT // license , // 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 { 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 { 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( ptrs: &loader::FunctionPointers, ) -> Result 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( ptrs: &loader::FunctionPointers, ) -> Result where L: loader::Loader, { let fns = ptrs.fns(); let properties: Vec = 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 = (&InstanceExtensions::none()).into(); assert!(i.iter().next().is_none()); } }