diff options
Diffstat (limited to 'src/device/extensions.rs')
-rw-r--r-- | src/device/extensions.rs | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/src/device/extensions.rs b/src/device/extensions.rs new file mode 100644 index 0000000..b6d0c44 --- /dev/null +++ b/src/device/extensions.rs @@ -0,0 +1,174 @@ +// 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::device::physical::PhysicalDevice; +pub use crate::extensions::{ + ExtensionRestriction, ExtensionRestrictionError, SupportedExtensionsError, +}; + +macro_rules! device_extensions { + ( + $($member:ident => { + doc: $doc:expr, + raw: $raw:expr, + requires_core: $requires_core:expr, + requires_device_extensions: [$($requires_device_extension:ident),*], + requires_instance_extensions: [$($requires_instance_extension:ident),*], + required_if_supported: $required_if_supported:expr, + conflicts_device_extensions: [$($conflicts_device_extension:ident),*], + },)* + ) => ( + extensions! { + DeviceExtensions, + $( $member => { + doc: $doc, + raw: $raw, + requires_core: $requires_core, + requires_device_extensions: [$($requires_device_extension),*], + requires_instance_extensions: [$($requires_instance_extension),*], + },)* + } + + impl DeviceExtensions { + /// Checks enabled extensions against the device version, instance extensions and each other. + pub(super) fn check_requirements( + &self, + supported: &DeviceExtensions, + api_version: crate::Version, + instance_extensions: &InstanceExtensions, + ) -> 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), + }); + } + + $( + if !self.$requires_device_extension { + return Err(crate::extensions::ExtensionRestrictionError { + extension: stringify!($member), + restriction: crate::extensions::ExtensionRestriction::RequiresDeviceExtension(stringify!($requires_device_extension)), + }); + } + )* + + $( + if !instance_extensions.$requires_instance_extension { + return Err(crate::extensions::ExtensionRestrictionError { + extension: stringify!($member), + restriction: crate::extensions::ExtensionRestriction::RequiresInstanceExtension(stringify!($requires_instance_extension)), + }); + } + )* + + $( + if self.$conflicts_device_extension { + return Err(crate::extensions::ExtensionRestrictionError { + extension: stringify!($member), + restriction: crate::extensions::ExtensionRestriction::ConflictsDeviceExtension(stringify!($conflicts_device_extension)), + }); + } + )* + } else { + if $required_if_supported && supported.$member { + return Err(crate::extensions::ExtensionRestrictionError { + extension: stringify!($member), + restriction: crate::extensions::ExtensionRestriction::RequiredIfSupported, + }); + } + } + )* + Ok(()) + } + + pub(crate) fn required_if_supported_extensions() -> Self { + Self { + $( + $member: $required_if_supported, + )* + _unbuildable: crate::extensions::Unbuildable(()) + } + } + } + ); +} + +pub use crate::autogen::DeviceExtensions; +pub(crate) use device_extensions; + +impl DeviceExtensions { + /// See the docs of supported_by_device(). + #[deprecated( + since = "0.25", + note = "Use PhysicalDevice::supported_extensions instead" + )] + pub fn supported_by_device_raw( + physical_device: PhysicalDevice, + ) -> Result<Self, SupportedExtensionsError> { + Ok(*physical_device.supported_extensions()) + } + + /// Returns a `DeviceExtensions` object with extensions supported by the `PhysicalDevice`. + #[deprecated( + since = "0.25", + note = "Use PhysicalDevice::supported_extensions instead" + )] + pub fn supported_by_device(physical_device: PhysicalDevice) -> Self { + *physical_device.supported_extensions() + } + + /// Returns a `DeviceExtensions` object with extensions required as well as supported by the `PhysicalDevice`. + /// They are needed to be passed to `Device::new(...)`. + #[deprecated( + since = "0.25", + note = "Use PhysicalDevice::required_extensions instead" + )] + pub fn required_extensions(physical_device: PhysicalDevice) -> Self { + *physical_device.required_extensions() + } +} + +/// This helper type can only be instantiated inside this module. +/// See `*Extensions::_unbuildable`. +#[doc(hidden)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub struct Unbuildable(()); + +#[cfg(test)] +mod tests { + use crate::device::DeviceExtensions; + use std::ffi::CString; + + #[test] + fn empty_extensions() { + let d: Vec<CString> = (&DeviceExtensions::none()).into(); + assert!(d.iter().next().is_none()); + } + + #[test] + fn required_if_supported_extensions() { + assert_eq!( + DeviceExtensions::required_if_supported_extensions(), + DeviceExtensions { + khr_portability_subset: true, + ..DeviceExtensions::none() + } + ) + } +} |