blob: 822eb67e0b877c897d179f7eef45c48c5a0588a9 [file] [log] [blame]
// 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) ());