aboutsummaryrefslogtreecommitdiff
path: root/src/extensions.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/extensions.rs')
-rw-r--r--src/extensions.rs271
1 files changed, 271 insertions, 0 deletions
diff --git a/src/extensions.rs b/src/extensions.rs
new file mode 100644
index 0000000..822eb67
--- /dev/null
+++ b/src/extensions.rs
@@ -0,0 +1,271 @@
+// 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::instance::loader::LoadingError;
+use crate::Error;
+use crate::OomError;
+use crate::Version;
+use std::error;
+use std::fmt;
+
+macro_rules! extensions {
+ (
+ $sname:ident,
+ $($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),*]$(,)?
+ },)*
+ ) => (
+ /// List of extensions that are enabled or available.
+ #[derive(Copy, Clone, PartialEq, Eq)]
+ pub struct $sname {
+ $(
+ #[doc = $doc]
+ pub $member: bool,
+ )*
+
+ /// This field ensures that an instance of this `Extensions` struct
+ /// can only be created through Vulkano functions and the update
+ /// syntax. This way, extensions can be added to Vulkano without
+ /// breaking existing code.
+ pub _unbuildable: crate::extensions::Unbuildable,
+ }
+
+ impl $sname {
+ /// Returns an `Extensions` object with all members set to `false`.
+ #[inline]
+ pub const fn none() -> $sname {
+ $sname {
+ $($member: false,)*
+ _unbuildable: crate::extensions::Unbuildable(())
+ }
+ }
+
+ /// Returns true if `self` is a superset of the parameter.
+ ///
+ /// That is, for each extension of the parameter that is true, the corresponding value
+ /// in self is true as well.
+ pub fn is_superset_of(&self, other: &$sname) -> bool {
+ $((self.$member == true || other.$member == false))&&+
+ }
+
+ /// Returns the union of this list and another list.
+ #[inline]
+ pub const fn union(&self, other: &$sname) -> $sname {
+ $sname {
+ $(
+ $member: self.$member || other.$member,
+ )*
+ _unbuildable: crate::extensions::Unbuildable(())
+ }
+ }
+
+ /// Returns the intersection of this list and another list.
+ #[inline]
+ pub const fn intersection(&self, other: &$sname) -> $sname {
+ $sname {
+ $(
+ $member: self.$member && other.$member,
+ )*
+ _unbuildable: crate::extensions::Unbuildable(())
+ }
+ }
+
+ /// Returns the difference of another list from this list.
+ #[inline]
+ pub const fn difference(&self, other: &$sname) -> $sname {
+ $sname {
+ $(
+ $member: self.$member && !other.$member,
+ )*
+ _unbuildable: crate::extensions::Unbuildable(())
+ }
+ }
+ }
+
+ impl std::fmt::Debug for $sname {
+ #[allow(unused_assignments)]
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+ write!(f, "[")?;
+
+ let mut first = true;
+
+ $(
+ if self.$member {
+ if !first { write!(f, ", ")? }
+ else { first = false; }
+ f.write_str(std::str::from_utf8($raw).unwrap())?;
+ }
+ )*
+
+ write!(f, "]")
+ }
+ }
+
+ impl<'a, I> From<I> for $sname where I: IntoIterator<Item = &'a std::ffi::CStr> {
+ fn from(names: I) -> Self {
+ let mut extensions = Self::none();
+ for name in names {
+ match name.to_bytes() {
+ $(
+ $raw => { extensions.$member = true; }
+ )*
+ _ => (),
+ }
+ }
+ extensions
+ }
+ }
+
+ impl<'a> From<&'a $sname> for Vec<std::ffi::CString> {
+ fn from(x: &'a $sname) -> Self {
+ let mut data = Self::new();
+ $(if x.$member { data.push(std::ffi::CString::new(&$raw[..]).unwrap()); })*
+ data
+ }
+ }
+ );
+}
+
+/// Error that can happen when loading the list of layers.
+#[derive(Clone, Debug)]
+pub enum SupportedExtensionsError {
+ /// Failed to load the Vulkan shared library.
+ LoadingError(LoadingError),
+ /// Not enough memory.
+ OomError(OomError),
+}
+
+impl error::Error for SupportedExtensionsError {
+ #[inline]
+ fn source(&self) -> Option<&(dyn error::Error + 'static)> {
+ match *self {
+ SupportedExtensionsError::LoadingError(ref err) => Some(err),
+ SupportedExtensionsError::OomError(ref err) => Some(err),
+ }
+ }
+}
+
+impl fmt::Display for SupportedExtensionsError {
+ #[inline]
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+ write!(
+ fmt,
+ "{}",
+ match *self {
+ SupportedExtensionsError::LoadingError(_) =>
+ "failed to load the Vulkan shared library",
+ SupportedExtensionsError::OomError(_) => "not enough memory available",
+ }
+ )
+ }
+}
+
+impl From<OomError> for SupportedExtensionsError {
+ #[inline]
+ fn from(err: OomError) -> SupportedExtensionsError {
+ SupportedExtensionsError::OomError(err)
+ }
+}
+
+impl From<LoadingError> for SupportedExtensionsError {
+ #[inline]
+ fn from(err: LoadingError) -> SupportedExtensionsError {
+ SupportedExtensionsError::LoadingError(err)
+ }
+}
+
+impl From<Error> for SupportedExtensionsError {
+ #[inline]
+ fn from(err: Error) -> SupportedExtensionsError {
+ match err {
+ err @ Error::OutOfHostMemory => SupportedExtensionsError::OomError(OomError::from(err)),
+ err @ Error::OutOfDeviceMemory => {
+ SupportedExtensionsError::OomError(OomError::from(err))
+ }
+ _ => panic!("unexpected error: {:?}", err),
+ }
+ }
+}
+
+/// An error that can happen when enabling an extension on an instance or device.
+#[derive(Clone, Copy, Debug)]
+pub struct ExtensionRestrictionError {
+ /// The extension in question.
+ pub extension: &'static str,
+ /// The restriction that was not met.
+ pub restriction: ExtensionRestriction,
+}
+
+impl error::Error for ExtensionRestrictionError {}
+
+impl fmt::Display for ExtensionRestrictionError {
+ #[inline]
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+ write!(
+ fmt,
+ "a restriction for the extension {} was not met: {}",
+ self.extension, self.restriction,
+ )
+ }
+}
+
+#[derive(Clone, Copy, Debug)]
+pub enum ExtensionRestriction {
+ /// Not supported by the loader or physical device.
+ NotSupported,
+ /// Requires a minimum Vulkan API version.
+ RequiresCore(Version),
+ /// Requires a device extension to be enabled.
+ RequiresDeviceExtension(&'static str),
+ /// Requires an instance extension to be enabled.
+ RequiresInstanceExtension(&'static str),
+ /// Required to be enabled by the physical device.
+ RequiredIfSupported,
+ /// Requires a device extension to be disabled.
+ ConflictsDeviceExtension(&'static str),
+}
+
+impl fmt::Display for ExtensionRestriction {
+ #[inline]
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+ match *self {
+ ExtensionRestriction::NotSupported => {
+ write!(fmt, "not supported by the loader or physical device")
+ }
+ ExtensionRestriction::RequiresCore(version) => {
+ write!(
+ fmt,
+ "requires Vulkan API version {}.{}",
+ version.major, version.minor
+ )
+ }
+ ExtensionRestriction::RequiresDeviceExtension(ext) => {
+ write!(fmt, "requires device extension {} to be enabled", ext)
+ }
+ ExtensionRestriction::RequiresInstanceExtension(ext) => {
+ write!(fmt, "requires instance extension {} to be enabled", ext)
+ }
+ ExtensionRestriction::RequiredIfSupported => {
+ write!(fmt, "required to be enabled by the physical device")
+ }
+ ExtensionRestriction::ConflictsDeviceExtension(ext) => {
+ write!(fmt, "requires device extension {} to be disabled", ext)
+ }
+ }
+ }
+}
+
+/// This helper type can only be instantiated inside this module.
+#[doc(hidden)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+pub struct Unbuildable(pub(crate) ());