diff --git a/vulkano-shaders/src/structs.rs b/vulkano-shaders/src/structs.rs index 8c7597d8aa..17682f30d9 100644 --- a/vulkano-shaders/src/structs.rs +++ b/vulkano-shaders/src/structs.rs @@ -251,27 +251,30 @@ fn write_impls<'a>( ) -> impl Iterator + 'a { let struct_ident = format_ident!("{}", struct_name); - (types_meta.partial_eq.then(|| { - let fields = rust_members - .iter() - .filter(|Member { is_dummy, .. }| !is_dummy) - .map(|Member { name, .. }| { - quote! { - if self.#name != other.#name { - return false + (types_meta + .partial_eq + .then(|| { + let fields = rust_members + .iter() + .filter(|Member { is_dummy, .. }| !is_dummy) + .map(|Member { name, .. }| { + quote! { + if self.#name != other.#name { + return false + } } - } - }); + }); - quote! { - impl PartialEq for #struct_ident { - fn eq(&self, other: &Self) -> bool { - #( #fields )* - true + quote! { + impl PartialEq for #struct_ident { + fn eq(&self, other: &Self) -> bool { + #( #fields )* + true + } } } - } - }).into_iter()) + }) + .into_iter()) .chain(types_meta.debug.then(|| { let fields = rust_members .iter() @@ -283,8 +286,8 @@ fn write_impls<'a>( quote! { impl std::fmt::Debug for #struct_ident { - fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { - formatter + fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { + f .debug_struct(#struct_name) #( #fields )* .finish() @@ -303,8 +306,8 @@ fn write_impls<'a>( quote! { impl std::fmt::Display for #struct_ident { - fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { - formatter + fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { + f .debug_struct(#struct_name) #( #fields )* .finish() @@ -323,7 +326,12 @@ fn write_impls<'a>( } } })) - .chain(types_meta.impls.iter().map(move |i| quote!{ #i for #struct_ident {} })) + .chain( + types_meta + .impls + .iter() + .map(move |i| quote! { #i for #struct_ident {} }), + ) } fn has_defined_layout(spirv: &Spirv, struct_id: Id) -> bool { diff --git a/vulkano-win/src/winit.rs b/vulkano-win/src/winit.rs index 2af6de9c81..de41d1e387 100644 --- a/vulkano-win/src/winit.rs +++ b/vulkano-win/src/winit.rs @@ -1,4 +1,10 @@ -use std::{borrow::Borrow, error::Error, fmt, rc::Rc, sync::Arc}; +use std::{ + borrow::Borrow, + error::Error, + fmt::{Display, Error as FmtError, Formatter}, + rc::Rc, + sync::Arc, +}; use vulkano::{ instance::{Instance, InstanceExtensions}, swapchain::{Surface, SurfaceCreationError}, @@ -80,11 +86,11 @@ impl Error for CreationError { } } -impl fmt::Display for CreationError { +impl Display for CreationError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { write!( - fmt, + f, "{}", match *self { CreationError::SurfaceCreationError(_) => "error while creating the surface", diff --git a/vulkano/autogen/extensions.rs b/vulkano/autogen/extensions.rs index 6505cb2e4e..4266c7e7aa 100644 --- a/vulkano/autogen/extensions.rs +++ b/vulkano/autogen/extensions.rs @@ -105,7 +105,7 @@ fn device_extensions_output(members: &[ExtensionsMember]) -> TokenStream { let requires_items = requires.iter().map(|require| { let require_items = require.api_version.iter().map(|version| { let version = format_ident!("V{}_{}", version.0, version.1); - quote! { api_version >= Version::#version } + quote! { api_version >= crate::Version::#version } }).chain(require.instance_extensions.iter().map(|ext| { quote! { instance_extensions.#ext } })).chain(require.device_extensions.iter().map(|ext| { @@ -114,19 +114,20 @@ fn device_extensions_output(members: &[ExtensionsMember]) -> TokenStream { let api_version_items = require.api_version.as_ref().map(|version| { let version = format_ident!("V{}_{}", version.0, version.1); - quote! { Some(Version::#version) } + quote! { Some(crate::Version::#version) } }).unwrap_or_else(|| quote!{ None }); let device_extensions_items = require.device_extensions.iter().map(|ext| ext.to_string()); let instance_extensions_items = require.instance_extensions.iter().map(|ext| ext.to_string()); quote! { if !(#(#require_items)||*) { - return Err(ExtensionRestrictionError { + return Err(crate::device::ExtensionRestrictionError { extension: #name_string, - restriction: ExtensionRestriction::Requires(OneOfRequirements { + restriction: crate::device::ExtensionRestriction::Requires(crate::RequiresOneOf { api_version: #api_version_items, device_extensions: &[#(#device_extensions_items),*], instance_extensions: &[#(#instance_extensions_items),*], + ..Default::default() }), }) } @@ -136,9 +137,9 @@ fn device_extensions_output(members: &[ExtensionsMember]) -> TokenStream { let string = extension.to_string(); quote! { if self.#extension { - return Err(ExtensionRestrictionError { + return Err(crate::device::ExtensionRestrictionError { extension: #name_string, - restriction: ExtensionRestriction::ConflictsDeviceExtension(#string), + restriction: crate::device::ExtensionRestriction::ConflictsDeviceExtension(#string), }); } } @@ -146,9 +147,9 @@ fn device_extensions_output(members: &[ExtensionsMember]) -> TokenStream { let required_if_supported = if *required_if_supported { quote! { if supported.#name { - return Err(ExtensionRestrictionError { + return Err(crate::device::ExtensionRestrictionError { extension: #name_string, - restriction: ExtensionRestriction::RequiredIfSupported, + restriction: crate::device::ExtensionRestriction::RequiredIfSupported, }); } } @@ -159,9 +160,9 @@ fn device_extensions_output(members: &[ExtensionsMember]) -> TokenStream { quote! { if self.#name { if !supported.#name { - return Err(ExtensionRestrictionError { + return Err(crate::device::ExtensionRestrictionError { extension: #name_string, - restriction: ExtensionRestriction::NotSupported, + restriction: crate::device::ExtensionRestriction::NotSupported, }); } @@ -181,9 +182,9 @@ fn device_extensions_output(members: &[ExtensionsMember]) -> TokenStream { pub(super) fn check_requirements( &self, supported: &DeviceExtensions, - api_version: Version, - instance_extensions: &InstanceExtensions, - ) -> Result<(), ExtensionRestrictionError> { + api_version: crate::Version, + instance_extensions: &crate::instance::InstanceExtensions, + ) -> Result<(), crate::device::ExtensionRestrictionError> { let device_extensions = self; #(#check_requirements_items)* Ok(()) @@ -207,7 +208,7 @@ fn instance_extensions_output(members: &[ExtensionsMember]) -> TokenStream { .iter() .map(|version| { let version = format_ident!("V{}_{}", version.0, version.1); - quote! { api_version >= Version::#version } + quote! { api_version >= crate::Version::#version } }) .chain(require.instance_extensions.iter().map(|ext| { quote! { instance_extensions.#ext } @@ -221,7 +222,7 @@ fn instance_extensions_output(members: &[ExtensionsMember]) -> TokenStream { .as_ref() .map(|version| { let version = format_ident!("V{}_{}", version.0, version.1); - quote! { Some(Version::#version) } + quote! { Some(crate::Version::#version) } }) .unwrap_or_else(|| quote! { None }); let device_extensions_items = @@ -233,12 +234,13 @@ fn instance_extensions_output(members: &[ExtensionsMember]) -> TokenStream { quote! { if !(#(#require_items)||*) { - return Err(ExtensionRestrictionError { + return Err(crate::instance::ExtensionRestrictionError { extension: #name_string, - restriction: ExtensionRestriction::Requires(OneOfRequirements { + restriction: crate::instance::ExtensionRestriction::Requires(crate::RequiresOneOf { api_version: #api_version_items, device_extensions: &[#(#device_extensions_items),*], instance_extensions: &[#(#instance_extensions_items),*], + ..Default::default() }), }) } @@ -248,9 +250,9 @@ fn instance_extensions_output(members: &[ExtensionsMember]) -> TokenStream { quote! { if self.#name { if !supported.#name { - return Err(ExtensionRestrictionError { + return Err(crate::instance::ExtensionRestrictionError { extension: #name_string, - restriction: ExtensionRestriction::NotSupported, + restriction: crate::instance::ExtensionRestriction::NotSupported, }); } @@ -267,8 +269,8 @@ fn instance_extensions_output(members: &[ExtensionsMember]) -> TokenStream { pub(super) fn check_requirements( &self, supported: &InstanceExtensions, - api_version: Version, - ) -> Result<(), ExtensionRestrictionError> { + api_version: crate::Version, + ) -> Result<(), crate::instance::ExtensionRestrictionError> { let instance_extensions = self; #(#check_requirements_items)* Ok(()) @@ -348,7 +350,7 @@ fn extensions_common_output(struct_name: Ident, members: &[ExtensionsMember]) -> let from_extensions_for_vec_cstring_items = members.iter().map(|ExtensionsMember { name, raw, .. }| { quote! { - if x.#name { data.push(CString::new(#raw).unwrap()); } + if x.#name { data.push(std::ffi::CString::new(#raw).unwrap()); } } }); @@ -441,7 +443,7 @@ fn extensions_common_output(struct_name: Ident, members: &[ExtensionsMember]) -> } } - impl BitAnd for #struct_name { + impl std::ops::BitAnd for #struct_name { type Output = #struct_name; #[inline] @@ -450,14 +452,14 @@ fn extensions_common_output(struct_name: Ident, members: &[ExtensionsMember]) -> } } - impl BitAndAssign for #struct_name { + impl std::ops::BitAndAssign for #struct_name { #[inline] fn bitand_assign(&mut self, rhs: Self) { *self = self.union(&rhs); } } - impl BitOr for #struct_name { + impl std::ops::BitOr for #struct_name { type Output = #struct_name; #[inline] @@ -466,14 +468,14 @@ fn extensions_common_output(struct_name: Ident, members: &[ExtensionsMember]) -> } } - impl BitOrAssign for #struct_name { + impl std::ops::BitOrAssign for #struct_name { #[inline] fn bitor_assign(&mut self, rhs: Self) { *self = self.intersection(&rhs); } } - impl BitXor for #struct_name { + impl std::ops::BitXor for #struct_name { type Output = #struct_name; #[inline] @@ -482,14 +484,14 @@ fn extensions_common_output(struct_name: Ident, members: &[ExtensionsMember]) -> } } - impl BitXorAssign for #struct_name { + impl std::ops::BitXorAssign for #struct_name { #[inline] fn bitxor_assign(&mut self, rhs: Self) { *self = self.symmetric_difference(&rhs); } } - impl Sub for #struct_name { + impl std::ops::Sub for #struct_name { type Output = #struct_name; #[inline] @@ -498,7 +500,7 @@ fn extensions_common_output(struct_name: Ident, members: &[ExtensionsMember]) -> } } - impl SubAssign for #struct_name { + impl std::ops::SubAssign for #struct_name { #[inline] fn sub_assign(&mut self, rhs: Self) { *self = self.difference(&rhs); @@ -507,7 +509,7 @@ fn extensions_common_output(struct_name: Ident, members: &[ExtensionsMember]) -> impl std::fmt::Debug for #struct_name { #[allow(unused_assignments)] - fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { + fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { write!(f, "[")?; let mut first = true; @@ -517,7 +519,7 @@ fn extensions_common_output(struct_name: Ident, members: &[ExtensionsMember]) -> } } - impl<'a, I> From for #struct_name where I: IntoIterator { + impl<'a, I> From for #struct_name where I: IntoIterator { fn from(names: I) -> Self { let mut extensions = Self::empty(); for name in names { @@ -530,7 +532,7 @@ fn extensions_common_output(struct_name: Ident, members: &[ExtensionsMember]) -> } } - impl<'a> From<&'a #struct_name> for Vec { + impl<'a> From<&'a #struct_name> for Vec { fn from(x: &'a #struct_name) -> Self { let mut data = Self::new(); #(#from_extensions_for_vec_cstring_items)* diff --git a/vulkano/autogen/features.rs b/vulkano/autogen/features.rs index 02c028276d..05da3cdc4f 100644 --- a/vulkano/autogen/features.rs +++ b/vulkano/autogen/features.rs @@ -113,9 +113,9 @@ fn features_output(members: &[FeaturesMember]) -> TokenStream { let string = feature.to_string(); quote! { if !self.#feature { - return Err(FeatureRestrictionError { + return Err(crate::device::FeatureRestrictionError { feature: #name_string, - restriction: FeatureRestriction::RequiresFeature(#string), + restriction: crate::device::FeatureRestriction::RequiresFeature(#string), }); } } @@ -124,9 +124,9 @@ fn features_output(members: &[FeaturesMember]) -> TokenStream { let string = feature.to_string(); quote! { if self.#feature { - return Err(FeatureRestrictionError { + return Err(crate::device::FeatureRestrictionError { feature: #name_string, - restriction: FeatureRestriction::ConflictsFeature(#string), + restriction: crate::device::FeatureRestriction::ConflictsFeature(#string), }); } } @@ -135,10 +135,10 @@ fn features_output(members: &[FeaturesMember]) -> TokenStream { required_by_extensions.iter().map(|(version, extension)| { let string = extension.to_string(); quote! { - if extensions.#extension && api_version >= Version::#version { - return Err(FeatureRestrictionError { + if extensions.#extension && api_version >= crate::Version::#version { + return Err(crate::device::FeatureRestrictionError { feature: #name_string, - restriction: FeatureRestriction::RequiredByExtension(#string), + restriction: crate::device::FeatureRestriction::RequiredByExtension(#string), }); } } @@ -146,9 +146,9 @@ fn features_output(members: &[FeaturesMember]) -> TokenStream { quote! { if self.#name { if !supported.#name { - return Err(FeatureRestrictionError { + return Err(crate::device::FeatureRestrictionError { feature: #name_string, - restriction: FeatureRestriction::NotSupported, + restriction: crate::device::FeatureRestriction::NotSupported, }); } @@ -332,9 +332,9 @@ fn features_output(members: &[FeaturesMember]) -> TokenStream { pub(super) fn check_requirements( &self, supported: &Features, - api_version: Version, - extensions: &DeviceExtensions, - ) -> Result<(), FeatureRestrictionError> { + api_version: crate::Version, + extensions: &crate::device::DeviceExtensions, + ) -> Result<(), crate::device::FeatureRestrictionError> { #(#check_requirements_items)* Ok(()) } @@ -420,7 +420,7 @@ fn features_output(members: &[FeaturesMember]) -> TokenStream { } } - impl BitAnd for Features { + impl std::ops::BitAnd for Features { type Output = Features; #[inline] @@ -429,14 +429,14 @@ fn features_output(members: &[FeaturesMember]) -> TokenStream { } } - impl BitAndAssign for Features { + impl std::ops::BitAndAssign for Features { #[inline] fn bitand_assign(&mut self, rhs: Self) { *self = self.intersection(&rhs); } } - impl BitOr for Features { + impl std::ops::BitOr for Features { type Output = Features; #[inline] @@ -445,14 +445,14 @@ fn features_output(members: &[FeaturesMember]) -> TokenStream { } } - impl BitOrAssign for Features { + impl std::ops::BitOrAssign for Features { #[inline] fn bitor_assign(&mut self, rhs: Self) { *self = self.union(&rhs); } } - impl BitXor for Features { + impl std::ops::BitXor for Features { type Output = Features; #[inline] @@ -461,14 +461,14 @@ fn features_output(members: &[FeaturesMember]) -> TokenStream { } } - impl BitXorAssign for Features { + impl std::ops::BitXorAssign for Features { #[inline] fn bitxor_assign(&mut self, rhs: Self) { *self = self.symmetric_difference(&rhs); } } - impl Sub for Features { + impl std::ops::Sub for Features { type Output = Features; #[inline] @@ -477,7 +477,7 @@ fn features_output(members: &[FeaturesMember]) -> TokenStream { } } - impl SubAssign for Features { + impl std::ops::SubAssign for Features { #[inline] fn sub_assign(&mut self, rhs: Self) { *self = self.difference(&rhs); @@ -486,7 +486,7 @@ fn features_output(members: &[FeaturesMember]) -> TokenStream { impl std::fmt::Debug for Features { #[allow(unused_assignments)] - fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { + fn fmt(&self, f: &mut std::fmt:: Formatter) -> Result<(), std::fmt::Error> { write!(f, "[")?; let mut first = true; @@ -698,9 +698,9 @@ fn features_ffi_output(members: &[FeaturesFfiMember]) -> TokenStream { impl FeaturesFfi { pub(crate) fn make_chain( &mut self, - api_version: Version, - device_extensions: &DeviceExtensions, - _instance_extensions: &InstanceExtensions, + api_version: crate::Version, + device_extensions: &crate::device::DeviceExtensions, + _instance_extensions: &crate::instance::InstanceExtensions, ) { self.features_vulkan10 = Default::default(); let head = &mut self.features_vulkan10; @@ -732,7 +732,7 @@ fn features_ffi_members<'a>( .map(|provided_by| { if let Some(version) = provided_by.strip_prefix("VK_VERSION_") { let version = format_ident!("V{}", version); - quote! { api_version >= Version::#version } + quote! { api_version >= crate::Version::#version } } else { let member = format_ident!( "{}_extensions", diff --git a/vulkano/autogen/fns.rs b/vulkano/autogen/fns.rs index 072319d8c6..81be9af034 100644 --- a/vulkano/autogen/fns.rs +++ b/vulkano/autogen/fns.rs @@ -90,7 +90,7 @@ fn fns_output(extension_members: &[FnsMember], fns_level: &str, doc: &str) -> To impl std::fmt::Debug for #struct_name { #[inline] - fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { + fn fmt(&self, _f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { Ok(()) } } diff --git a/vulkano/src/buffer/cpu_access.rs b/vulkano/src/buffer/cpu_access.rs index 0772022820..64cc7a799b 100644 --- a/vulkano/src/buffer/cpu_access.rs +++ b/vulkano/src/buffer/cpu_access.rs @@ -35,7 +35,7 @@ use crate::{ use smallvec::SmallVec; use std::{ error::Error, - fmt, + fmt::{Display, Error as FmtError, Formatter}, hash::{Hash, Hasher}, marker::PhantomData, mem::size_of, @@ -572,13 +572,13 @@ pub enum ReadLockError { impl Error for ReadLockError {} -impl fmt::Display for ReadLockError { +impl Display for ReadLockError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { write!( - fmt, + f, "{}", - match *self { + match self { ReadLockError::CpuWriteLocked => { "the buffer is already locked for write mode by the CPU" } @@ -601,13 +601,13 @@ pub enum WriteLockError { impl Error for WriteLockError {} -impl fmt::Display for WriteLockError { +impl Display for WriteLockError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { write!( - fmt, + f, "{}", - match *self { + match self { WriteLockError::CpuLocked => "the buffer is already locked by the CPU", WriteLockError::GpuLocked => "the buffer is already locked by the GPU", } diff --git a/vulkano/src/buffer/device_local.rs b/vulkano/src/buffer/device_local.rs index 9e79bc7154..9b93104eed 100644 --- a/vulkano/src/buffer/device_local.rs +++ b/vulkano/src/buffer/device_local.rs @@ -37,10 +37,10 @@ use crate::{ sync::{NowFuture, Sharing}, DeviceSize, }; -use core::fmt; use smallvec::SmallVec; use std::{ error::Error, + fmt::{Display, Error as FmtError, Formatter}, fs::File, hash::{Hash, Hasher}, marker::PhantomData, @@ -590,9 +590,9 @@ impl Error for DeviceLocalBufferCreationError { } } -impl fmt::Display for DeviceLocalBufferCreationError { +impl Display for DeviceLocalBufferCreationError { #[inline] - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match self { Self::DeviceMemoryAllocationError(err) => err.fmt(f), Self::CommandBufferBeginError(err) => err.fmt(f), diff --git a/vulkano/src/buffer/sys.rs b/vulkano/src/buffer/sys.rs index 2d7346a92b..583a2ccc19 100644 --- a/vulkano/src/buffer/sys.rs +++ b/vulkano/src/buffer/sys.rs @@ -30,18 +30,18 @@ use super::{ }; use crate::{ device::{Device, DeviceOwned}, - macros::{vulkan_bitflags, ExtensionNotEnabled}, + macros::vulkan_bitflags, memory::{DeviceMemory, DeviceMemoryAllocationError, MemoryRequirements}, range_map::RangeMap, sync::{AccessError, CurrentAccess, Sharing}, - DeviceSize, OomError, Version, VulkanError, VulkanObject, + DeviceSize, OomError, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject, }; use ash::vk::Handle; use parking_lot::{Mutex, MutexGuard}; use smallvec::SmallVec; use std::{ error::Error, - fmt, + fmt::{Display, Error as FmtError, Formatter}, hash::{Hash, Hasher}, mem::MaybeUninit, ops::Range, @@ -86,7 +86,7 @@ impl UnsafeBuffer { assert!(size != 0); // VUID-VkBufferCreateInfo-usage-parameter - usage.validate(&device)?; + usage.validate_device(&device)?; // VUID-VkBufferCreateInfo-usage-requiredbitmask assert!(!usage.is_empty()); @@ -97,25 +97,34 @@ impl UnsafeBuffer { if let Some(sparse_level) = sparse { // VUID-VkBufferCreateInfo-flags-00915 if !device.enabled_features().sparse_binding { - return Err(BufferCreationError::FeatureNotEnabled { - feature: "sparse_binding", - reason: "sparse was `Some`", + return Err(BufferCreationError::RequirementNotMet { + required_for: "`create_info.sparse` is `Some`", + requires_one_of: RequiresOneOf { + features: &["sparse_binding"], + ..Default::default() + }, }); } // VUID-VkBufferCreateInfo-flags-00916 if sparse_level.sparse_residency && !device.enabled_features().sparse_residency_buffer { - return Err(BufferCreationError::FeatureNotEnabled { - feature: "sparse_residency_buffer", - reason: "sparse was `Some` and `sparse_residency` was set", + return Err(BufferCreationError::RequirementNotMet { + required_for: "`create_info.sparse` is `Some(sparse_level)`, where `sparse_level.sparse_residency` is set", + requires_one_of: RequiresOneOf { + features: &["sparse_residency_buffer"], + ..Default::default() + }, }); } // VUID-VkBufferCreateInfo-flags-00917 if sparse_level.sparse_aliased && !device.enabled_features().sparse_residency_aliased { - return Err(BufferCreationError::FeatureNotEnabled { - feature: "sparse_residency_aliased", - reason: "sparse was `Some` and `sparse_aliased` was set", + return Err(BufferCreationError::RequirementNotMet { + required_for: "`create_info.sparse` is `Some(sparse_level)`, where `sparse_level.sparse_aliased` is set", + requires_one_of: RequiresOneOf { + features: &["sparse_residency_aliased"], + ..Default::default() + }, }); } @@ -462,13 +471,9 @@ pub enum BufferCreationError { /// Allocating memory failed. AllocError(DeviceMemoryAllocationError), - ExtensionNotEnabled { - extension: &'static str, - reason: &'static str, - }, - FeatureNotEnabled { - feature: &'static str, - reason: &'static str, + RequirementNotMet { + required_for: &'static str, + requires_one_of: RequiresOneOf, }, /// The specified size exceeded the value of the `max_buffer_size` limit. @@ -489,25 +494,25 @@ impl Error for BufferCreationError { } } -impl fmt::Display for BufferCreationError { +impl Display for BufferCreationError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - match *self { - Self::AllocError(_) => write!(fmt, "allocating memory failed"), - Self::ExtensionNotEnabled { extension, reason } => write!( - fmt, - "the extension {} must be enabled: {}", - extension, reason + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { + match self { + Self::AllocError(_) => write!(f, "allocating memory failed"), + Self::RequirementNotMet { + required_for, + requires_one_of, + } => write!( + f, + "a requirement was not met for: {}; requires one of: {}", + required_for, requires_one_of, ), - Self::FeatureNotEnabled { feature, reason } => { - write!(fmt, "the feature {} must be enabled: {}", feature, reason) - } Self::MaxBufferSizeExceeded { .. } => write!( - fmt, + f, "the specified size exceeded the value of the `max_buffer_size` limit" ), Self::SharingInvalidQueueFamilyId { .. } => { - write!(fmt, "the sharing mode was set to `Concurrent`, but one of the specified queue family ids was not valid") + write!(f, "the sharing mode was set to `Concurrent`, but one of the specified queue family ids was not valid") } } } @@ -535,12 +540,12 @@ impl From for BufferCreationError { } } -impl From for BufferCreationError { +impl From for BufferCreationError { #[inline] - fn from(err: ExtensionNotEnabled) -> Self { - Self::ExtensionNotEnabled { - extension: err.extension, - reason: err.reason, + fn from(err: RequirementNotMet) -> Self { + Self::RequirementNotMet { + required_for: err.required_for, + requires_one_of: err.requires_one_of, } } } @@ -771,7 +776,10 @@ mod tests { use super::{ BufferCreationError, BufferUsage, SparseLevel, UnsafeBuffer, UnsafeBufferCreateInfo, }; - use crate::device::{Device, DeviceOwned}; + use crate::{ + device::{Device, DeviceOwned}, + RequiresOneOf, + }; #[test] fn create() { @@ -810,10 +818,10 @@ mod tests { ..Default::default() }, ) { - Err(BufferCreationError::FeatureNotEnabled { - feature: "sparse_binding", + Err(BufferCreationError::RequirementNotMet { + requires_one_of: RequiresOneOf { features, .. }, .. - }) => (), + }) if features.contains(&"sparse_binding") => (), _ => panic!(), } } @@ -837,10 +845,10 @@ mod tests { ..Default::default() }, ) { - Err(BufferCreationError::FeatureNotEnabled { - feature: "sparse_residency_buffer", + Err(BufferCreationError::RequirementNotMet { + requires_one_of: RequiresOneOf { features, .. }, .. - }) => (), + }) if features.contains(&"sparse_residency_buffer") => (), _ => panic!(), } } @@ -864,10 +872,10 @@ mod tests { ..Default::default() }, ) { - Err(BufferCreationError::FeatureNotEnabled { - feature: "sparse_residency_aliased", + Err(BufferCreationError::RequirementNotMet { + requires_one_of: RequiresOneOf { features, .. }, .. - }) => (), + }) if features.contains(&"sparse_residency_aliased") => (), _ => panic!(), } } diff --git a/vulkano/src/buffer/traits.rs b/vulkano/src/buffer/traits.rs index b06d295389..e3f36352ed 100644 --- a/vulkano/src/buffer/traits.rs +++ b/vulkano/src/buffer/traits.rs @@ -8,10 +8,10 @@ // according to those terms. use super::{sys::UnsafeBuffer, BufferContents, BufferSlice, BufferUsage}; -use crate::{device::DeviceOwned, DeviceSize, SafeDeref, VulkanObject}; +use crate::{device::DeviceOwned, DeviceSize, RequiresOneOf, SafeDeref, VulkanObject}; use std::{ error::Error, - fmt, + fmt::{Debug, Display, Error as FmtError, Formatter}, hash::{Hash, Hasher}, num::NonZeroU64, ops::Range, @@ -82,7 +82,13 @@ pub unsafe trait BufferAccess: DeviceOwned + Send + Sync { // VUID-vkGetBufferDeviceAddress-bufferDeviceAddress-03324 if !device.enabled_features().buffer_device_address { - return Err(BufferDeviceAddressError::FeatureNotEnabled); + return Err(BufferDeviceAddressError::RequirementNotMet { + required_for: "`raw_device_address`", + requires_one_of: RequiresOneOf { + features: &["buffer_device_address"], + ..Default::default() + }, + }); } // VUID-VkBufferDeviceAddressInfo-buffer-02601 @@ -168,8 +174,8 @@ where type Content = ::Content; } -impl fmt::Debug for dyn BufferAccess { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +impl Debug for dyn BufferAccess { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { f.debug_struct("dyn BufferAccess") .field("inner", &self.inner()) .finish() @@ -196,24 +202,33 @@ impl Hash for dyn BufferAccess { /// Error that can happen when querying the device address of a buffer. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum BufferDeviceAddressError { + RequirementNotMet { + required_for: &'static str, + requires_one_of: RequiresOneOf, + }, + BufferMissingUsage, - FeatureNotEnabled, } impl Error for BufferDeviceAddressError {} -impl fmt::Display for BufferDeviceAddressError { +impl Display for BufferDeviceAddressError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match self { + Self::RequirementNotMet { + required_for, + requires_one_of, + } => write!( + f, + "a requirement was not met for: {}; requires one of: {}", + required_for, requires_one_of, + ), + Self::BufferMissingUsage => write!( - fmt, + f, "the device address usage flag was not set on this buffer", ), - Self::FeatureNotEnabled => write!( - fmt, - "the buffer_device_address feature was not enabled on the device", - ), } } } diff --git a/vulkano/src/buffer/usage.rs b/vulkano/src/buffer/usage.rs index 1d4966e804..9ffbba0dc6 100644 --- a/vulkano/src/buffer/usage.rs +++ b/vulkano/src/buffer/usage.rs @@ -46,58 +46,58 @@ vulkan_bitflags! { /// The buffer's device address can be retrieved. shader_device_address = SHADER_DEVICE_ADDRESS { api_version: V1_2, - extensions: [khr_buffer_device_address, ext_buffer_device_address], + device_extensions: [khr_buffer_device_address, ext_buffer_device_address], }, /* // TODO: document video_decode_src = VIDEO_DECODE_SRC_KHR { - extensions: [khr_video_decode_queue], + device_extensions: [khr_video_decode_queue], }, // TODO: document video_decode_dst = VIDEO_DECODE_DST_KHR { - extensions: [khr_video_decode_queue], + device_extensions: [khr_video_decode_queue], }, // TODO: document transform_feedback_buffer = TRANSFORM_FEEDBACK_BUFFER_EXT { - extensions: [ext_transform_feedback], + device_extensions: [ext_transform_feedback], }, // TODO: document transform_feedback_counter_buffer = TRANSFORM_FEEDBACK_COUNTER_BUFFER_EXT { - extensions: [ext_transform_feedback], + device_extensions: [ext_transform_feedback], }, // TODO: document conditional_rendering = CONDITIONAL_RENDERING_EXT { - extensions: [ext_conditional_rendering], + device_extensions: [ext_conditional_rendering], }, // TODO: document acceleration_structure_build_input_read_only = ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_KHR { - extensions: [khr_acceleration_structure], + device_extensions: [khr_acceleration_structure], }, // TODO: document acceleration_structure_storage = ACCELERATION_STRUCTURE_STORAGE_KHR { - extensions: [khr_acceleration_structure], + device_extensions: [khr_acceleration_structure], }, // TODO: document shader_binding_table = SHADER_BINDING_TABLE_KHR { - extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], + device_extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], }, // TODO: document video_encode_dst = VIDEO_ENCODE_DST_KHR { - extensions: [khr_video_encode_queue], + device_extensions: [khr_video_encode_queue], }, // TODO: document video_encode_src = VIDEO_ENCODE_SRC_KHR { - extensions: [khr_video_encode_queue], + device_extensions: [khr_video_encode_queue], }, */ } diff --git a/vulkano/src/buffer/view.rs b/vulkano/src/buffer/view.rs index ab77acbf26..4658980944 100644 --- a/vulkano/src/buffer/view.rs +++ b/vulkano/src/buffer/view.rs @@ -50,7 +50,7 @@ use crate::{ }; use std::{ error::Error, - fmt, + fmt::{Display, Error as FmtError, Formatter}, hash::{Hash, Hasher}, mem::MaybeUninit, ops::Range, @@ -357,32 +357,32 @@ impl Error for BufferViewCreationError { } } -impl fmt::Display for BufferViewCreationError { +impl Display for BufferViewCreationError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match *self { BufferViewCreationError::OomError(_) => write!( - fmt, + f, "out of memory when creating buffer view", ), BufferViewCreationError::BufferMissingUsage => write!( - fmt, + f, "the buffer was not created with one of the `storage_texel_buffer` or `uniform_texel_buffer` usages", ), BufferViewCreationError::OffsetNotAligned { .. } => write!( - fmt, + f, "the offset within the buffer is not a multiple of the required alignment", ), BufferViewCreationError::RangeNotAligned { .. } => write!( - fmt, + f, "the range within the buffer is not a multiple of the required alignment", ), BufferViewCreationError::UnsupportedFormat => write!( - fmt, + f, "the requested format is not supported for this usage", ), BufferViewCreationError::MaxTexelBufferElementsExceeded => write!( - fmt, + f, "the `max_texel_buffer_elements` limit has been exceeded", ), } diff --git a/vulkano/src/command_buffer/auto.rs b/vulkano/src/command_buffer/auto.rs index 831c128415..6e25471db7 100644 --- a/vulkano/src/command_buffer/auto.rs +++ b/vulkano/src/command_buffer/auto.rs @@ -24,11 +24,10 @@ use crate::{ device::{physical::QueueFamily, Device, DeviceOwned, Queue}, format::Format, image::{sys::UnsafeImage, ImageAccess, ImageLayout, ImageSubresourceRange}, - macros::ExtensionNotEnabled, query::{QueryControlFlags, QueryType}, render_pass::{Framebuffer, Subpass}, sync::{AccessCheckError, AccessFlags, GpuFuture, PipelineMemoryAccess, PipelineStages}, - DeviceSize, OomError, + DeviceSize, OomError, RequirementNotMet, RequiresOneOf, }; use std::{ collections::HashMap, @@ -341,9 +340,12 @@ impl AutoCommandBufferBuilder { // VUID-VkCommandBufferInheritanceRenderingInfo-multiview-06008 if view_mask != 0 && !device.enabled_features().multiview { - return Err(CommandBufferBeginError::FeatureNotEnabled { - feature: "multiview", - reason: "view_mask is not 0", + return Err(CommandBufferBeginError::RequirementNotMet { + required_for: "`inheritance_info.render_pass` is `CommandBufferInheritanceRenderPassType::BeginRendering`, where `view_mask` is not `0`", + requires_one_of: RequiresOneOf { + features: &["multiview"], + ..Default::default() + }, }); } @@ -434,36 +436,46 @@ impl AutoCommandBufferBuilder { if let Some(control_flags) = occlusion_query { // VUID-VkCommandBufferInheritanceInfo-queryFlags-00057 - control_flags.validate(device)?; + control_flags.validate_device(device)?; // VUID-VkCommandBufferInheritanceInfo-occlusionQueryEnable-00056 // VUID-VkCommandBufferInheritanceInfo-queryFlags-02788 if !device.enabled_features().inherited_queries { - return Err(CommandBufferBeginError::FeatureNotEnabled { - feature: "inherited_queries", - reason: "occlusion queries were enabled", + return Err(CommandBufferBeginError::RequirementNotMet { + required_for: "`inheritance_info.occlusion_query` is `Some`", + requires_one_of: RequiresOneOf { + features: &["inherited_queries"], + ..Default::default() + }, }); } // VUID-vkBeginCommandBuffer-commandBuffer-00052 if control_flags.precise && !device.enabled_features().occlusion_query_precise { - return Err(CommandBufferBeginError::FeatureNotEnabled { - feature: "occlusion_query_precise", - reason: "occlusion_query.precise was set", + return Err(CommandBufferBeginError::RequirementNotMet { + required_for: + "`inheritance_info.occlusion_query` is `Some(control_flags)`, where `control_flags.precise` is set", + requires_one_of: RequiresOneOf { + features: &["occlusion_query_precise"], + ..Default::default() + }, }); } } // VUID-VkCommandBufferInheritanceInfo-pipelineStatistics-02789 - query_statistics_flags.validate(device)?; + query_statistics_flags.validate_device(device)?; // VUID-VkCommandBufferInheritanceInfo-pipelineStatistics-00058 if query_statistics_flags.count() > 0 && !device.enabled_features().pipeline_statistics_query { - return Err(CommandBufferBeginError::FeatureNotEnabled { - feature: "pipeline_statistics_query", - reason: "one or more statistics flags were enabled", + return Err(CommandBufferBeginError::RequirementNotMet { + required_for: "`inheritance_info.query_statistics_flags` is not empty", + requires_one_of: RequiresOneOf { + features: &["pipeline_statistics_query"], + ..Default::default() + }, }); } } else { @@ -483,13 +495,9 @@ pub enum CommandBufferBeginError { /// Not enough memory. OomError(OomError), - ExtensionNotEnabled { - extension: &'static str, - reason: &'static str, - }, - FeatureNotEnabled { - feature: &'static str, - reason: &'static str, + RequirementNotMet { + required_for: &'static str, + requires_one_of: RequiresOneOf, }, /// A color attachment has a format that does not support that usage. @@ -524,15 +532,17 @@ impl Error for CommandBufferBeginError { impl Display for CommandBufferBeginError { #[inline] fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { - match *self { + match self { Self::OomError(_) => write!(f, "not enough memory available"), - Self::ExtensionNotEnabled { extension, reason } => { - write!(f, "the extension {} must be enabled: {}", extension, reason) - } - Self::FeatureNotEnabled { feature, reason } => { - write!(f, "the feature {} must be enabled: {}", feature, reason) - } + Self::RequirementNotMet { + required_for, + requires_one_of, + } => write!( + f, + "a requirement was not met for: {}; requires one of: {}", + required_for, requires_one_of, + ), Self::ColorAttachmentFormatUsageNotSupported { attachment_index } => write!( f, @@ -568,12 +578,12 @@ impl From for CommandBufferBeginError { } } -impl From for CommandBufferBeginError { +impl From for CommandBufferBeginError { #[inline] - fn from(err: ExtensionNotEnabled) -> Self { - Self::ExtensionNotEnabled { - extension: err.extension, - reason: err.reason, + fn from(err: RequirementNotMet) -> Self { + Self::RequirementNotMet { + required_for: err.required_for, + requires_one_of: err.requires_one_of, } } } diff --git a/vulkano/src/command_buffer/commands/bind_push.rs b/vulkano/src/command_buffer/commands/bind_push.rs index b46753a239..2b565c4f04 100644 --- a/vulkano/src/command_buffer/commands/bind_push.rs +++ b/vulkano/src/command_buffer/commands/bind_push.rs @@ -21,7 +21,6 @@ use crate::{ DescriptorWriteInfo, WriteDescriptorSet, }, device::DeviceOwned, - macros::ExtensionNotEnabled, pipeline::{ graphics::{ input_assembly::{Index, IndexType}, @@ -31,12 +30,13 @@ use crate::{ ComputePipeline, GraphicsPipeline, PipelineBindPoint, PipelineLayout, }, shader::ShaderStages, - DeviceSize, VulkanObject, + DeviceSize, RequirementNotMet, RequiresOneOf, VulkanObject, }; use parking_lot::Mutex; use smallvec::SmallVec; use std::{ - error, fmt, + error, + fmt::{Display, Error as FmtError, Formatter}, mem::{size_of, size_of_val}, ptr, slice, sync::Arc, @@ -92,7 +92,7 @@ impl AutoCommandBufferBuilder { descriptor_sets: &[DescriptorSetWithOffsets], ) -> Result<(), BindPushError> { // VUID-vkCmdBindDescriptorSets-pipelineBindPoint-parameter - pipeline_bind_point.validate(self.device())?; + pipeline_bind_point.validate_device(self.device())?; // VUID-vkCmdBindDescriptorSets-commandBuffer-cmdpool // VUID-vkCmdBindDescriptorSets-pipelineBindPoint-00361 @@ -186,9 +186,12 @@ impl AutoCommandBufferBuilder { // VUID-vkCmdBindIndexBuffer-indexType-02765 if index_type == IndexType::U8 && !self.device().enabled_features().index_type_uint8 { - return Err(BindPushError::FeatureNotEnabled { - feature: "index_type_uint8", - reason: "index_buffer's index type was U8", + return Err(BindPushError::RequirementNotMet { + required_for: "`index_type` is `IndexType::U8`", + requires_one_of: RequiresOneOf { + features: &["index_type_uint8"], + ..Default::default() + }, }); } @@ -535,14 +538,17 @@ impl AutoCommandBufferBuilder { descriptor_writes: &[WriteDescriptorSet], ) -> Result<(), BindPushError> { if !self.device().enabled_extensions().khr_push_descriptor { - return Err(BindPushError::ExtensionNotEnabled { - extension: "khr_push_descriptor", - reason: "called push_descriptor_set", + return Err(BindPushError::RequirementNotMet { + required_for: "`push_descriptor_set`", + requires_one_of: RequiresOneOf { + device_extensions: &["khr_push_descriptor"], + ..Default::default() + }, }); } // VUID-vkCmdPushDescriptorSetKHR-pipelineBindPoint-parameter - pipeline_bind_point.validate(self.device())?; + pipeline_bind_point.validate_device(self.device())?; // VUID-vkCmdPushDescriptorSetKHR-commandBuffer-cmdpool // VUID-vkCmdPushDescriptorSetKHR-pipelineBindPoint-00363 @@ -1177,13 +1183,9 @@ impl UnsafeCommandBufferBuilderBindVertexBuffer { enum BindPushError { DescriptorSetUpdateError(DescriptorSetUpdateError), - ExtensionNotEnabled { - extension: &'static str, - reason: &'static str, - }, - FeatureNotEnabled { - feature: &'static str, - reason: &'static str, + RequirementNotMet { + required_for: &'static str, + requires_one_of: RequiresOneOf, }, /// The element of `descriptor_sets` being bound to a slot is not compatible with the @@ -1242,20 +1244,19 @@ impl error::Error for BindPushError { } } -impl fmt::Display for BindPushError { +impl Display for BindPushError { #[inline] - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match self { - Self::ExtensionNotEnabled { extension, reason } => write!( - f, - "the extension {} must be enabled: {}", - extension, reason - ), - Self::FeatureNotEnabled { feature, reason } => write!( + Self::RequirementNotMet { + required_for, + requires_one_of, + } => write!( f, - "the feature {} must be enabled: {}", - feature, reason, + "a requirement was not met for: {}; requires one of: {}", + required_for, requires_one_of, ), + Self::DescriptorSetUpdateError(_) => write!( f, "a DescriptorSetUpdateError", @@ -1318,12 +1319,12 @@ impl From for BindPushError { } } -impl From for BindPushError { +impl From for BindPushError { #[inline] - fn from(err: ExtensionNotEnabled) -> Self { - Self::ExtensionNotEnabled { - extension: err.extension, - reason: err.reason, + fn from(err: RequirementNotMet) -> Self { + Self::RequirementNotMet { + required_for: err.required_for, + requires_one_of: err.requires_one_of, } } } diff --git a/vulkano/src/command_buffer/commands/debug.rs b/vulkano/src/command_buffer/commands/debug.rs index 5eb685016a..7e85054d86 100644 --- a/vulkano/src/command_buffer/commands/debug.rs +++ b/vulkano/src/command_buffer/commands/debug.rs @@ -15,8 +15,13 @@ use crate::{ }, device::DeviceOwned, instance::debug::DebugUtilsLabel, + RequiresOneOf, +}; +use std::{ + error::Error, + ffi::CString, + fmt::{Display, Error as FmtError, Formatter}, }; -use std::{error::Error, ffi::CString, fmt}; /// # Commands for debugging. /// @@ -49,9 +54,12 @@ impl AutoCommandBufferBuilder { .enabled_extensions() .ext_debug_utils { - return Err(DebugUtilsError::ExtensionNotEnabled { - extension: "ext_debug_utils", - reason: "tried to record a debug utils command", + return Err(DebugUtilsError::RequirementNotMet { + required_for: "`begin_debug_utils_label`", + requires_one_of: RequiresOneOf { + instance_extensions: &["ext_debug_utils"], + ..Default::default() + }, }); } @@ -86,9 +94,12 @@ impl AutoCommandBufferBuilder { .enabled_extensions() .ext_debug_utils { - return Err(DebugUtilsError::ExtensionNotEnabled { - extension: "ext_debug_utils", - reason: "tried to record a debug utils command", + return Err(DebugUtilsError::RequirementNotMet { + required_for: "`end_debug_utils_label`", + requires_one_of: RequiresOneOf { + instance_extensions: &["ext_debug_utils"], + ..Default::default() + }, }); } @@ -131,9 +142,12 @@ impl AutoCommandBufferBuilder { .enabled_extensions() .ext_debug_utils { - return Err(DebugUtilsError::ExtensionNotEnabled { - extension: "ext_debug_utils", - reason: "tried to record a debug utils command", + return Err(DebugUtilsError::RequirementNotMet { + required_for: "`insert_debug_utils_label`", + requires_one_of: RequiresOneOf { + instance_extensions: &["ext_debug_utils"], + ..Default::default() + }, }); } @@ -284,9 +298,9 @@ impl UnsafeCommandBufferBuilder { /// Error that can happen when recording a debug utils command. #[derive(Clone, Debug)] pub enum DebugUtilsError { - ExtensionNotEnabled { - extension: &'static str, - reason: &'static str, + RequirementNotMet { + required_for: &'static str, + requires_one_of: RequiresOneOf, }, /// The queue family doesn't allow this operation. @@ -295,13 +309,19 @@ pub enum DebugUtilsError { impl Error for DebugUtilsError {} -impl fmt::Display for DebugUtilsError { +impl Display for DebugUtilsError { #[inline] - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match self { - Self::ExtensionNotEnabled { extension, reason } => { - write!(f, "the extension {} must be enabled: {}", extension, reason) - } + Self::RequirementNotMet { + required_for, + requires_one_of, + } => write!( + f, + "a requirement was not met for: {}; requires one of: {}", + required_for, requires_one_of, + ), + Self::NotSupportedByQueueFamily => { write!(f, "the queue family doesn't allow this operation") } diff --git a/vulkano/src/command_buffer/commands/dynamic_state.rs b/vulkano/src/command_buffer/commands/dynamic_state.rs index 17c806ebfc..62fa2a7e76 100644 --- a/vulkano/src/command_buffer/commands/dynamic_state.rs +++ b/vulkano/src/command_buffer/commands/dynamic_state.rs @@ -14,7 +14,6 @@ use crate::{ AutoCommandBufferBuilder, }, device::DeviceOwned, - macros::ExtensionNotEnabled, pipeline::{ graphics::{ color_blend::LogicOp, @@ -25,11 +24,15 @@ use crate::{ }, DynamicState, }, - Version, + RequirementNotMet, RequiresOneOf, Version, }; use parking_lot::Mutex; use smallvec::SmallVec; -use std::{error::Error, fmt, ops::RangeInclusive}; +use std::{ + error::Error, + fmt::{Display, Error as FmtError, Formatter}, + ops::RangeInclusive, +}; /// # Commands to set dynamic state for pipelines. /// @@ -121,9 +124,12 @@ impl AutoCommandBufferBuilder { // VUID-vkCmdSetColorWriteEnableEXT-None-04803 if !self.device().enabled_features().color_write_enable { - return Err(SetDynamicStateError::ExtensionNotEnabled { - extension: "color_write_enable", - reason: "called set_color_write_enable", + return Err(SetDynamicStateError::RequirementNotMet { + required_for: "`set_color_write_enable`", + requires_one_of: RequiresOneOf { + device_extensions: &["ext_color_write_enable"], + ..Default::default() + }, }); } @@ -171,7 +177,7 @@ impl AutoCommandBufferBuilder { self.validate_pipeline_fixed_state(DynamicState::CullMode)?; // VUID-vkCmdSetCullMode-cullMode-parameter - cull_mode.validate(self.device())?; + cull_mode.validate_device(self.device())?; // VUID-vkCmdSetCullMode-commandBuffer-cmdpool if !self.queue_family().supports_graphics() { @@ -182,9 +188,13 @@ impl AutoCommandBufferBuilder { if !(self.device().api_version() >= Version::V1_3 || self.device().enabled_features().extended_dynamic_state) { - return Err(SetDynamicStateError::FeatureNotEnabled { - feature: "extended_dynamic_state", - reason: "called set_cull_mode", + return Err(SetDynamicStateError::RequirementNotMet { + required_for: "`set_cull_mode`", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_3), + features: &["extended_dynamic_state"], + ..Default::default() + }, }); } @@ -232,9 +242,12 @@ impl AutoCommandBufferBuilder { // VUID-vkCmdSetDepthBias-depthBiasClamp-00790 if clamp != 0.0 && !self.device().enabled_features().depth_bias_clamp { - return Err(SetDynamicStateError::FeatureNotEnabled { - feature: "depth_bias_clamp", - reason: "clamp was not 0.0", + return Err(SetDynamicStateError::RequirementNotMet { + required_for: "`clamp` is not `0.0`", + requires_one_of: RequiresOneOf { + features: &["depth_bias_clamp"], + ..Default::default() + }, }); } @@ -273,9 +286,13 @@ impl AutoCommandBufferBuilder { if !(self.device().api_version() >= Version::V1_3 || self.device().enabled_features().extended_dynamic_state2) { - return Err(SetDynamicStateError::FeatureNotEnabled { - feature: "extended_dynamic_state2", - reason: "called set_depth_bias_enable", + return Err(SetDynamicStateError::RequirementNotMet { + required_for: "`set_depth_bias_enable`", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_3), + features: &["extended_dynamic_state2"], + ..Default::default() + }, }); } @@ -321,9 +338,12 @@ impl AutoCommandBufferBuilder { .ext_depth_range_unrestricted && !((0.0..=1.0).contains(bounds.start()) && (0.0..=1.0).contains(bounds.end())) { - return Err(SetDynamicStateError::ExtensionNotEnabled { - extension: "ext_depth_range_unrestricted", - reason: "the start and end of bounds were not between 0.0 and 1.0 inclusive", + return Err(SetDynamicStateError::RequirementNotMet { + required_for: "`bounds` is not between `0.0` and `1.0` inclusive", + requires_one_of: RequiresOneOf { + device_extensions: &["ext_depth_range_unrestricted"], + ..Default::default() + }, }); } @@ -365,9 +385,13 @@ impl AutoCommandBufferBuilder { if !(self.device().api_version() >= Version::V1_3 || self.device().enabled_features().extended_dynamic_state) { - return Err(SetDynamicStateError::FeatureNotEnabled { - feature: "extended_dynamic_state", - reason: "called set_depth_bounds_test_enable", + return Err(SetDynamicStateError::RequirementNotMet { + required_for: "`set_depth_bounds_test_enable`", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_3), + features: &["extended_dynamic_state"], + ..Default::default() + }, }); } @@ -401,7 +425,7 @@ impl AutoCommandBufferBuilder { self.validate_pipeline_fixed_state(DynamicState::DepthCompareOp)?; // VUID-vkCmdSetDepthCompareOp-depthCompareOp-parameter - compare_op.validate(self.device())?; + compare_op.validate_device(self.device())?; // VUID-vkCmdSetDepthCompareOp-commandBuffer-cmdpool if !self.queue_family().supports_graphics() { @@ -412,9 +436,13 @@ impl AutoCommandBufferBuilder { if !(self.device().api_version() >= Version::V1_3 || self.device().enabled_features().extended_dynamic_state) { - return Err(SetDynamicStateError::FeatureNotEnabled { - feature: "extended_dynamic_state", - reason: "called set_depth_compare_op", + return Err(SetDynamicStateError::RequirementNotMet { + required_for: "`set_depth_compare_op`", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_3), + features: &["extended_dynamic_state"], + ..Default::default() + }, }); } @@ -453,9 +481,13 @@ impl AutoCommandBufferBuilder { if !(self.device().api_version() >= Version::V1_3 || self.device().enabled_features().extended_dynamic_state) { - return Err(SetDynamicStateError::FeatureNotEnabled { - feature: "extended_dynamic_state", - reason: "called set_depth_test_enable", + return Err(SetDynamicStateError::RequirementNotMet { + required_for: "`set_depth_test_enable`", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_3), + features: &["extended_dynamic_state"], + ..Default::default() + }, }); } @@ -494,9 +526,13 @@ impl AutoCommandBufferBuilder { if !(self.device().api_version() >= Version::V1_3 || self.device().enabled_features().extended_dynamic_state) { - return Err(SetDynamicStateError::FeatureNotEnabled { - feature: "extended_dynamic_state", - reason: "called set_depth_write_enable", + return Err(SetDynamicStateError::RequirementNotMet { + required_for: "`set_depth_write_enable`", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_3), + features: &["extended_dynamic_state"], + ..Default::default() + }, }); } @@ -544,9 +580,12 @@ impl AutoCommandBufferBuilder { } if self.device().enabled_extensions().ext_discard_rectangles { - return Err(SetDynamicStateError::ExtensionNotEnabled { - extension: "ext_discard_rectangles", - reason: "called set_discard_rectangle", + return Err(SetDynamicStateError::RequirementNotMet { + required_for: "`set_discard_rectangle`", + requires_one_of: RequiresOneOf { + device_extensions: &["ext_discard_rectangles"], + ..Default::default() + }, }); } @@ -597,7 +636,7 @@ impl AutoCommandBufferBuilder { self.validate_pipeline_fixed_state(DynamicState::FrontFace)?; // VUID-vkCmdSetFrontFace-frontFace-parameter - face.validate(self.device())?; + face.validate_device(self.device())?; // VUID-vkCmdSetFrontFace-commandBuffer-cmdpool if !self.queue_family().supports_graphics() { @@ -608,9 +647,13 @@ impl AutoCommandBufferBuilder { if !(self.device().api_version() >= Version::V1_3 || self.device().enabled_features().extended_dynamic_state) { - return Err(SetDynamicStateError::FeatureNotEnabled { - feature: "extended_dynamic_state", - reason: "called set_front_face", + return Err(SetDynamicStateError::RequirementNotMet { + required_for: "`set_front_face`", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_3), + features: &["extended_dynamic_state"], + ..Default::default() + }, }); } @@ -650,9 +693,12 @@ impl AutoCommandBufferBuilder { } if !self.device().enabled_extensions().ext_line_rasterization { - return Err(SetDynamicStateError::ExtensionNotEnabled { - extension: "ext_line_rasterization", - reason: "called set_line_stipple", + return Err(SetDynamicStateError::RequirementNotMet { + required_for: "`set_line_stipple`", + requires_one_of: RequiresOneOf { + device_extensions: &["ext_line_rasterization"], + ..Default::default() + }, }); } @@ -692,9 +738,12 @@ impl AutoCommandBufferBuilder { // VUID-vkCmdSetLineWidth-lineWidth-00788 if !self.device().enabled_features().wide_lines && line_width != 1.0 { - return Err(SetDynamicStateError::FeatureNotEnabled { - feature: "wide_lines", - reason: "line_width was not 1.0", + return Err(SetDynamicStateError::RequirementNotMet { + required_for: "`line_width` is not `1.0`", + requires_one_of: RequiresOneOf { + features: &["wide_lines"], + ..Default::default() + }, }); } @@ -725,7 +774,7 @@ impl AutoCommandBufferBuilder { self.validate_pipeline_fixed_state(DynamicState::LogicOp)?; // VUID-vkCmdSetLogicOpEXT-logicOp-parameter - logic_op.validate(self.device())?; + logic_op.validate_device(self.device())?; // VUID-vkCmdSetLogicOpEXT-commandBuffer-cmdpool if !self.queue_family().supports_graphics() { @@ -738,9 +787,12 @@ impl AutoCommandBufferBuilder { .enabled_features() .extended_dynamic_state2_logic_op { - return Err(SetDynamicStateError::FeatureNotEnabled { - feature: "extended_dynamic_state2_logic_op", - reason: "called set_logic_op", + return Err(SetDynamicStateError::RequirementNotMet { + required_for: "`set_logic_op`", + requires_one_of: RequiresOneOf { + features: &["extended_dynamic_state2_logic_op"], + ..Default::default() + }, }); } @@ -785,9 +837,12 @@ impl AutoCommandBufferBuilder { .enabled_features() .extended_dynamic_state2_patch_control_points { - return Err(SetDynamicStateError::FeatureNotEnabled { - feature: "extended_dynamic_state2_patch_control_points", - reason: "called set_patch_control_points", + return Err(SetDynamicStateError::RequirementNotMet { + required_for: "`set_patch_control_points`", + requires_one_of: RequiresOneOf { + features: &["extended_dynamic_state2_patch_control_points"], + ..Default::default() + }, }); } @@ -850,9 +905,13 @@ impl AutoCommandBufferBuilder { if !(self.device().api_version() >= Version::V1_3 || self.device().enabled_features().extended_dynamic_state2) { - return Err(SetDynamicStateError::FeatureNotEnabled { - feature: "extended_dynamic_state2", - reason: "called set_primitive_restart_enable", + return Err(SetDynamicStateError::RequirementNotMet { + required_for: "`set_primitive_restart_enable`", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_3), + features: &["extended_dynamic_state2"], + ..Default::default() + }, }); } @@ -890,7 +949,7 @@ impl AutoCommandBufferBuilder { self.validate_pipeline_fixed_state(DynamicState::PrimitiveTopology)?; // VUID-vkCmdSetPrimitiveTopology-primitiveTopology-parameter - topology.validate(self.device())?; + topology.validate_device(self.device())?; // VUID-vkCmdSetPrimitiveTopology-commandBuffer-cmdpool if !self.queue_family().supports_graphics() { @@ -901,9 +960,13 @@ impl AutoCommandBufferBuilder { if !(self.device().api_version() >= Version::V1_3 || self.device().enabled_features().extended_dynamic_state) { - return Err(SetDynamicStateError::FeatureNotEnabled { - feature: "extended_dynamic_state", - reason: "called set_primitive_topology", + return Err(SetDynamicStateError::RequirementNotMet { + required_for: "`set_primitive_topology`", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_3), + features: &["extended_dynamic_state"], + ..Default::default() + }, }); } @@ -917,9 +980,12 @@ impl AutoCommandBufferBuilder { | PrimitiveTopology::TriangleStripWithAdjacency ) { - return Err(SetDynamicStateError::FeatureNotEnabled { - feature: "geometry_shader", - reason: "topology was a WithAdjacency topology", + return Err(SetDynamicStateError::RequirementNotMet { + required_for: "`topology` is `PrimitiveTopology::*WithAdjacency`", + requires_one_of: RequiresOneOf { + features: &["geometry_shader"], + ..Default::default() + }, }); } @@ -927,9 +993,12 @@ impl AutoCommandBufferBuilder { if !self.device().enabled_features().tessellation_shader && matches!(topology, PrimitiveTopology::PatchList) { - return Err(SetDynamicStateError::FeatureNotEnabled { - feature: "tessellation_shader", - reason: "topology was PatchList", + return Err(SetDynamicStateError::RequirementNotMet { + required_for: "`topology` is `PrimitiveTopology::PatchList`", + requires_one_of: RequiresOneOf { + features: &["tessellation_shader"], + ..Default::default() + }, }); } @@ -971,9 +1040,13 @@ impl AutoCommandBufferBuilder { if !(self.device().api_version() >= Version::V1_3 || self.device().enabled_features().extended_dynamic_state2) { - return Err(SetDynamicStateError::FeatureNotEnabled { - feature: "extended_dynamic_state2", - reason: "called set_rasterizer_discard_enable", + return Err(SetDynamicStateError::RequirementNotMet { + required_for: "`set_rasterizer_discard_enable`", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_3), + features: &["extended_dynamic_state2"], + ..Default::default() + }, }); } @@ -1029,17 +1102,23 @@ impl AutoCommandBufferBuilder { if !self.device().enabled_features().multi_viewport { // VUID-vkCmdSetScissor-firstScissor-00593 if first_scissor != 0 { - return Err(SetDynamicStateError::FeatureNotEnabled { - feature: "multi_viewport", - reason: "first_scissor was not 0", + return Err(SetDynamicStateError::RequirementNotMet { + required_for: "`first_scissor` is not `0`", + requires_one_of: RequiresOneOf { + features: &["multi_viewport"], + ..Default::default() + }, }); } // VUID-vkCmdSetScissor-scissorCount-00594 if scissors.len() > 1 { - return Err(SetDynamicStateError::FeatureNotEnabled { - feature: "multi_viewport", - reason: "scissors contained more than one element", + return Err(SetDynamicStateError::RequirementNotMet { + required_for: "`scissors.len()` is greater than `1`", + requires_one_of: RequiresOneOf { + features: &["multi_viewport"], + ..Default::default() + }, }); } } @@ -1090,9 +1169,13 @@ impl AutoCommandBufferBuilder { if !(self.device().api_version() >= Version::V1_3 || self.device().enabled_features().extended_dynamic_state) { - return Err(SetDynamicStateError::FeatureNotEnabled { - feature: "extended_dynamic_state", - reason: "called set_scissor_with_count", + return Err(SetDynamicStateError::RequirementNotMet { + required_for: "`set_scissor_with_count`", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_3), + features: &["extended_dynamic_state"], + ..Default::default() + }, }); } @@ -1106,9 +1189,12 @@ impl AutoCommandBufferBuilder { // VUID-vkCmdSetScissorWithCount-scissorCount-03398 if !self.device().enabled_features().multi_viewport && scissors.len() > 1 { - return Err(SetDynamicStateError::FeatureNotEnabled { - feature: "multi_viewport", - reason: "scissors contained more than one element", + return Err(SetDynamicStateError::RequirementNotMet { + required_for: "`scissors.len()` is greater than `1`", + requires_one_of: RequiresOneOf { + features: &["multi_viewport"], + ..Default::default() + }, }); } @@ -1144,7 +1230,7 @@ impl AutoCommandBufferBuilder { self.validate_pipeline_fixed_state(DynamicState::StencilCompareMask)?; // VUID-vkCmdSetStencilCompareMask-faceMask-parameter - faces.validate(self.device())?; + faces.validate_device(self.device())?; // VUID-vkCmdSetStencilCompareMask-commandBuffer-cmdpool if !self.queue_family().supports_graphics() { @@ -1194,19 +1280,19 @@ impl AutoCommandBufferBuilder { self.validate_pipeline_fixed_state(DynamicState::StencilOp)?; // VUID-vkCmdSetStencilOp-faceMask-parameter - faces.validate(self.device())?; + faces.validate_device(self.device())?; // VUID-vkCmdSetStencilOp-failOp-parameter - fail_op.validate(self.device())?; + fail_op.validate_device(self.device())?; // VUID-vkCmdSetStencilOp-passOp-parameter - pass_op.validate(self.device())?; + pass_op.validate_device(self.device())?; // VUID-vkCmdSetStencilOp-depthFailOp-parameter - depth_fail_op.validate(self.device())?; + depth_fail_op.validate_device(self.device())?; // VUID-vkCmdSetStencilOp-compareOp-parameter - compare_op.validate(self.device())?; + compare_op.validate_device(self.device())?; // VUID-vkCmdSetStencilOp-commandBuffer-cmdpool if !self.queue_family().supports_graphics() { @@ -1217,9 +1303,13 @@ impl AutoCommandBufferBuilder { if !(self.device().api_version() >= Version::V1_3 || self.device().enabled_features().extended_dynamic_state) { - return Err(SetDynamicStateError::FeatureNotEnabled { - feature: "extended_dynamic_state", - reason: "called set_stencil_op", + return Err(SetDynamicStateError::RequirementNotMet { + required_for: "`set_stencil_op`", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_3), + features: &["extended_dynamic_state"], + ..Default::default() + }, }); } @@ -1251,7 +1341,7 @@ impl AutoCommandBufferBuilder { self.validate_pipeline_fixed_state(DynamicState::StencilReference)?; // VUID-vkCmdSetStencilReference-faceMask-parameter - faces.validate(self.device())?; + faces.validate_device(self.device())?; // VUID-vkCmdSetStencilReference-commandBuffer-cmdpool if !self.queue_family().supports_graphics() { @@ -1293,9 +1383,13 @@ impl AutoCommandBufferBuilder { if !(self.device().api_version() >= Version::V1_3 || self.device().enabled_features().extended_dynamic_state) { - return Err(SetDynamicStateError::FeatureNotEnabled { - feature: "extended_dynamic_state", - reason: "called set_stencil_test_enable", + return Err(SetDynamicStateError::RequirementNotMet { + required_for: "`set_stencil_test_enable`", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_3), + features: &["extended_dynamic_state"], + ..Default::default() + }, }); } @@ -1327,7 +1421,7 @@ impl AutoCommandBufferBuilder { self.validate_pipeline_fixed_state(DynamicState::StencilWriteMask)?; // VUID-vkCmdSetStencilWriteMask-faceMask-parameter - faces.validate(self.device())?; + faces.validate_device(self.device())?; // VUID-vkCmdSetStencilWriteMask-commandBuffer-cmdpool if !self.queue_family().supports_graphics() { @@ -1387,17 +1481,23 @@ impl AutoCommandBufferBuilder { if !self.device().enabled_features().multi_viewport { // VUID-vkCmdSetViewport-firstViewport-01224 if first_viewport != 0 { - return Err(SetDynamicStateError::FeatureNotEnabled { - feature: "multi_viewport", - reason: "first_viewport was not 0", + return Err(SetDynamicStateError::RequirementNotMet { + required_for: "`first_scissors` is not `0`", + requires_one_of: RequiresOneOf { + features: &["multi_viewport"], + ..Default::default() + }, }); } // VUID-vkCmdSetViewport-viewportCount-01225 if viewports.len() > 1 { - return Err(SetDynamicStateError::FeatureNotEnabled { - feature: "multi_viewport", - reason: "viewports contained more than one element", + return Err(SetDynamicStateError::RequirementNotMet { + required_for: "`viewports.len()` is greater than `1`", + requires_one_of: RequiresOneOf { + features: &["multi_viewport"], + ..Default::default() + }, }); } } @@ -1448,9 +1548,13 @@ impl AutoCommandBufferBuilder { if !(self.device().api_version() >= Version::V1_3 || self.device().enabled_features().extended_dynamic_state) { - return Err(SetDynamicStateError::FeatureNotEnabled { - feature: "extended_dynamic_state", - reason: "called set_viewport_with_count", + return Err(SetDynamicStateError::RequirementNotMet { + required_for: "`set_viewport_with_count`", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_3), + features: &["extended_dynamic_state"], + ..Default::default() + }, }); } @@ -1464,9 +1568,12 @@ impl AutoCommandBufferBuilder { // VUID-vkCmdSetViewportWithCount-viewportCount-03395 if !self.device().enabled_features().multi_viewport && viewports.len() > 1 { - return Err(SetDynamicStateError::FeatureNotEnabled { - feature: "multi_viewport", - reason: "viewports contained more than one element", + return Err(SetDynamicStateError::RequirementNotMet { + required_for: "`viewports.len()` is greater than `1`", + requires_one_of: RequiresOneOf { + features: &["multi_viewport"], + ..Default::default() + }, }); } @@ -2679,13 +2786,9 @@ impl UnsafeCommandBufferBuilder { #[derive(Clone, Debug)] #[allow(dead_code)] enum SetDynamicStateError { - ExtensionNotEnabled { - extension: &'static str, - reason: &'static str, - }, - FeatureNotEnabled { - feature: &'static str, - reason: &'static str, + RequirementNotMet { + required_for: &'static str, + requires_one_of: RequiresOneOf, }, /// The provided `factor` is not between 1 and 256 inclusive. @@ -2720,16 +2823,18 @@ enum SetDynamicStateError { impl Error for SetDynamicStateError {} -impl fmt::Display for SetDynamicStateError { +impl Display for SetDynamicStateError { #[inline] - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match self { - Self::ExtensionNotEnabled { extension, reason } => { - write!(f, "the extension {} must be enabled: {}", extension, reason) - } - Self::FeatureNotEnabled { feature, reason } => { - write!(f, "the feature {} must be enabled: {}", feature, reason,) - } + Self::RequirementNotMet { + required_for, + requires_one_of, + } => write!( + f, + "a requirement was not met for: {}; requires one of: {}", + required_for, requires_one_of, + ), Self::FactorOutOfRange => write!( f, @@ -2767,12 +2872,12 @@ impl fmt::Display for SetDynamicStateError { } } -impl From for SetDynamicStateError { +impl From for SetDynamicStateError { #[inline] - fn from(err: ExtensionNotEnabled) -> Self { - Self::ExtensionNotEnabled { - extension: err.extension, - reason: err.reason, + fn from(err: RequirementNotMet) -> Self { + Self::RequirementNotMet { + required_for: err.required_for, + requires_one_of: err.requires_one_of, } } } diff --git a/vulkano/src/command_buffer/commands/image.rs b/vulkano/src/command_buffer/commands/image.rs index fbc3752c0f..331aa6eb2e 100644 --- a/vulkano/src/command_buffer/commands/image.rs +++ b/vulkano/src/command_buffer/commands/image.rs @@ -21,7 +21,7 @@ use crate::{ }, sampler::Filter, sync::{AccessFlags, PipelineMemoryAccess, PipelineStages}, - Version, VulkanObject, + RequiresOneOf, Version, VulkanObject, }; use smallvec::{smallvec, SmallVec}; use std::{ @@ -102,13 +102,13 @@ impl AutoCommandBufferBuilder { } = blit_image_info; // VUID-VkBlitImageInfo2-srcImageLayout-parameter - src_image_layout.validate(device)?; + src_image_layout.validate_device(device)?; // VUID-VkBlitImageInfo2-dstImageLayout-parameter - dst_image_layout.validate(device)?; + dst_image_layout.validate_device(device)?; // VUID-VkBlitImageInfo2-filter-parameter - filter.validate(device)?; + filter.validate_device(device)?; let src_image_inner = src_image.inner(); let dst_image_inner = dst_image.inner(); @@ -328,7 +328,7 @@ impl AutoCommandBufferBuilder { } // VUID-VkImageSubresourceLayers-aspectMask-parameter - subresource.aspects.validate(device)?; + subresource.aspects.validate_device(device)?; // VUID-VkImageSubresourceLayers-aspectMask-requiredbitmask assert!(!subresource.aspects.is_empty()); @@ -600,7 +600,7 @@ impl AutoCommandBufferBuilder { } = clear_info; // VUID-vkCmdClearColorImage-imageLayout-parameter - image_layout.validate(device)?; + image_layout.validate_device(device)?; // VUID-vkCmdClearColorImage-commonparent assert_eq!(device, image.device()); @@ -662,7 +662,7 @@ impl AutoCommandBufferBuilder { for (region_index, subresource_range) in regions.iter().enumerate() { // VUID-VkImageSubresourceRange-aspectMask-parameter - subresource_range.aspects.validate(device)?; + subresource_range.aspects.validate_device(device)?; // VUID-VkImageSubresourceRange-aspectMask-requiredbitmask assert!(!subresource_range.aspects.is_empty()); @@ -748,7 +748,7 @@ impl AutoCommandBufferBuilder { } = clear_info; // VUID-vkCmdClearDepthStencilImage-imageLayout-parameter - image_layout.validate(device)?; + image_layout.validate_device(device)?; // VUID-vkCmdClearDepthStencilImage-commonparent assert_eq!(device, image.device()); @@ -799,15 +799,19 @@ impl AutoCommandBufferBuilder { if !device.enabled_extensions().ext_depth_range_unrestricted && !(0.0..=1.0).contains(&clear_value.depth) { - return Err(CopyError::ExtensionNotEnabled { - extension: "ext_depth_range_unrestricted", - reason: "clear_value.depth was not between 0.0 and 1.0 inclusive", + return Err(CopyError::RequirementNotMet { + required_for: + "`clear_info.clear_value.depth` is not between `0.0` and `1.0` inclusive", + requires_one_of: RequiresOneOf { + device_extensions: &["ext_depth_range_unrestricted"], + ..Default::default() + }, }); } for (region_index, subresource_range) in regions.iter().enumerate() { // VUID-VkImageSubresourceRange-aspectMask-parameter - subresource_range.aspects.validate(device)?; + subresource_range.aspects.validate_device(device)?; // VUID-VkImageSubresourceRange-aspectMask-requiredbitmask assert!(!subresource_range.aspects.is_empty()); @@ -901,10 +905,10 @@ impl AutoCommandBufferBuilder { } = resolve_image_info; // VUID-VkResolveImageInfo2-srcImageLayout-parameter - src_image_layout.validate(device)?; + src_image_layout.validate_device(device)?; // VUID-VkResolveImageInfo2-dstImageLayout-parameter - dst_image_layout.validate(device)?; + dst_image_layout.validate_device(device)?; // VUID-VkResolveImageInfo2-commonparent assert_eq!(device, src_image.device()); @@ -1028,7 +1032,7 @@ impl AutoCommandBufferBuilder { } // VUID-VkImageSubresourceLayers-aspectMask-parameter - subresource.aspects.validate(device)?; + subresource.aspects.validate_device(device)?; // VUID-VkImageSubresourceLayers-aspectMask-requiredbitmask // VUID-VkImageResolve2-aspectMask-00266 diff --git a/vulkano/src/command_buffer/commands/mod.rs b/vulkano/src/command_buffer/commands/mod.rs index 97552e6abb..d2df4bd431 100644 --- a/vulkano/src/command_buffer/commands/mod.rs +++ b/vulkano/src/command_buffer/commands/mod.rs @@ -22,19 +22,21 @@ use super::synced::SyncCommandBufferBuilderError; use crate::{ format::Format, image::{ImageAspects, ImageLayout, SampleCount, SampleCounts}, - macros::ExtensionNotEnabled, - DeviceSize, + DeviceSize, RequirementNotMet, RequiresOneOf, +}; +use std::{ + error::Error, + fmt::{Display, Error as FmtError, Formatter}, }; -use std::{error::Error, fmt}; /// Error that can happen when recording a copy command. #[derive(Clone, Debug)] pub enum CopyError { SyncCommandBufferBuilderError(SyncCommandBufferBuilderError), - ExtensionNotEnabled { - extension: &'static str, - reason: &'static str, + RequirementNotMet { + required_for: &'static str, + requires_one_of: RequiresOneOf, }, /// Operation forbidden inside of a render pass. @@ -282,16 +284,21 @@ impl Error for CopyError { } } -impl fmt::Display for CopyError { +impl Display for CopyError { #[inline] - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match self { Self::SyncCommandBufferBuilderError(_) => write!(f, "a SyncCommandBufferBuilderError"), - Self::ExtensionNotEnabled { extension, reason } => write!( + + Self::RequirementNotMet { + required_for, + requires_one_of, + } => write!( f, - "the extension {} must be enabled: {}", - extension, reason + "a requirement was not met for: {}; requires one of: {}", + required_for, requires_one_of, ), + Self::ForbiddenInsideRenderPass => { write!(f, "operation forbidden inside of a render pass") } @@ -585,12 +592,12 @@ impl From for CopyError { } } -impl From for CopyError { +impl From for CopyError { #[inline] - fn from(err: ExtensionNotEnabled) -> Self { - Self::ExtensionNotEnabled { - extension: err.extension, - reason: err.reason, + fn from(err: RequirementNotMet) -> Self { + Self::RequirementNotMet { + required_for: err.required_for, + requires_one_of: err.requires_one_of, } } } @@ -602,9 +609,9 @@ pub enum CopyErrorResource { Destination, } -impl fmt::Display for CopyErrorResource { +impl Display for CopyErrorResource { #[inline] - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match self { Self::Source => write!(f, "source"), Self::Destination => write!(f, "destination"), diff --git a/vulkano/src/command_buffer/commands/pipeline.rs b/vulkano/src/command_buffer/commands/pipeline.rs index 7177029e67..6e8590de63 100644 --- a/vulkano/src/command_buffer/commands/pipeline.rs +++ b/vulkano/src/command_buffer/commands/pipeline.rs @@ -34,9 +34,17 @@ use crate::{ sampler::{Sampler, SamplerImageViewIncompatibleError}, shader::{DescriptorRequirements, ShaderScalarType, ShaderStage}, sync::{AccessFlags, PipelineMemoryAccess, PipelineStages}, - DeviceSize, VulkanObject, + DeviceSize, RequiresOneOf, VulkanObject, +}; +use std::{ + borrow::Cow, + cmp::min, + error::Error, + fmt::{Display, Error as FmtError, Formatter}, + mem::size_of, + ops::Range, + sync::Arc, }; -use std::{borrow::Cow, cmp::min, error::Error, fmt, mem::size_of, ops::Range, sync::Arc}; /// # Commands to execute a bound pipeline. /// @@ -286,9 +294,12 @@ impl AutoCommandBufferBuilder { // VUID-vkCmdDrawIndirect-drawCount-02718 if draw_count > 1 && !self.device().enabled_features().multi_draw_indirect { - return Err(PipelineExecutionError::FeatureNotEnabled { - feature: "multi_draw_indirect", - reason: "draw_count was greater than 1", + return Err(PipelineExecutionError::RequirementNotMet { + required_for: "`draw_count` is greater than `1`", + requires_one_of: RequiresOneOf { + features: &["multi_draw_indirect"], + ..Default::default() + }, }); } @@ -475,9 +486,12 @@ impl AutoCommandBufferBuilder { // VUID-vkCmdDrawIndexedIndirect-drawCount-02718 if draw_count > 1 && !self.device().enabled_features().multi_draw_indirect { - return Err(PipelineExecutionError::FeatureNotEnabled { - feature: "multi_draw_indirect", - reason: "draw_count was greater than 1", + return Err(PipelineExecutionError::RequirementNotMet { + required_for: "`draw_count` is greater than `1`", + requires_one_of: RequiresOneOf { + features: &["multi_draw_indirect"], + ..Default::default() + }, }); } @@ -1093,9 +1107,12 @@ impl AutoCommandBufferBuilder { | PrimitiveTopology::TriangleListWithAdjacency => { // VUID? if !device.enabled_features().primitive_topology_list_restart { - return Err(PipelineExecutionError::FeatureNotEnabled { - feature: "primitive_topology_list_restart", - reason: "the PrimitiveRestartEnable dynamic state was true in combination with a List PrimitiveTopology", + return Err(PipelineExecutionError::RequirementNotMet { + required_for: "The bound pipeline sets `DynamicState::PrimitiveRestartEnable` and the current primitive topology is `PrimitiveTopology::*List`", + requires_one_of: RequiresOneOf { + features: &["primitive_topology_list_restart"], + ..Default::default() + }, }); } } @@ -1105,9 +1122,12 @@ impl AutoCommandBufferBuilder { .enabled_features() .primitive_topology_patch_list_restart { - return Err(PipelineExecutionError::FeatureNotEnabled { - feature: "primitive_topology_patch_list_restart", - reason: "the PrimitiveRestartEnable dynamic state was true in combination with PrimitiveTopology::PatchList", + return Err(PipelineExecutionError::RequirementNotMet { + required_for: "The bound pipeline sets `DynamicState::PrimitiveRestartEnable` and the current primitive topology is `PrimitiveTopology::PatchList`", + requires_one_of: RequiresOneOf { + features: &["primitive_topology_patch_list_restart"], + ..Default::default() + }, }); } } @@ -2241,9 +2261,9 @@ impl UnsafeCommandBufferBuilder { pub enum PipelineExecutionError { SyncCommandBufferBuilderError(SyncCommandBufferBuilderError), - FeatureNotEnabled { - feature: &'static str, - reason: &'static str, + RequirementNotMet { + required_for: &'static str, + requires_one_of: RequiresOneOf, }, /// The resource bound to a descriptor set binding at a particular index is not compatible @@ -2430,15 +2450,20 @@ impl Error for PipelineExecutionError { } } -impl fmt::Display for PipelineExecutionError { +impl Display for PipelineExecutionError { #[inline] - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match self { Self::SyncCommandBufferBuilderError(_) => write!(f, "a SyncCommandBufferBuilderError"), - Self::FeatureNotEnabled { feature, reason } => { - write!(f, "the feature {} must be enabled: {}", feature, reason) - } + Self::RequirementNotMet { + required_for, + requires_one_of, + } => write!( + f, + "a requirement was not met for: {}; requires one of: {}", + required_for, requires_one_of, + ), Self::DescriptorResourceInvalid { set_num, binding_num, index, .. } => write!( f, @@ -2689,9 +2714,9 @@ impl Error for DescriptorResourceInvalidError { } } -impl fmt::Display for DescriptorResourceInvalidError { +impl Display for DescriptorResourceInvalidError { #[inline] - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match self { Self::ImageViewFormatMismatch { provided, required } => write!( f, diff --git a/vulkano/src/command_buffer/commands/query.rs b/vulkano/src/command_buffer/commands/query.rs index 747f38ca05..42203786f6 100644 --- a/vulkano/src/command_buffer/commands/query.rs +++ b/vulkano/src/command_buffer/commands/query.rs @@ -16,15 +16,20 @@ use crate::{ AutoCommandBufferBuilder, }, device::{physical::QueueFamily, DeviceOwned}, - macros::ExtensionNotEnabled, query::{ QueriesRange, Query, QueryControlFlags, QueryPool, QueryResultElement, QueryResultFlags, QueryType, }, sync::{AccessFlags, PipelineMemoryAccess, PipelineStage, PipelineStages}, - DeviceSize, VulkanObject, + DeviceSize, RequirementNotMet, RequiresOneOf, VulkanObject, +}; +use std::{ + error::Error, + fmt::{Display, Error as FmtError, Formatter}, + mem::size_of, + ops::Range, + sync::Arc, }; -use std::{error::Error, fmt, mem::size_of, ops::Range, sync::Arc}; /// # Commands related to queries. impl AutoCommandBufferBuilder { @@ -74,7 +79,7 @@ impl AutoCommandBufferBuilder { let device = self.device(); // VUID-vkCmdBeginQuery-flags-parameter - flags.validate(device)?; + flags.validate_device(device)?; // VUID-vkCmdBeginQuery-commonparent assert_eq!(device, query_pool.device()); @@ -92,9 +97,12 @@ impl AutoCommandBufferBuilder { // VUID-vkCmdBeginQuery-queryType-00800 if flags.precise && !device.enabled_features().occlusion_query_precise { - return Err(QueryError::FeatureNotEnabled { - feature: "occlusion_query_precise", - reason: "flags.precise was enabled", + return Err(QueryError::RequirementNotMet { + required_for: "`flags.precise` is set", + requires_one_of: RequiresOneOf { + features: &["occlusion_query_precise"], + ..Default::default() + }, }); } } @@ -237,9 +245,12 @@ impl AutoCommandBufferBuilder { PipelineStage::GeometryShader => { // VUID-vkCmdWriteTimestamp-pipelineStage-04075 if !device.enabled_features().geometry_shader { - return Err(QueryError::FeatureNotEnabled { - feature: "geometry_shader", - reason: "stage was GeometryShader", + return Err(QueryError::RequirementNotMet { + required_for: "`stage` is `PipelineStage::GeometryShader`", + requires_one_of: RequiresOneOf { + features: &["geometry_shadere"], + ..Default::default() + }, }); } } @@ -247,10 +258,12 @@ impl AutoCommandBufferBuilder { | PipelineStage::TessellationEvaluationShader => { // VUID-vkCmdWriteTimestamp-pipelineStage-04076 if !device.enabled_features().tessellation_shader { - return Err(QueryError::FeatureNotEnabled { - feature: "tessellation_shader", - reason: - "stage was TessellationControlShader or TessellationEvaluationShader", + return Err(QueryError::RequirementNotMet { + required_for: "`stage` is `PipelineStage::TessellationControlShader` or `PipelineStage::TessellationEvaluationShader`", + requires_one_of: RequiresOneOf { + features: &["tessellation_shader"], + ..Default::default() + }, }); } } @@ -723,13 +736,9 @@ impl UnsafeCommandBufferBuilder { pub enum QueryError { SyncCommandBufferBuilderError(SyncCommandBufferBuilderError), - ExtensionNotEnabled { - extension: &'static str, - reason: &'static str, - }, - FeatureNotEnabled { - feature: &'static str, - reason: &'static str, + RequirementNotMet { + required_for: &'static str, + requires_one_of: RequiresOneOf, }, /// The buffer is too small for the copy operation. @@ -777,24 +786,22 @@ pub enum QueryError { impl Error for QueryError {} -impl fmt::Display for QueryError { +impl Display for QueryError { #[inline] - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match *self { Self::SyncCommandBufferBuilderError(_) => write!( f, "a SyncCommandBufferBuilderError", ), - Self::ExtensionNotEnabled { extension, reason } => write!( - f, - "the extension {} must be enabled: {}", - extension, reason - ), - Self::FeatureNotEnabled { feature, reason } => write!( + Self::RequirementNotMet { + required_for, + requires_one_of, + } => write!( f, - "the feature {} must be enabled: {}", - feature, reason, + "a requirement was not met for: {}; requires one of: {}", + required_for, requires_one_of, ), Self::BufferTooSmall { .. } => { @@ -842,12 +849,12 @@ impl From for QueryError { } } -impl From for QueryError { +impl From for QueryError { #[inline] - fn from(err: ExtensionNotEnabled) -> Self { - Self::ExtensionNotEnabled { - extension: err.extension, - reason: err.reason, + fn from(err: RequirementNotMet) -> Self { + Self::RequirementNotMet { + required_for: err.required_for, + requires_one_of: err.requires_one_of, } } } diff --git a/vulkano/src/command_buffer/commands/render_pass.rs b/vulkano/src/command_buffer/commands/render_pass.rs index 92bd19404b..1fde76a0f7 100644 --- a/vulkano/src/command_buffer/commands/render_pass.rs +++ b/vulkano/src/command_buffer/commands/render_pass.rs @@ -21,16 +21,21 @@ use crate::{ device::DeviceOwned, format::{ClearColorValue, ClearValue, Format, NumericType}, image::{ImageLayout, ImageViewAbstract, SampleCount}, - macros::ExtensionNotEnabled, render_pass::{ AttachmentDescription, Framebuffer, LoadOp, RenderPass, ResolveMode, StoreOp, SubpassDescription, }, sync::{AccessFlags, PipelineMemoryAccess, PipelineStages}, - Version, VulkanObject, + RequirementNotMet, RequiresOneOf, Version, VulkanObject, }; use smallvec::SmallVec; -use std::{cmp::min, error::Error, fmt, ops::Range, sync::Arc}; +use std::{ + cmp::min, + error::Error, + fmt::{Display, Error as FmtError, Formatter}, + ops::Range, + sync::Arc, +}; /// # Commands for render passes. /// @@ -94,7 +99,7 @@ where let device = self.device(); // VUID-VkSubpassBeginInfo-contents-parameter - contents.validate(device)?; + contents.validate_device(device)?; // VUID-vkCmdBeginRenderPass2-commandBuffer-cmdpool if !self.queue_family().supports_graphics() { @@ -420,7 +425,7 @@ where let device = self.device(); // VUID-VkSubpassBeginInfo-contents-parameter - contents.validate(device)?; + contents.validate_device(device)?; // VUID-vkCmdNextSubpass2-renderpass let render_pass_state = self @@ -661,9 +666,12 @@ impl AutoCommandBufferBuilder { // VUID-vkCmdBeginRendering-dynamicRendering-06446 if !device.enabled_features().dynamic_rendering { - return Err(RenderPassError::FeatureNotEnabled { - feature: "dynamic_rendering", - reason: "called begin_rendering", + return Err(RenderPassError::RequirementNotMet { + required_for: "`begin_rendering`", + requires_one_of: RequiresOneOf { + features: &["dynamic_rendering"], + ..Default::default() + }, }); } @@ -690,7 +698,7 @@ impl AutoCommandBufferBuilder { } = rendering_info; // VUID-VkRenderingInfo-flags-parameter - contents.validate(device)?; + contents.validate_device(device)?; // VUID-vkCmdBeginRendering-commandBuffer-06068 if self.inheritance_info.is_some() && contents == SubpassContents::SecondaryCommandBuffers { @@ -704,9 +712,12 @@ impl AutoCommandBufferBuilder { // VUID-VkRenderingInfo-multiview-06127 if view_mask != 0 && !device.enabled_features().multiview { - return Err(RenderPassError::FeatureNotEnabled { - feature: "multiview", - reason: "view_mask is not 0", + return Err(RenderPassError::RequirementNotMet { + required_for: "`rendering_info.viewmask` is not `0`", + requires_one_of: RequiresOneOf { + features: &["multiview"], + ..Default::default() + }, }); } @@ -752,13 +763,13 @@ impl AutoCommandBufferBuilder { } = attachment_info; // VUID-VkRenderingAttachmentInfo-imageLayout-parameter - image_layout.validate(device)?; + image_layout.validate_device(device)?; // VUID-VkRenderingAttachmentInfo-loadOp-parameter - load_op.validate(device)?; + load_op.validate_device(device)?; // VUID-VkRenderingAttachmentInfo-storeOp-parameter - store_op.validate(device)?; + store_op.validate_device(device)?; // VUID-VkRenderingInfo-colorAttachmentCount-06087 if !image_view.usage().color_attachment { @@ -812,10 +823,10 @@ impl AutoCommandBufferBuilder { } = resolve_info; // VUID-VkRenderingAttachmentInfo-resolveImageLayout-parameter - resolve_image_layout.validate(device)?; + resolve_image_layout.validate_device(device)?; // VUID-VkRenderingAttachmentInfo-resolveMode-parameter - mode.validate(device)?; + mode.validate_device(device)?; let resolve_image = resolve_image_view.image(); @@ -901,13 +912,13 @@ impl AutoCommandBufferBuilder { } = attachment_info; // VUID-VkRenderingAttachmentInfo-imageLayout-parameter - image_layout.validate(device)?; + image_layout.validate_device(device)?; // VUID-VkRenderingAttachmentInfo-loadOp-parameter - load_op.validate(device)?; + load_op.validate_device(device)?; // VUID-VkRenderingAttachmentInfo-storeOp-parameter - store_op.validate(device)?; + store_op.validate_device(device)?; let image_aspects = image_view.format().unwrap().aspects(); @@ -965,10 +976,10 @@ impl AutoCommandBufferBuilder { } = resolve_info; // VUID-VkRenderingAttachmentInfo-resolveImageLayout-parameter - resolve_image_layout.validate(device)?; + resolve_image_layout.validate_device(device)?; // VUID-VkRenderingAttachmentInfo-resolveMode-parameter - mode.validate(device)?; + mode.validate_device(device)?; // VUID-VkRenderingInfo-pDepthAttachment-06102 if !properties @@ -1026,13 +1037,13 @@ impl AutoCommandBufferBuilder { } = attachment_info; // VUID-VkRenderingAttachmentInfo-imageLayout-parameter - image_layout.validate(device)?; + image_layout.validate_device(device)?; // VUID-VkRenderingAttachmentInfo-loadOp-parameter - load_op.validate(device)?; + load_op.validate_device(device)?; // VUID-VkRenderingAttachmentInfo-storeOp-parameter - store_op.validate(device)?; + store_op.validate_device(device)?; let image_aspects = image_view.format().unwrap().aspects(); @@ -1090,10 +1101,10 @@ impl AutoCommandBufferBuilder { } = resolve_info; // VUID-VkRenderingAttachmentInfo-resolveImageLayout-parameter - resolve_image_layout.validate(device)?; + resolve_image_layout.validate_device(device)?; // VUID-VkRenderingAttachmentInfo-resolveMode-parameter - mode.validate(device)?; + mode.validate_device(device)?; // VUID-VkRenderingInfo-pStencilAttachment-06103 if !properties @@ -2528,13 +2539,9 @@ pub struct ClearRect { pub enum RenderPassError { SyncCommandBufferBuilderError(SyncCommandBufferBuilderError), - ExtensionNotEnabled { - extension: &'static str, - reason: &'static str, - }, - FeatureNotEnabled { - feature: &'static str, - reason: &'static str, + RequirementNotMet { + required_for: &'static str, + requires_one_of: RequiresOneOf, }, /// A framebuffer image did not have the required usage enabled. @@ -2789,20 +2796,20 @@ impl Error for RenderPassError { } } -impl fmt::Display for RenderPassError { +impl Display for RenderPassError { #[inline] - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match self { Self::SyncCommandBufferBuilderError(_) => write!(f, "a SyncCommandBufferBuilderError"), - Self::ExtensionNotEnabled { extension, reason } => write!( + Self::RequirementNotMet { + required_for, + requires_one_of, + } => write!( f, - "the extension {} must be enabled: {}", - extension, reason + "a requirement was not met for: {}; requires one of: {}", + required_for, requires_one_of, ), - Self::FeatureNotEnabled { feature, reason } => { - write!(f, "the feature {} must be enabled: {}", feature, reason) - } Self::AttachmentImageMissingUsage { attachment_index, usage } => write!( f, @@ -3093,12 +3100,12 @@ impl From for RenderPassError { } } -impl From for RenderPassError { +impl From for RenderPassError { #[inline] - fn from(err: ExtensionNotEnabled) -> Self { - Self::ExtensionNotEnabled { - extension: err.extension, - reason: err.reason, + fn from(err: RequirementNotMet) -> Self { + Self::RequirementNotMet { + required_for: err.required_for, + requires_one_of: err.requires_one_of, } } } diff --git a/vulkano/src/command_buffer/commands/secondary.rs b/vulkano/src/command_buffer/commands/secondary.rs index c986797518..dad5370ad3 100644 --- a/vulkano/src/command_buffer/commands/secondary.rs +++ b/vulkano/src/command_buffer/commands/secondary.rs @@ -20,10 +20,13 @@ use crate::{ format::Format, image::SampleCount, query::{QueryControlFlags, QueryPipelineStatisticFlags, QueryType}, - SafeDeref, VulkanObject, + RequiresOneOf, SafeDeref, VulkanObject, }; use smallvec::SmallVec; -use std::{error::Error, fmt}; +use std::{ + error::Error, + fmt::{Display, Error as FmtError, Formatter}, +}; /// # Commands to execute a secondary command buffer inside a primary command buffer. /// @@ -317,9 +320,12 @@ where // VUID-vkCmdExecuteCommands-commandBuffer-00101 if !self.query_state.is_empty() && !self.device().enabled_features().inherited_queries { - return Err(ExecuteCommandsError::FeatureNotEnabled { - feature: "inherited_queries", - reason: "a query was active when calling execute_commands", + return Err(ExecuteCommandsError::RequirementNotMet { + required_for: "`execute_commands` when a query is active", + requires_one_of: RequiresOneOf { + features: &["inherited_queries"], + ..Default::default() + }, }); } @@ -557,9 +563,9 @@ impl UnsafeCommandBufferBuilderExecuteCommands { pub enum ExecuteCommandsError { SyncCommandBufferBuilderError(SyncCommandBufferBuilderError), - FeatureNotEnabled { - feature: &'static str, - reason: &'static str, + RequirementNotMet { + required_for: &'static str, + requires_one_of: RequiresOneOf, }, /// Operation forbidden inside a render subpass with the specified contents. @@ -701,15 +707,20 @@ impl Error for ExecuteCommandsError { } } -impl fmt::Display for ExecuteCommandsError { +impl Display for ExecuteCommandsError { #[inline] - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match self { Self::SyncCommandBufferBuilderError(_) => write!(f, "a SyncCommandBufferBuilderError"), - Self::FeatureNotEnabled { feature, reason } => { - write!(f, "the feature {} must be enabled: {}", feature, reason) - } + Self::RequirementNotMet { + required_for, + requires_one_of, + } => write!( + f, + "a requirement was not met for: {}; requires one of: {}", + required_for, requires_one_of, + ), Self::ForbiddenWithSubpassContents { contents: subpass_contents } => write!( f, diff --git a/vulkano/src/command_buffer/commands/transfer.rs b/vulkano/src/command_buffer/commands/transfer.rs index deb065a2de..9900ba7df7 100644 --- a/vulkano/src/command_buffer/commands/transfer.rs +++ b/vulkano/src/command_buffer/commands/transfer.rs @@ -229,10 +229,10 @@ impl AutoCommandBufferBuilder { } = copy_image_info; // VUID-VkCopyImageInfo2-srcImageLayout-parameter - src_image_layout.validate(device)?; + src_image_layout.validate_device(device)?; // VUID-VkCopyImageInfo2-dstImageLayout-parameter - dst_image_layout.validate(device)?; + dst_image_layout.validate_device(device)?; // VUID-VkCopyImageInfo2-commonparent assert_eq!(device, src_image.device()); @@ -404,7 +404,7 @@ impl AutoCommandBufferBuilder { } // VUID-VkImageSubresourceLayers-aspectMask-parameter - subresource.aspects.validate(device)?; + subresource.aspects.validate_device(device)?; // VUID-VkImageSubresourceLayers-aspectMask-requiredbitmask assert!(!subresource.aspects.is_empty()); @@ -878,7 +878,7 @@ impl AutoCommandBufferBuilder { } = copy_buffer_to_image_info; // VUID-VkCopyBufferToImageInfo2-dstImageLayout-parameter - dst_image_layout.validate(device)?; + dst_image_layout.validate_device(device)?; // VUID-VkCopyBufferToImageInfo2-commonparent assert_eq!(device, src_buffer.device()); @@ -1307,7 +1307,7 @@ impl AutoCommandBufferBuilder { } = copy_image_to_buffer_info; // VUID-VkCopyImageToBufferInfo2-srcImageLayout-parameter - src_image_layout.validate(device)?; + src_image_layout.validate_device(device)?; // VUID-VkCopyImageToBufferInfo2-commonparent assert_eq!(device, dst_buffer.device()); diff --git a/vulkano/src/command_buffer/pool/sys.rs b/vulkano/src/command_buffer/pool/sys.rs index fa465b0948..ff08cea7b0 100644 --- a/vulkano/src/command_buffer/pool/sys.rs +++ b/vulkano/src/command_buffer/pool/sys.rs @@ -10,12 +10,12 @@ use crate::{ command_buffer::CommandBufferLevel, device::{physical::QueueFamily, Device, DeviceOwned}, - OomError, Version, VulkanError, VulkanObject, + OomError, RequiresOneOf, Version, VulkanError, VulkanObject, }; use smallvec::SmallVec; use std::{ error::Error, - fmt, + fmt::{Display, Error as FmtError, Formatter}, hash::{Hash, Hasher}, marker::PhantomData, mem::MaybeUninit, @@ -275,7 +275,14 @@ impl UnsafeCommandPool { if !(self.device.api_version() >= Version::V1_1 || self.device.enabled_extensions().khr_maintenance1) { - return Err(CommandPoolTrimError::Maintenance1ExtensionNotEnabled); + return Err(CommandPoolTrimError::RequirementNotMet { + required_for: "`trim`", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_1), + device_extensions: &["khr_maintenance1"], + ..Default::default() + }, + }); } unsafe { @@ -380,16 +387,16 @@ impl Error for UnsafeCommandPoolCreationError { } } -impl fmt::Display for UnsafeCommandPoolCreationError { +impl Display for UnsafeCommandPoolCreationError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match *self { - Self::OomError(_) => write!(fmt, "not enough memory",), + Self::OomError(_) => write!(f, "not enough memory",), Self::QueueFamilyIndexOutOfRange { queue_family_index, queue_family_count, } => write!( - fmt, + f, "the provided `queue_family_index` ({}) was not less than the number of queue families in the physical device ({})", queue_family_index, queue_family_count, ), @@ -521,24 +528,27 @@ impl Hash for UnsafeCommandPoolAlloc { /// Error that can happen when trimming command pools. #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum CommandPoolTrimError { - /// The `KHR_maintenance1` extension was not enabled. - Maintenance1ExtensionNotEnabled, + RequirementNotMet { + required_for: &'static str, + requires_one_of: RequiresOneOf, + }, } impl Error for CommandPoolTrimError {} -impl fmt::Display for CommandPoolTrimError { +impl Display for CommandPoolTrimError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!( - fmt, - "{}", - match *self { - CommandPoolTrimError::Maintenance1ExtensionNotEnabled => { - "the `KHR_maintenance1` extension was not enabled" - } - } - ) + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { + match self { + Self::RequirementNotMet { + required_for, + requires_one_of, + } => write!( + f, + "a requirement was not met for: {}; requires one of: {}", + required_for, requires_one_of, + ), + } } } @@ -557,7 +567,7 @@ mod tests { }; use crate::{ command_buffer::{pool::sys::CommandBufferAllocateInfo, CommandBufferLevel}, - Version, + RequiresOneOf, Version, }; #[test] @@ -617,14 +627,24 @@ mod tests { if device.api_version() >= Version::V1_1 { if matches!( pool.trim(), - Err(CommandPoolTrimError::Maintenance1ExtensionNotEnabled) + Err(CommandPoolTrimError::RequirementNotMet { + requires_one_of: RequiresOneOf { + device_extensions, + .. + }, .. + }) if device_extensions.contains(&"khr_maintenance1") ) { panic!() } } else { if !matches!( pool.trim(), - Err(CommandPoolTrimError::Maintenance1ExtensionNotEnabled) + Err(CommandPoolTrimError::RequirementNotMet { + requires_one_of: RequiresOneOf { + device_extensions, + .. + }, .. + }) if device_extensions.contains(&"khr_maintenance1") ) { panic!() } diff --git a/vulkano/src/command_buffer/submit/bind_sparse.rs b/vulkano/src/command_buffer/submit/bind_sparse.rs index dc94b47154..33b1e13b93 100644 --- a/vulkano/src/command_buffer/submit/bind_sparse.rs +++ b/vulkano/src/command_buffer/submit/bind_sparse.rs @@ -16,7 +16,11 @@ use crate::{ DeviceSize, OomError, SynchronizedVulkanObject, VulkanError, VulkanObject, }; use smallvec::SmallVec; -use std::{error::Error, fmt, marker::PhantomData}; +use std::{ + error::Error, + fmt::{Debug, Display, Error as FmtError, Formatter}, + marker::PhantomData, +}; // TODO: correctly implement Debug on all the structs of this module @@ -246,10 +250,10 @@ impl<'a> SubmitBindSparseBuilder<'a> { } } -impl<'a> fmt::Debug for SubmitBindSparseBuilder<'a> { +impl<'a> Debug for SubmitBindSparseBuilder<'a> { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!(fmt, "") + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { + write!(f, "") } } @@ -480,11 +484,11 @@ impl Error for SubmitBindSparseError { } } -impl fmt::Display for SubmitBindSparseError { +impl Display for SubmitBindSparseError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { write!( - fmt, + f, "{}", match *self { SubmitBindSparseError::OomError(_) => "not enough memory", diff --git a/vulkano/src/command_buffer/submit/queue_present.rs b/vulkano/src/command_buffer/submit/queue_present.rs index 79dcb8fcc7..52793210b9 100644 --- a/vulkano/src/command_buffer/submit/queue_present.rs +++ b/vulkano/src/command_buffer/submit/queue_present.rs @@ -14,7 +14,12 @@ use crate::{ OomError, SynchronizedVulkanObject, VulkanError, VulkanObject, }; use smallvec::SmallVec; -use std::{error::Error, fmt, marker::PhantomData, ptr}; +use std::{ + error::Error, + fmt::{Debug, Display, Error as FmtError, Formatter}, + marker::PhantomData, + ptr, +}; /// Prototype for a submission that presents a swapchain on the screen. // TODO: example here @@ -181,9 +186,9 @@ impl<'a> SubmitPresentBuilder<'a> { } } -impl<'a> fmt::Debug for SubmitPresentBuilder<'a> { - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - fmt.debug_struct("SubmitPresentBuilder") +impl<'a> Debug for SubmitPresentBuilder<'a> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { + f.debug_struct("SubmitPresentBuilder") .field("wait_semaphores", &self.wait_semaphores) .field("swapchains", &self.swapchains) .field("image_indices", &self.image_indices) @@ -223,11 +228,11 @@ impl Error for SubmitPresentError { } } -impl fmt::Display for SubmitPresentError { +impl Display for SubmitPresentError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { write!( - fmt, + f, "{}", match *self { SubmitPresentError::OomError(_) => "not enough memory", diff --git a/vulkano/src/command_buffer/submit/queue_submit.rs b/vulkano/src/command_buffer/submit/queue_submit.rs index 468c5a50db..3654627517 100644 --- a/vulkano/src/command_buffer/submit/queue_submit.rs +++ b/vulkano/src/command_buffer/submit/queue_submit.rs @@ -14,7 +14,11 @@ use crate::{ OomError, SynchronizedVulkanObject, VulkanError, VulkanObject, }; use smallvec::SmallVec; -use std::{error::Error, fmt, marker::PhantomData}; +use std::{ + error::Error, + fmt::{Display, Error as FmtError, Formatter}, + marker::PhantomData, +}; /// Prototype for a submission that executes command buffers. // TODO: example here @@ -261,11 +265,11 @@ impl Error for SubmitCommandBufferError { } } -impl fmt::Display for SubmitCommandBufferError { +impl Display for SubmitCommandBufferError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { write!( - fmt, + f, "{}", match *self { SubmitCommandBufferError::OomError(_) => "not enough memory", diff --git a/vulkano/src/command_buffer/synced/builder.rs b/vulkano/src/command_buffer/synced/builder.rs index a9d096fb92..35fa7e9f44 100644 --- a/vulkano/src/command_buffer/synced/builder.rs +++ b/vulkano/src/command_buffer/synced/builder.rs @@ -48,7 +48,7 @@ use std::{ borrow::Cow, collections::{hash_map::Entry, HashMap}, error::Error, - fmt, + fmt::{Debug, Display, Error as FmtError, Formatter}, ops::{Range, RangeInclusive}, sync::Arc, }; @@ -59,9 +59,6 @@ use std::{ /// for `pipeline_layout` which is automatically handled. This wrapper automatically builds /// pipeline barriers, keeps used resources alive and implements the `CommandBuffer` trait. /// -/// Since the implementation needs to cache commands in a `Vec`, most methods have additional -/// `Send + Sync + 'static` trait requirements on their generics. -/// /// If this builder finds out that a command isn't valid because of synchronization reasons (eg. /// trying to copy from a buffer to an image which share the same memory), then an error is /// returned. @@ -863,10 +860,10 @@ unsafe impl DeviceOwned for SyncCommandBufferBuilder { } } -impl fmt::Debug for SyncCommandBufferBuilder { +impl Debug for SyncCommandBufferBuilder { #[inline] - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&self.inner, f) + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { + Debug::fmt(&self.inner, f) } } @@ -886,12 +883,12 @@ pub enum SyncCommandBufferBuilderError { impl Error for SyncCommandBufferBuilderError {} -impl fmt::Display for SyncCommandBufferBuilderError { +impl Display for SyncCommandBufferBuilderError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match self { - SyncCommandBufferBuilderError::Conflict { .. } => write!(fmt, "unsolvable conflict"), - SyncCommandBufferBuilderError::ExecError(err) => err.fmt(fmt), + SyncCommandBufferBuilderError::Conflict { .. } => write!(f, "unsolvable conflict"), + SyncCommandBufferBuilderError::ExecError(err) => Display::fmt(err, f), } } } diff --git a/vulkano/src/command_buffer/synced/mod.rs b/vulkano/src/command_buffer/synced/mod.rs index 5c1c3845ee..a3cc2633fc 100644 --- a/vulkano/src/command_buffer/synced/mod.rs +++ b/vulkano/src/command_buffer/synced/mod.rs @@ -84,7 +84,13 @@ use crate::{ }, DeviceSize, }; -use std::{borrow::Cow, collections::HashMap, ops::Range, sync::Arc}; +use std::{ + borrow::Cow, + collections::HashMap, + fmt::{Debug, Error as FmtError, Formatter}, + ops::Range, + sync::Arc, +}; mod builder; @@ -513,8 +519,8 @@ pub(super) trait Command: Send + Sync { unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder); } -impl std::fmt::Debug for dyn Command { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl Debug for dyn Command { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { f.write_str(self.name()) } } diff --git a/vulkano/src/command_buffer/traits.rs b/vulkano/src/command_buffer/traits.rs index 7c7affcf03..7146f864d7 100644 --- a/vulkano/src/command_buffer/traits.rs +++ b/vulkano/src/command_buffer/traits.rs @@ -26,7 +26,7 @@ use parking_lot::Mutex; use std::{ borrow::Cow, error::Error, - fmt, + fmt::{Display, Error as FmtError, Formatter}, ops::Range, sync::{ atomic::{AtomicBool, Ordering}, @@ -540,11 +540,11 @@ impl Error for CommandBufferExecError { } } -impl fmt::Display for CommandBufferExecError { +impl Display for CommandBufferExecError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { write!( - fmt, + f, "{}", match *self { CommandBufferExecError::AccessError { .. } => diff --git a/vulkano/src/descriptor_set/layout.rs b/vulkano/src/descriptor_set/layout.rs index 4e80ffea5b..97b638b755 100644 --- a/vulkano/src/descriptor_set/layout.rs +++ b/vulkano/src/descriptor_set/layout.rs @@ -13,15 +13,15 @@ use crate::{ device::{Device, DeviceOwned}, - macros::{vulkan_enum, ExtensionNotEnabled}, + macros::vulkan_enum, sampler::Sampler, shader::{DescriptorRequirements, ShaderStages}, - OomError, Version, VulkanError, VulkanObject, + OomError, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject, }; use std::{ collections::{BTreeMap, HashMap}, error::Error, - fmt, + fmt::{Display, Error as FmtError, Formatter}, hash::{Hash, Hasher}, mem::MaybeUninit, ptr, @@ -115,9 +115,12 @@ impl DescriptorSetLayout { if push_descriptor { if !device.enabled_extensions().khr_push_descriptor { - return Err(DescriptorSetLayoutCreationError::ExtensionNotEnabled { - extension: "khr_push_descriptor", - reason: "description was set to be a push descriptor", + return Err(DescriptorSetLayoutCreationError::RequirementNotMet { + required_for: "`create_info.push_descriptor` is set", + requires_one_of: RequiresOneOf { + device_extensions: &["khr_push_descriptor"], + ..Default::default() + }, }); } } @@ -135,11 +138,11 @@ impl DescriptorSetLayout { } = binding; // VUID-VkDescriptorSetLayoutBinding-descriptorType-parameter - descriptor_type.validate(device)?; + descriptor_type.validate_device(device)?; if descriptor_count != 0 { // VUID-VkDescriptorSetLayoutBinding-descriptorCount-00283 - stages.validate(device)?; + stages.validate_device(device)?; *descriptor_counts.entry(descriptor_type).or_default() += descriptor_count; } @@ -213,9 +216,12 @@ impl DescriptorSetLayout { .enabled_features() .descriptor_binding_variable_descriptor_count { - return Err(DescriptorSetLayoutCreationError::FeatureNotEnabled { - feature: "descriptor_binding_variable_descriptor_count", - reason: "binding has a variable count", + return Err(DescriptorSetLayoutCreationError::RequirementNotMet { + required_for: "`create_info.bindings` has an element where `variable_descriptor_count` is set", + requires_one_of: RequiresOneOf { + features: &["descriptor_binding_variable_descriptor_count"], + ..Default::default() + }, }); } @@ -465,13 +471,9 @@ pub enum DescriptorSetLayoutCreationError { /// Out of Memory. OomError(OomError), - ExtensionNotEnabled { - extension: &'static str, - reason: &'static str, - }, - FeatureNotEnabled { - feature: &'static str, - reason: &'static str, + RequirementNotMet { + required_for: &'static str, + requires_one_of: RequiresOneOf, }, /// A binding includes immutable samplers but their number differs from `descriptor_count`. @@ -514,28 +516,30 @@ impl From for DescriptorSetLayoutCreationError { impl Error for DescriptorSetLayoutCreationError {} -impl std::fmt::Display for DescriptorSetLayoutCreationError { +impl Display for DescriptorSetLayoutCreationError { #[inline] - fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match *self { Self::OomError(_) => { - write!(fmt, "out of memory") + write!(f, "out of memory") } - Self::ExtensionNotEnabled { extension, reason } => write!( - fmt, - "the extension {} must be enabled: {}", - extension, reason + + Self::RequirementNotMet { + required_for, + requires_one_of, + } => write!( + f, + "a requirement was not met for: {}; requires one of: {}", + required_for, requires_one_of, ), - Self::FeatureNotEnabled { feature, reason } => { - write!(fmt, "the feature {} must be enabled: {}", feature, reason) - } + Self::ImmutableSamplersCountMismatch { binding_num, sampler_count, descriptor_count } => write!( - fmt, + f, "binding {} includes immutable samplers but their number ({}) differs from `descriptor_count` ({})", binding_num, sampler_count, descriptor_count, ), Self::ImmutableSamplersDescriptorTypeIncompatible { binding_num } => write!( - fmt, + f, "binding {} includes immutable samplers but it has an incompatible `descriptor_type`", binding_num, ), @@ -543,27 +547,27 @@ impl std::fmt::Display for DescriptorSetLayoutCreationError { provided, max_supported, } => write!( - fmt, + f, "more descriptors were provided in all bindings ({}) than the `max_push_descriptors` limit ({})", provided, max_supported, ), Self::PushDescriptorDescriptorTypeIncompatible { binding_num } => write!( - fmt, + f, "`push_descriptor` is enabled, but binding {} has an incompatible `descriptor_type`", binding_num, ), Self::PushDescriptorVariableDescriptorCount { binding_num } => write!( - fmt, + f, "`push_descriptor` is enabled, but binding {} has `variable_descriptor_count` enabled", binding_num, ), Self::VariableDescriptorCountBindingNotHighest { binding_num, highest_binding_num } => write!( - fmt, + f, "binding {} has `variable_descriptor_count` enabled, but it is not the highest-numbered binding ({})", binding_num, highest_binding_num, ), Self::VariableDescriptorCountDescriptorTypeIncompatible { binding_num } => write!( - fmt, + f, "binding {} has `variable_descriptor_count` enabled, but it has an incompatible `descriptor_type`", binding_num, ), @@ -571,12 +575,12 @@ impl std::fmt::Display for DescriptorSetLayoutCreationError { } } -impl From for DescriptorSetLayoutCreationError { +impl From for DescriptorSetLayoutCreationError { #[inline] - fn from(err: ExtensionNotEnabled) -> Self { - Self::ExtensionNotEnabled { - extension: err.extension, - reason: err.reason, + fn from(err: RequirementNotMet) -> Self { + Self::RequirementNotMet { + required_for: err.required_for, + requires_one_of: err.requires_one_of, } } } @@ -792,22 +796,22 @@ pub enum DescriptorRequirementsNotMet { impl Error for DescriptorRequirementsNotMet {} -impl fmt::Display for DescriptorRequirementsNotMet { +impl Display for DescriptorRequirementsNotMet { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match self { Self::DescriptorType { required, obtained } => write!( - fmt, + f, "the descriptor's type ({:?}) is not one of those required ({:?})", obtained, required ), Self::DescriptorCount { required, obtained } => write!( - fmt, + f, "the descriptor count ({}) is less than what is required ({})", obtained, required ), Self::ShaderStages { .. } => write!( - fmt, + f, "the descriptor's shader stages do not contain the stages that are required", ), } @@ -863,22 +867,22 @@ vulkan_enum! { // TODO: document InlineUniformBlock = INLINE_UNIFORM_BLOCK { api_version: V1_3, - extensions: [ext_inline_uniform_block], + device_extensions: [ext_inline_uniform_block], }, // TODO: document AccelerationStructure = ACCELERATION_STRUCTURE_KHR { - extensions: [khr_acceleration_structure], + device_extensions: [khr_acceleration_structure], }, // TODO: document AccelerationStructureNV = ACCELERATION_STRUCTURE_NV { - extensions: [nv_ray_tracing], + device_extensions: [nv_ray_tracing], }, // TODO: document Mutable = MUTABLE_VALVE { - extensions: [valve_mutable_descriptor_type], + device_extensions: [valve_mutable_descriptor_type], }, */ } diff --git a/vulkano/src/descriptor_set/mod.rs b/vulkano/src/descriptor_set/mod.rs index fde3b48f95..60673f748d 100644 --- a/vulkano/src/descriptor_set/mod.rs +++ b/vulkano/src/descriptor_set/mod.rs @@ -93,6 +93,7 @@ use smallvec::{smallvec, SmallVec}; use std::{ collections::HashMap, error::Error, + fmt::{Display, Error as FmtError, Formatter}, hash::{Hash, Hasher}, ptr, sync::Arc, @@ -504,9 +505,9 @@ impl Error for DescriptorSetCreationError { } } -impl std::fmt::Display for DescriptorSetCreationError { +impl Display for DescriptorSetCreationError { #[inline] - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match self { Self::DescriptorSetUpdateError(_) => { write!(f, "an error occurred while updating the descriptor set") diff --git a/vulkano/src/descriptor_set/pool/sys.rs b/vulkano/src/descriptor_set/pool/sys.rs index 324bdff0e1..889428106b 100644 --- a/vulkano/src/descriptor_set/pool/sys.rs +++ b/vulkano/src/descriptor_set/pool/sys.rs @@ -19,7 +19,7 @@ use smallvec::SmallVec; use std::{ collections::HashMap, error::Error, - fmt, + fmt::{Display, Error as FmtError, Formatter}, hash::{Hash, Hasher}, mem::MaybeUninit, ptr, @@ -426,11 +426,11 @@ pub enum DescriptorPoolAllocError { impl Error for DescriptorPoolAllocError {} -impl fmt::Display for DescriptorPoolAllocError { +impl Display for DescriptorPoolAllocError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { write!( - fmt, + f, "{}", match *self { DescriptorPoolAllocError::OutOfHostMemory => "no memory available on the host", diff --git a/vulkano/src/descriptor_set/sys.rs b/vulkano/src/descriptor_set/sys.rs index 3ccfa7dbdf..8b09d9dbf4 100644 --- a/vulkano/src/descriptor_set/sys.rs +++ b/vulkano/src/descriptor_set/sys.rs @@ -18,7 +18,10 @@ use crate::{ VulkanObject, }; use smallvec::SmallVec; -use std::{fmt, ptr}; +use std::{ + fmt::{Debug, Error as FmtError, Formatter}, + ptr, +}; /// Low-level descriptor set. /// @@ -114,8 +117,8 @@ unsafe impl VulkanObject for UnsafeDescriptorSet { } } -impl fmt::Debug for UnsafeDescriptorSet { - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!(fmt, "", self.handle) +impl Debug for UnsafeDescriptorSet { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { + write!(f, "", self.handle) } } diff --git a/vulkano/src/descriptor_set/update.rs b/vulkano/src/descriptor_set/update.rs index 3351685d58..a489a31bdf 100644 --- a/vulkano/src/descriptor_set/update.rs +++ b/vulkano/src/descriptor_set/update.rs @@ -16,7 +16,12 @@ use crate::{ DeviceSize, VulkanObject, }; use smallvec::SmallVec; -use std::{error::Error, ptr, sync::Arc}; +use std::{ + error::Error, + fmt::{Display, Error as FmtError, Formatter}, + ptr, + sync::Arc, +}; /// Represents a single write operation to the binding of a descriptor set. /// @@ -943,56 +948,56 @@ impl Error for DescriptorSetUpdateError { } } -impl std::fmt::Display for DescriptorSetUpdateError { +impl Display for DescriptorSetUpdateError { #[inline] - fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match self { Self::ArrayIndexOutOfBounds { binding, available_count, written_count, } => write!( - fmt, + f, "tried to write up to element {} to binding {}, but only {} descriptors are available", written_count, binding, available_count, ), Self::ImageView2dFrom3d { binding, index } => write!( - fmt, + f, "tried to write an image view to binding {} index {} with a 2D type and a 3D underlying image", binding, index, ), Self::ImageViewDepthAndStencil { binding, index } => write!( - fmt, + f, "tried to write an image view to binding {} index {} that has both the `depth` and `stencil` aspects", binding, index, ), Self::ImageViewHasSamplerYcbcrConversion { binding, index } => write!( - fmt, + f, "tried to write an image view to binding {} index {} with an attached sampler YCbCr conversion to binding that does not support it", binding, index, ), Self::ImageViewIsArrayed { binding, index } => write!( - fmt, + f, "tried to write an image view of an arrayed type to binding {} index {}, but this binding has a descriptor type that does not support arrayed image views", binding, index, ), Self::ImageViewIncompatibleSampler { binding, index, .. } => write!( - fmt, + f, "tried to write an image view to binding {} index {}, that was not compatible with the sampler that was provided as part of the update or immutably in the layout", binding, index, ), Self::ImageViewNotIdentitySwizzled { binding, index } => write!( - fmt, + f, "tried to write an image view with non-identity swizzling to binding {} index {}, but this binding has a descriptor type that requires it to be identity swizzled", binding, index, ), Self::IncompatibleDescriptorType { binding } => write!( - fmt, + f, "tried to write a resource to binding {} whose type was not compatible with the descriptor type", binding, ), Self::InvalidBinding { binding } => write!( - fmt, + f, "tried to write to a nonexistent binding {}", binding, ), @@ -1001,17 +1006,17 @@ impl std::fmt::Display for DescriptorSetUpdateError { index, usage, } => write!( - fmt, + f, "tried to write a resource to binding {} index {} that did not have the required usage {} enabled", binding, index, usage, ), Self::SamplerHasSamplerYcbcrConversion { binding, index } => write!( - fmt, + f, "tried to write a sampler to binding {} index {} that has an attached sampler YCbCr conversion", binding, index, ), Self::SamplerIsImmutable { binding } => write!( - fmt, + f, "tried to write a sampler to binding {}, which already contains immutable samplers in the descriptor set layout", binding, ), diff --git a/vulkano/src/device/extensions.rs b/vulkano/src/device/extensions.rs index 083c61f076..124c1c7e8d 100644 --- a/vulkano/src/device/extensions.rs +++ b/vulkano/src/device/extensions.rs @@ -7,13 +7,7 @@ // notice may not be copied, modified, or distributed except // according to those terms. -pub use crate::extensions::{ExtensionRestriction, ExtensionRestrictionError, OneOfRequirements}; -use crate::{instance::InstanceExtensions, Version}; -use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Sub, SubAssign}; -use std::{ - ffi::{CStr, CString}, - fmt::Formatter, -}; +pub use crate::extensions::{ExtensionRestriction, ExtensionRestrictionError}; // Generated by build.rs include!(concat!(env!("OUT_DIR"), "/device_extensions.rs")); diff --git a/vulkano/src/device/features.rs b/vulkano/src/device/features.rs index d92c8f4c53..e349026989 100644 --- a/vulkano/src/device/features.rs +++ b/vulkano/src/device/features.rs @@ -7,10 +7,10 @@ // notice may not be copied, modified, or distributed except // according to those terms. -use crate::{device::DeviceExtensions, instance::InstanceExtensions, Version}; -use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Sub, SubAssign}; -use std::fmt::Display; -use std::{error::Error, fmt, fmt::Formatter}; +use std::{ + error::Error, + fmt::{Display, Error as FmtError, Formatter}, +}; // Generated by build.rs include!(concat!(env!("OUT_DIR"), "/features.rs")); @@ -28,9 +28,9 @@ impl Error for FeatureRestrictionError {} impl Display for FeatureRestrictionError { #[inline] - fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { write!( - fmt, + f, "a restriction for the feature {} was not met: {}", self.feature, self.restriction, ) @@ -51,19 +51,19 @@ pub enum FeatureRestriction { impl Display for FeatureRestriction { #[inline] - fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match *self { FeatureRestriction::NotSupported => { - write!(fmt, "not supported by the physical device") + write!(f, "not supported by the physical device") } FeatureRestriction::RequiresFeature(feat) => { - write!(fmt, "requires feature {} to be enabled", feat) + write!(f, "requires feature {} to be enabled", feat) } FeatureRestriction::ConflictsFeature(feat) => { - write!(fmt, "requires feature {} to be disabled", feat) + write!(f, "requires feature {} to be disabled", feat) } FeatureRestriction::RequiredByExtension(ext) => { - write!(fmt, "required to be enabled by extension {}", ext) + write!(f, "required to be enabled by extension {}", ext) } } } diff --git a/vulkano/src/device/mod.rs b/vulkano/src/device/mod.rs index fa2e23fec2..249e74d3c0 100644 --- a/vulkano/src/device/mod.rs +++ b/vulkano/src/device/mod.rs @@ -106,9 +106,9 @@ use crate::{ command_buffer::pool::StandardCommandPool, descriptor_set::pool::StandardDescriptorPool, instance::{debug::DebugUtilsLabel, Instance}, - macros::ExtensionNotEnabled, memory::{pool::StandardMemoryPool, ExternalMemoryHandleType}, - OomError, SynchronizedVulkanObject, Version, VulkanError, VulkanObject, + OomError, RequirementNotMet, RequiresOneOf, SynchronizedVulkanObject, Version, VulkanError, + VulkanObject, }; pub use crate::{ device::extensions::DeviceExtensions, @@ -124,7 +124,7 @@ use std::{ collections::{hash_map::Entry, HashMap}, error::Error, ffi::CString, - fmt, + fmt::{Display, Error as FmtError, Formatter}, fs::File, hash::{Hash, Hasher}, mem::MaybeUninit, @@ -633,7 +633,7 @@ impl Device { use std::os::unix::io::IntoRawFd; // VUID-vkGetMemoryFdPropertiesKHR-handleType-parameter - handle_type.validate(self)?; + handle_type.validate_device(self)?; // VUID-vkGetMemoryFdPropertiesKHR-handleType-00674 if handle_type == ExternalMemoryHandleType::OpaqueFd { @@ -766,44 +766,44 @@ pub enum DeviceCreationError { impl Error for DeviceCreationError {} -impl fmt::Display for DeviceCreationError { +impl Display for DeviceCreationError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match *self { Self::InitializationFailed => { write!( - fmt, + f, "failed to create the device for an implementation-specific reason" ) } - Self::OutOfHostMemory => write!(fmt, "no memory available on the host"), + Self::OutOfHostMemory => write!(f, "no memory available on the host"), Self::OutOfDeviceMemory => { - write!(fmt, "no memory available on the graphical device") + write!(f, "no memory available on the graphical device") } - Self::DeviceLost => write!(fmt, "failed to connect to the device"), + Self::DeviceLost => write!(f, "failed to connect to the device"), Self::TooManyQueuesForFamily => { - write!(fmt, "tried to create too many queues for a given family") + write!(f, "tried to create too many queues for a given family") } Self::FeatureNotPresent => { write!( - fmt, + f, "some of the requested features are unsupported by the physical device" ) } Self::PriorityOutOfRange => { write!( - fmt, + f, "the priority of one of the queues is out of the [0.0; 1.0] range" ) } Self::ExtensionNotPresent => { - write!(fmt,"some of the requested device extensions are not supported by the physical device") + write!(f,"some of the requested device extensions are not supported by the physical device") } Self::TooManyObjects => { - write!(fmt,"you have reached the limit to the number of devices that can be created from the same physical device") + write!(f,"you have reached the limit to the number of devices that can be created from the same physical device") } - Self::ExtensionRestrictionNotMet(err) => err.fmt(fmt), - Self::FeatureRestrictionNotMet(err) => err.fmt(fmt), + Self::ExtensionRestrictionNotMet(err) => err.fmt(f), + Self::FeatureRestrictionNotMet(err) => err.fmt(f), } } } @@ -938,9 +938,9 @@ pub enum MemoryFdPropertiesError { /// No memory available on the host. OutOfHostMemory, - ExtensionNotEnabled { - extension: &'static str, - reason: &'static str, + RequirementNotMet { + required_for: &'static str, + requires_one_of: RequiresOneOf, }, /// The provided external handle was not valid. @@ -955,24 +955,29 @@ pub enum MemoryFdPropertiesError { impl Error for MemoryFdPropertiesError {} -impl fmt::Display for MemoryFdPropertiesError { +impl Display for MemoryFdPropertiesError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match *self { - Self::OutOfHostMemory => write!(fmt, "no memory available on the host"), - Self::ExtensionNotEnabled { extension, reason } => write!( - fmt, - "the extension {} must be enabled: {}", - extension, reason + Self::OutOfHostMemory => write!(f, "no memory available on the host"), + + Self::RequirementNotMet { + required_for, + requires_one_of, + } => write!( + f, + "a requirement was not met for: {}; requires one of: {}", + required_for, requires_one_of, ), + Self::InvalidExternalHandle => { - write!(fmt, "the provided external handle was not valid") + write!(f, "the provided external handle was not valid") } Self::InvalidExternalHandleType => { - write!(fmt, "the provided external handle type was not valid") + write!(f, "the provided external handle type was not valid") } Self::NotSupported => write!( - fmt, + f, "the `khr_external_memory_fd` extension was not enabled on the device", ), } @@ -990,12 +995,12 @@ impl From for MemoryFdPropertiesError { } } -impl From for MemoryFdPropertiesError { +impl From for MemoryFdPropertiesError { #[inline] - fn from(err: ExtensionNotEnabled) -> Self { - Self::ExtensionNotEnabled { - extension: err.extension, - reason: err.reason, + fn from(err: RequirementNotMet) -> Self { + Self::RequirementNotMet { + required_for: err.required_for, + requires_one_of: err.requires_one_of, } } } @@ -1090,9 +1095,12 @@ impl Queue { .enabled_extensions() .ext_debug_utils { - return Err(DebugUtilsError::ExtensionNotEnabled { - extension: "ext_debug_utils", - reason: "tried to submit a debug utils command", + return Err(DebugUtilsError::RequirementNotMet { + required_for: "`begin_debug_utils_label`", + requires_one_of: RequiresOneOf { + instance_extensions: &["ext_debug_utils"], + ..Default::default() + }, }); } @@ -1128,9 +1136,12 @@ impl Queue { .enabled_extensions() .ext_debug_utils { - return Err(DebugUtilsError::ExtensionNotEnabled { - extension: "ext_debug_utils", - reason: "tried to submit a debug utils command", + return Err(DebugUtilsError::RequirementNotMet { + required_for: "`end_debug_utils_label`", + requires_one_of: RequiresOneOf { + instance_extensions: &["ext_debug_utils"], + ..Default::default() + }, }); } @@ -1183,9 +1194,12 @@ impl Queue { .enabled_extensions() .ext_debug_utils { - return Err(DebugUtilsError::ExtensionNotEnabled { - extension: "ext_debug_utils", - reason: "tried to submit a debug utils command", + return Err(DebugUtilsError::RequirementNotMet { + required_for: "`insert_debug_utils_label`", + requires_one_of: RequiresOneOf { + instance_extensions: &["ext_debug_utils"], + ..Default::default() + }, }); } @@ -1228,21 +1242,26 @@ impl Hash for Queue { /// Error that can happen when submitting a debug utils command to a queue. #[derive(Clone, Debug)] pub enum DebugUtilsError { - ExtensionNotEnabled { - extension: &'static str, - reason: &'static str, + RequirementNotMet { + required_for: &'static str, + requires_one_of: RequiresOneOf, }, } impl Error for DebugUtilsError {} -impl fmt::Display for DebugUtilsError { +impl Display for DebugUtilsError { #[inline] - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match self { - Self::ExtensionNotEnabled { extension, reason } => { - write!(f, "the extension {} must be enabled: {}", extension, reason) - } + Self::RequirementNotMet { + required_for, + requires_one_of, + } => write!( + f, + "a requirement was not met for: {}; requires one of: {}", + required_for, requires_one_of, + ), } } } diff --git a/vulkano/src/device/physical.rs b/vulkano/src/device/physical.rs index df67c15af7..aa00412901 100644 --- a/vulkano/src/device/physical.rs +++ b/vulkano/src/device/physical.rs @@ -19,9 +19,17 @@ use crate::{ SurfaceApi, SurfaceCapabilities, SurfaceInfo, }, sync::{ExternalSemaphoreInfo, ExternalSemaphoreProperties, PipelineStage}, - DeviceSize, OomError, Version, VulkanError, VulkanObject, + DeviceSize, OomError, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject, +}; +use std::{ + error::Error, + ffi::CStr, + fmt::{Debug, Display, Error as FmtError, Formatter}, + hash::Hash, + mem::MaybeUninit, + ptr, + sync::Arc, }; -use std::{error::Error, ffi::CStr, fmt, hash::Hash, mem::MaybeUninit, ptr, sync::Arc}; #[derive(Clone, Debug)] pub(crate) struct PhysicalDeviceInfo { @@ -434,20 +442,27 @@ impl<'a> PhysicalDevice<'a> { /// Retrieves the external memory properties supported for buffers with a given configuration. /// - /// Returns `None` if the instance API version is less than 1.1 and the + /// Instance API version must be at least 1.1, or the /// [`khr_external_memory_capabilities`](crate::instance::InstanceExtensions::khr_external_memory_capabilities) - /// extension is not enabled on the instance. + /// extension must be enabled on the instance. pub fn external_buffer_properties( &self, info: ExternalBufferInfo, - ) -> Option { + ) -> Result { if !(self.instance.api_version() >= Version::V1_1 || self .instance .enabled_extensions() .khr_external_memory_capabilities) { - return None; + return Err(ExternalBufferPropertiesError::RequirementNotMet { + required_for: "`external_buffer_properties`", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_1), + instance_extensions: &["khr_external_memory_capabilities"], + ..Default::default() + }, + }); } /* Input */ @@ -460,12 +475,12 @@ impl<'a> PhysicalDevice<'a> { } = info; // VUID-VkPhysicalDeviceExternalBufferInfo-usage-parameter - // TODO: usage.validate()?; + usage.validate_physical_device(self)?; assert!(!usage.is_empty()); // VUID-VkPhysicalDeviceExternalBufferInfo-handleType-parameter - // TODO: handle_type.validate()?; + handle_type.validate_physical_device(self)?; let external_buffer_info = ash::vk::PhysicalDeviceExternalBufferInfo { flags: sparse.map(Into::into).unwrap_or_default(), @@ -499,7 +514,7 @@ impl<'a> PhysicalDevice<'a> { } } - Some(ExternalBufferProperties { + Ok(ExternalBufferProperties { external_memory_properties: external_buffer_properties .external_memory_properties .into(), @@ -576,20 +591,27 @@ impl<'a> PhysicalDevice<'a> { /// Retrieves the external handle properties supported for semaphores with a given /// configuration. /// - /// Returns `None` if the instance API version is less than 1.1 and the + /// The instance API version must be at least 1.1, or the /// [`khr_external_semaphore_capabilities`](crate::instance::InstanceExtensions::khr_external_semaphore_capabilities) - /// extension is not enabled on the instance. + /// extension must be enabled on the instance. pub fn external_semaphore_properties( &self, info: ExternalSemaphoreInfo, - ) -> Option { + ) -> Result { if !(self.instance.api_version() >= Version::V1_1 || self .instance .enabled_extensions() .khr_external_semaphore_capabilities) { - return None; + return Err(ExternalSemaphorePropertiesError::RequirementNotMet { + required_for: "`external_semaphore_properties`", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_1), + instance_extensions: &["khr_external_semaphore_capabilities"], + ..Default::default() + }, + }); } /* Input */ @@ -600,7 +622,7 @@ impl<'a> PhysicalDevice<'a> { } = info; // VUID-VkPhysicalDeviceExternalSemaphoreInfo-handleType-parameter - // TODO: handle_type.validate()?; + handle_type.validate_physical_device(self)?; let external_semaphore_info = ash::vk::PhysicalDeviceExternalSemaphoreInfo { handle_type: handle_type.into(), @@ -632,7 +654,7 @@ impl<'a> PhysicalDevice<'a> { } } - Some(ExternalSemaphoreProperties { + Ok(ExternalSemaphoreProperties { exportable: external_semaphore_properties .external_semaphore_features .intersects(ash::vk::ExternalSemaphoreFeatureFlags::EXPORTABLE), @@ -656,7 +678,7 @@ impl<'a> PhysicalDevice<'a> { pub fn image_format_properties( &self, image_format_info: ImageFormatInfo, - ) -> Result, OomError> { + ) -> Result, ImageFormatPropertiesError> { /* Input */ let ImageFormatInfo { format, @@ -673,22 +695,16 @@ impl<'a> PhysicalDevice<'a> { } = image_format_info; // VUID-VkPhysicalDeviceImageFormatInfo2-format-parameter - // TODO: format.validate()?; + // TODO: format.validate_physical_device(self)?; // VUID-VkPhysicalDeviceImageFormatInfo2-imageType-parameter - // TODO: image_type.validate()?; + image_type.validate_physical_device(self)?; // VUID-VkPhysicalDeviceImageFormatInfo2-tiling-parameter - // TODO: tiling.validate()?; + tiling.validate_physical_device(self)?; // VUID-VkPhysicalDeviceImageFormatInfo2-usage-parameter - // TODO: usage.validate()?; - - // VUID-VkPhysicalDeviceExternalImageFormatInfo-handleType-parameter - // TODO: external_memory_handle_type.validate()?; - - // VUID-VkPhysicalDeviceImageViewImageFormatInfoEXT-imageViewType-parameter - // TODO: image_view_type.validate()?; + usage.validate_physical_device(self)?; let flags = ImageCreateFlags { mutable_format, @@ -713,10 +729,19 @@ impl<'a> PhysicalDevice<'a> { .enabled_extensions() .khr_external_memory_capabilities) { - // Can't query this, return unsupported - return Ok(None); + return Err(ImageFormatPropertiesError::RequirementNotMet { + required_for: "`image_format_info.external_memory_handle_type` is `Some`", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_1), + instance_extensions: &["khr_external_memory_capabilities"], + ..Default::default() + }, + }); } + // VUID-VkPhysicalDeviceExternalImageFormatInfo-handleType-parameter + handle_type.validate_physical_device(self)?; + Some( ash::vk::PhysicalDeviceExternalImageFormatInfo::builder() .handle_type(handle_type.into()), @@ -730,13 +755,19 @@ impl<'a> PhysicalDevice<'a> { } let mut image_view_image_format_info = if let Some(image_view_type) = image_view_type { - if !(self.supported_extensions().ext_filter_cubic - || self.supported_extensions().img_filter_cubic) - { - // Can't query this, return unsupported - return Ok(None); + if !self.supported_extensions().ext_filter_cubic { + return Err(ImageFormatPropertiesError::RequirementNotMet { + required_for: "`image_format_info.image_view_type` is `Some`", + requires_one_of: RequiresOneOf { + device_extensions: &["ext_filter_cubic"], + ..Default::default() + }, + }); } + // VUID-VkPhysicalDeviceImageViewImageFormatInfoEXT-imageViewType-parameter + image_view_type.validate_physical_device(self)?; + if !image_view_type.is_compatible_with(image_type) { return Ok(None); } @@ -1680,15 +1711,15 @@ impl From for ConformanceVersion { } } -impl fmt::Debug for ConformanceVersion { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +impl Debug for ConformanceVersion { + fn fmt(&self, formatter: &mut Formatter) -> Result<(), FmtError> { write!(formatter, "{}.{}.{}", self.major, self.minor, self.patch) } } -impl fmt::Display for ConformanceVersion { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(self, formatter) +impl Display for ConformanceVersion { + fn fmt(&self, formatter: &mut Formatter) -> Result<(), FmtError> { + Debug::fmt(self, formatter) } } @@ -1771,7 +1802,7 @@ vulkan_bitflags! { // TODO: document partitioned = PARTITIONED_NV { - extensions: [nv_shader_subgroup_partitioned], + device_extensions: [nv_shader_subgroup_partitioned], }, } @@ -1814,9 +1845,143 @@ impl From for ShaderCoreProperties { } } +/// Error that can happen when retrieving properties of an external buffer. +#[derive(Clone, Debug)] +pub enum ExternalBufferPropertiesError { + RequirementNotMet { + required_for: &'static str, + requires_one_of: RequiresOneOf, + }, +} + +impl Error for ExternalBufferPropertiesError {} + +impl Display for ExternalBufferPropertiesError { + #[inline] + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { + match self { + Self::RequirementNotMet { + required_for, + requires_one_of, + } => write!( + f, + "a requirement was not met for: {}; requires one of: {}", + required_for, requires_one_of, + ), + } + } +} + +impl From for ExternalBufferPropertiesError { + #[inline] + fn from(err: RequirementNotMet) -> Self { + Self::RequirementNotMet { + required_for: err.required_for, + requires_one_of: err.requires_one_of, + } + } +} + +/// Error that can happen when retrieving properties of an external semaphore. +#[derive(Clone, Debug)] +pub enum ExternalSemaphorePropertiesError { + RequirementNotMet { + required_for: &'static str, + requires_one_of: RequiresOneOf, + }, +} + +impl Error for ExternalSemaphorePropertiesError {} + +impl Display for ExternalSemaphorePropertiesError { + #[inline] + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { + match self { + Self::RequirementNotMet { + required_for, + requires_one_of, + } => write!( + f, + "a requirement was not met for: {}; requires one of: {}", + required_for, requires_one_of, + ), + } + } +} + +impl From for ExternalSemaphorePropertiesError { + #[inline] + fn from(err: RequirementNotMet) -> Self { + Self::RequirementNotMet { + required_for: err.required_for, + requires_one_of: err.requires_one_of, + } + } +} + +/// Error that can happen when retrieving format properties of an image. +#[derive(Clone, Debug)] +pub enum ImageFormatPropertiesError { + /// Not enough memory. + OomError(OomError), + + RequirementNotMet { + required_for: &'static str, + requires_one_of: RequiresOneOf, + }, +} + +impl Error for ImageFormatPropertiesError { + #[inline] + fn source(&self) -> Option<&(dyn Error + 'static)> { + match self { + Self::OomError(err) => Some(err), + _ => None, + } + } +} + +impl Display for ImageFormatPropertiesError { + #[inline] + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { + match self { + Self::OomError(_) => write!(f, "not enough memory"), + + Self::RequirementNotMet { + required_for, + requires_one_of, + } => write!( + f, + "a requirement was not met for: {}; requires one of: {}", + required_for, requires_one_of, + ), + } + } +} + +impl From for ImageFormatPropertiesError { + #[inline] + fn from(err: VulkanError) -> Self { + match err { + err @ VulkanError::OutOfHostMemory => Self::OomError(OomError::from(err)), + err @ VulkanError::OutOfDeviceMemory => Self::OomError(OomError::from(err)), + _ => panic!("unexpected error: {:?}", err), + } + } +} + +impl From for ImageFormatPropertiesError { + #[inline] + fn from(err: RequirementNotMet) -> Self { + Self::RequirementNotMet { + required_for: err.required_for, + requires_one_of: err.requires_one_of, + } + } +} + /// Error that can happen when retrieving properties of a surface. #[derive(Copy, Clone, Debug, PartialEq, Eq)] -#[repr(u32)] pub enum SurfacePropertiesError { /// Not enough memory. OomError(OomError), @@ -1838,11 +2003,11 @@ impl Error for SurfacePropertiesError { } } -impl fmt::Display for SurfacePropertiesError { +impl Display for SurfacePropertiesError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { write!( - fmt, + f, "{}", match *self { Self::OomError(_) => "not enough memory", diff --git a/vulkano/src/extensions.rs b/vulkano/src/extensions.rs index 93e5312b9a..cac04a31f1 100644 --- a/vulkano/src/extensions.rs +++ b/vulkano/src/extensions.rs @@ -7,7 +7,7 @@ // notice may not be copied, modified, or distributed except // according to those terms. -use crate::Version; +use crate::RequiresOneOf; use std::{ error::Error, fmt::{Display, Error as FmtError, Formatter}, @@ -26,9 +26,9 @@ impl Error for ExtensionRestrictionError {} impl Display for ExtensionRestrictionError { #[inline] - fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { write!( - fmt, + f, "a restriction for the extension {} was not met: {}", self.extension, self.restriction, ) @@ -42,85 +42,31 @@ pub enum ExtensionRestriction { /// Required to be enabled by the physical device. RequiredIfSupported, /// Requires one of the following. - Requires(OneOfRequirements), + Requires(RequiresOneOf), /// Requires a device extension to be disabled. ConflictsDeviceExtension(&'static str), } impl Display for ExtensionRestriction { #[inline] - fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match *self { ExtensionRestriction::NotSupported => { - write!(fmt, "not supported by the loader or physical device") + write!(f, "not supported by the loader or physical device") } ExtensionRestriction::RequiredIfSupported => { - write!(fmt, "required to be enabled by the physical device") + write!(f, "required to be enabled by the physical device") } ExtensionRestriction::Requires(requires) => { - if requires.has_multiple() { - write!(fmt, "requires one of: {}", requires) + if requires.len() > 1 { + write!(f, "requires one of: {}", requires) } else { - write!(fmt, "requires: {}", requires) + write!(f, "requires: {}", requires) } } ExtensionRestriction::ConflictsDeviceExtension(ext) => { - write!(fmt, "requires device extension {} to be disabled", ext) + write!(f, "requires device extension {} to be disabled", ext) } } } } - -#[derive(Clone, Copy, Debug, Default)] -pub struct OneOfRequirements { - pub api_version: Option, - pub device_extensions: &'static [&'static str], - pub instance_extensions: &'static [&'static str], -} - -impl OneOfRequirements { - /// Returns whether there is more than one possible requirement. - #[inline] - pub fn has_multiple(&self) -> bool { - self.api_version.iter().count() - + self.device_extensions.len() - + self.instance_extensions.len() - > 1 - } -} - -impl Display for OneOfRequirements { - #[inline] - fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> { - let mut items_written = 0; - - if let Some(version) = self.api_version { - write!( - fmt, - "Vulkan API version {}.{}", - version.major, version.minor - )?; - items_written += 1; - } - - for ext in self.instance_extensions.iter() { - if items_written != 0 { - write!(fmt, ", ")?; - } - - write!(fmt, "instance extension {}", ext)?; - items_written += 1; - } - - for ext in self.device_extensions.iter() { - if items_written != 0 { - write!(fmt, ", ")?; - } - - write!(fmt, "device extension {}", ext)?; - items_written += 1; - } - - Ok(()) - } -} diff --git a/vulkano/src/format.rs b/vulkano/src/format.rs index 82f52573eb..f1adb941a5 100644 --- a/vulkano/src/format.rs +++ b/vulkano/src/format.rs @@ -760,14 +760,14 @@ vulkan_bitflags! { /// image view. storage_read_without_format = STORAGE_READ_WITHOUT_FORMAT { api_version: V1_3, - extensions: [khr_format_feature_flags2], + device_extensions: [khr_format_feature_flags2], }, /// Can be used with a storage image descriptor for writing, without specifying a format on the /// image view. storage_write_without_format = STORAGE_WRITE_WITHOUT_FORMAT { api_version: V1_3, - extensions: [khr_format_feature_flags2], + device_extensions: [khr_format_feature_flags2], }, /// Can be used with a color attachment in a framebuffer, or with an input attachment @@ -784,24 +784,24 @@ vulkan_bitflags! { /// Can be used with a fragment density map attachment in a framebuffer. fragment_density_map = FRAGMENT_DENSITY_MAP_EXT { - extensions: [ext_fragment_density_map], + device_extensions: [ext_fragment_density_map], }, /// Can be used with a fragment shading rate attachment in a framebuffer. fragment_shading_rate_attachment = FRAGMENT_SHADING_RATE_ATTACHMENT_KHR { - extensions: [khr_fragment_shading_rate], + device_extensions: [khr_fragment_shading_rate], }, /// Can be used with the source image in a transfer (copy) operation. transfer_src = TRANSFER_SRC { api_version: V1_1, - extensions: [khr_maintenance1], + device_extensions: [khr_maintenance1], }, /// Can be used with the destination image in a transfer (copy) operation. transfer_dst = TRANSFER_DST { api_version: V1_1, - extensions: [khr_maintenance1], + device_extensions: [khr_maintenance1], }, /// Can be used with the source image in a blit operation. @@ -819,7 +819,7 @@ vulkan_bitflags! { /// Can be used with samplers or as a blit source, using the /// [`Cubic`](crate::sampler::Filter::Cubic) filter. sampled_image_filter_cubic = SAMPLED_IMAGE_FILTER_CUBIC_EXT { - extensions: [ext_filter_cubic, img_filter_cubic], + device_extensions: [ext_filter_cubic, img_filter_cubic], }, /// Can be used with samplers using a reduction mode of @@ -827,76 +827,76 @@ vulkan_bitflags! { /// [`Max`](crate::sampler::SamplerReductionMode::Max). sampled_image_filter_minmax = SAMPLED_IMAGE_FILTER_MINMAX { api_version: V1_2, - extensions: [ext_sampler_filter_minmax], + device_extensions: [ext_sampler_filter_minmax], }, /// Can be used with sampler YCbCr conversions using a chroma offset of /// [`Midpoint`](crate::sampler::ycbcr::ChromaLocation::Midpoint). midpoint_chroma_samples = MIDPOINT_CHROMA_SAMPLES { api_version: V1_1, - extensions: [khr_sampler_ycbcr_conversion], + device_extensions: [khr_sampler_ycbcr_conversion], }, /// Can be used with sampler YCbCr conversions using a chroma offset of /// [`CositedEven`](crate::sampler::ycbcr::ChromaLocation::CositedEven). cosited_chroma_samples = COSITED_CHROMA_SAMPLES { api_version: V1_1, - extensions: [khr_sampler_ycbcr_conversion], + device_extensions: [khr_sampler_ycbcr_conversion], }, /// Can be used with sampler YCbCr conversions using the /// [`Linear`](crate::sampler::Filter::Linear) chroma filter. sampled_image_ycbcr_conversion_linear_filter = SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER { api_version: V1_1, - extensions: [khr_sampler_ycbcr_conversion], + device_extensions: [khr_sampler_ycbcr_conversion], }, /// Can be used with sampler YCbCr conversions whose chroma filter differs from the filters of /// the base sampler. sampled_image_ycbcr_conversion_separate_reconstruction_filter = SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER { api_version: V1_1, - extensions: [khr_sampler_ycbcr_conversion], + device_extensions: [khr_sampler_ycbcr_conversion], }, /// When used with a sampler YCbCr conversion, the implementation will always perform /// explicit chroma reconstruction. sampled_image_ycbcr_conversion_chroma_reconstruction_explicit = SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT { api_version: V1_1, - extensions: [khr_sampler_ycbcr_conversion], + device_extensions: [khr_sampler_ycbcr_conversion], }, /// Can be used with sampler YCbCr conversions with forced explicit reconstruction. sampled_image_ycbcr_conversion_chroma_reconstruction_explicit_forceable = SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE { api_version: V1_1, - extensions: [khr_sampler_ycbcr_conversion], + device_extensions: [khr_sampler_ycbcr_conversion], }, /// Can be used with samplers using depth comparison. sampled_image_depth_comparison = SAMPLED_IMAGE_DEPTH_COMPARISON { api_version: V1_3, - extensions: [khr_format_feature_flags2], + device_extensions: [khr_format_feature_flags2], }, /* Video */ /// Can be used with the output image of a video decode operation. video_decode_output = VIDEO_DECODE_OUTPUT_KHR { - extensions: [khr_video_decode_queue], + device_extensions: [khr_video_decode_queue], }, /// Can be used with the DPB image of a video decode operation. video_decode_dpb = VIDEO_DECODE_DPB_KHR { - extensions: [khr_video_decode_queue], + device_extensions: [khr_video_decode_queue], }, /// Can be used with the input image of a video encode operation. video_encode_input = VIDEO_ENCODE_INPUT_KHR { - extensions: [khr_video_encode_queue], + device_extensions: [khr_video_encode_queue], }, /// Can be used with the DPB image of a video encode operation. video_encode_dpb = VIDEO_ENCODE_DPB_KHR { - extensions: [khr_video_encode_queue], + device_extensions: [khr_video_encode_queue], }, /* Misc image features */ @@ -904,7 +904,7 @@ vulkan_bitflags! { /// For multi-planar formats, can be used with images created with the `disjoint` flag. disjoint = DISJOINT { api_version: V1_1, - extensions: [khr_sampler_ycbcr_conversion], + device_extensions: [khr_sampler_ycbcr_conversion], }, /* Buffer usage */ @@ -924,7 +924,7 @@ vulkan_bitflags! { /// Can be used with the vertex buffer of an acceleration structure. acceleration_structure_vertex_buffer = ACCELERATION_STRUCTURE_VERTEX_BUFFER_KHR { - extensions: [khr_acceleration_structure], + device_extensions: [khr_acceleration_structure], }, } diff --git a/vulkano/src/image/aspect.rs b/vulkano/src/image/aspect.rs index ec5a035a5e..ff8aac55af 100644 --- a/vulkano/src/image/aspect.rs +++ b/vulkano/src/image/aspect.rs @@ -31,34 +31,34 @@ vulkan_enum! { // TODO: document Plane0 = PLANE_0 { api_version: V1_1, - extensions: [khr_sampler_ycbcr_conversion], + device_extensions: [khr_sampler_ycbcr_conversion], }, // TODO: document Plane1 = PLANE_1 { api_version: V1_1, - extensions: [khr_sampler_ycbcr_conversion], + device_extensions: [khr_sampler_ycbcr_conversion], }, // TODO: document Plane2 = PLANE_2 { api_version: V1_1, - extensions: [khr_sampler_ycbcr_conversion], + device_extensions: [khr_sampler_ycbcr_conversion], }, // TODO: document MemoryPlane0 = MEMORY_PLANE_0_EXT { - extensions: [ext_image_drm_format_modifier], + device_extensions: [ext_image_drm_format_modifier], }, // TODO: document MemoryPlane1 = MEMORY_PLANE_1_EXT { - extensions: [ext_image_drm_format_modifier], + device_extensions: [ext_image_drm_format_modifier], }, // TODO: document MemoryPlane2 = MEMORY_PLANE_2_EXT { - extensions: [ext_image_drm_format_modifier], + device_extensions: [ext_image_drm_format_modifier], }, } @@ -82,34 +82,34 @@ vulkan_bitflags! { // TODO: document plane0 = PLANE_0 { api_version: V1_1, - extensions: [khr_sampler_ycbcr_conversion], + device_extensions: [khr_sampler_ycbcr_conversion], }, // TODO: document plane1 = PLANE_1 { api_version: V1_1, - extensions: [khr_sampler_ycbcr_conversion], + device_extensions: [khr_sampler_ycbcr_conversion], }, // TODO: document plane2 = PLANE_2 { api_version: V1_1, - extensions: [khr_sampler_ycbcr_conversion], + device_extensions: [khr_sampler_ycbcr_conversion], }, // TODO: document memory_plane0 = MEMORY_PLANE_0_EXT { - extensions: [ext_image_drm_format_modifier], + device_extensions: [ext_image_drm_format_modifier], }, // TODO: document memory_plane1 = MEMORY_PLANE_1_EXT { - extensions: [ext_image_drm_format_modifier], + device_extensions: [ext_image_drm_format_modifier], }, // TODO: document memory_plane2 = MEMORY_PLANE_2_EXT { - extensions: [ext_image_drm_format_modifier], + device_extensions: [ext_image_drm_format_modifier], }, } diff --git a/vulkano/src/image/immutable.rs b/vulkano/src/image/immutable.rs index 99f8efd64d..a6553a2386 100644 --- a/vulkano/src/image/immutable.rs +++ b/vulkano/src/image/immutable.rs @@ -36,7 +36,7 @@ use crate::{ use smallvec::SmallVec; use std::{ error::Error, - fmt, + fmt::{Display, Error as FmtError, Formatter}, hash::{Hash, Hasher}, sync::Arc, }; @@ -485,9 +485,9 @@ impl Error for ImmutableImageCreationError { } } -impl fmt::Display for ImmutableImageCreationError { +impl Display for ImmutableImageCreationError { #[inline] - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match self { Self::ImageCreationError(err) => err.fmt(f), Self::DeviceMemoryAllocationError(err) => err.fmt(f), diff --git a/vulkano/src/image/layout.rs b/vulkano/src/image/layout.rs index 3bb555d112..bf2e774a12 100644 --- a/vulkano/src/image/layout.rs +++ b/vulkano/src/image/layout.rs @@ -77,49 +77,49 @@ vulkan_enum! { // TODO: document DepthReadOnlyStencilAttachmentOptimal = DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL { api_version: V1_1, - extensions: [khr_maintenance2], + device_extensions: [khr_maintenance2], }, // TODO: document DepthAttachmentStencilReadOnlyOptimal = DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL { api_version: V1_1, - extensions: [khr_maintenance2], + device_extensions: [khr_maintenance2], }, // TODO: document DepthAttachmentOptimal = DEPTH_ATTACHMENT_OPTIMAL { api_version: V1_2, - extensions: [khr_separate_depth_stencil_layouts], + device_extensions: [khr_separate_depth_stencil_layouts], }, // TODO: document DepthReadOnlyOptimal = DEPTH_READ_ONLY_OPTIMAL { api_version: V1_2, - extensions: [khr_separate_depth_stencil_layouts], + device_extensions: [khr_separate_depth_stencil_layouts], }, // TODO: document StencilAttachmentOptimal = STENCIL_ATTACHMENT_OPTIMAL { api_version: V1_2, - extensions: [khr_separate_depth_stencil_layouts], + device_extensions: [khr_separate_depth_stencil_layouts], }, // TODO: document StencilReadOnlyOptimal = STENCIL_READ_ONLY_OPTIMAL { api_version: V1_2, - extensions: [khr_separate_depth_stencil_layouts], + device_extensions: [khr_separate_depth_stencil_layouts], }, // TODO: document ReadOnlyOptimal = READ_ONLY_OPTIMAL { api_version: V1_3, - extensions: [khr_synchronization2], + device_extensions: [khr_synchronization2], }, // TODO: document AttachmentOptimal = ATTACHMENT_OPTIMAL { api_version: V1_3, - extensions: [khr_synchronization2], + device_extensions: [khr_synchronization2], }, */ @@ -127,53 +127,53 @@ vulkan_enum! { /// acquired from the swapchain, and must be transitioned back into this layout before /// presenting them. PresentSrc = PRESENT_SRC_KHR { - extensions: [khr_swapchain], + device_extensions: [khr_swapchain], }, /* // TODO: document VideoDecodeDst = VIDEO_DECODE_DST_KHR { - extensions: [khr_video_decode_queue], + device_extensions: [khr_video_decode_queue], }, // TODO: document VideoDecodeSrc = VIDEO_DECODE_SRC_KHR { - extensions: [khr_video_decode_queue], + device_extensions: [khr_video_decode_queue], }, // TODO: document VideoDecodeDpb = VIDEO_DECODE_DPB_KHR { - extensions: [khr_video_decode_queue], + device_extensions: [khr_video_decode_queue], }, // TODO: document SharedPresent = SHARED_PRESENT_KHR { - extensions: [khr_shared_presentable_image], + device_extensions: [khr_shared_presentable_image], }, // TODO: document FragmentDensityMapOptimal = FRAGMENT_DENSITY_MAP_OPTIMAL_EXT { - extensions: [ext_fragment_density_map], + device_extensions: [ext_fragment_density_map], }, // TODO: document FragmentShadingRateAttachmentOptimal = FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR { - extensions: [khr_fragment_shading_rate], + device_extensions: [khr_fragment_shading_rate], }, // TODO: document VideoEncodeDst = VIDEO_ENCODE_DST_KHR { - extensions: [khr_video_encode_queue], + device_extensions: [khr_video_encode_queue], }, // TODO: document VideoEncodeSrc = VIDEO_ENCODE_SRC_KHR { - extensions: [khr_video_encode_queue], + device_extensions: [khr_video_encode_queue], }, // TODO: document VideoEncodeDpb = VIDEO_ENCODE_DPB_KHR { - extensions: [khr_video_encode_queue], + device_extensions: [khr_video_encode_queue], }, */ } diff --git a/vulkano/src/image/mod.rs b/vulkano/src/image/mod.rs index 3c601e9b7c..a514d0752d 100644 --- a/vulkano/src/image/mod.rs +++ b/vulkano/src/image/mod.rs @@ -246,7 +246,7 @@ vulkan_bitflags! { /// For 3D images, allows creation of an image view of type `Dim2d` or `Dim2dArray`. array_2d_compatible = TYPE_2D_ARRAY_COMPATIBLE { api_version: V1_1, - extensions: [khr_maintenance1], + device_extensions: [khr_maintenance1], }, /// For images with a compressed format, allows creation of an image view with an uncompressed @@ -256,7 +256,7 @@ vulkan_bitflags! { /// Requires `mutable_format`. block_texel_view_compatible = BLOCK_TEXEL_VIEW_COMPATIBLE { api_version: V1_1, - extensions: [khr_maintenance1], + device_extensions: [khr_maintenance1], }, } @@ -289,7 +289,7 @@ vulkan_enum! { /* // TODO: document DrmFormatModifier = DRM_FORMAT_MODIFIER_EXT { - extensions: [ext_image_drm_format_modifier], + device_extensions: [ext_image_drm_format_modifier], }, */ } diff --git a/vulkano/src/image/sys.rs b/vulkano/src/image/sys.rs index 87c4814d48..2ba849369a 100644 --- a/vulkano/src/image/sys.rs +++ b/vulkano/src/image/sys.rs @@ -20,24 +20,23 @@ use super::{ }; use crate::{ buffer::cpu_access::{ReadLockError, WriteLockError}, - device::{Device, DeviceOwned}, + device::{physical::ImageFormatPropertiesError, Device, DeviceOwned}, format::{ChromaSampling, Format, FormatFeatures, NumericType}, image::{view::ImageViewCreationError, ImageFormatInfo, ImageFormatProperties, ImageType}, - macros::ExtensionNotEnabled, memory::{ DeviceMemory, DeviceMemoryAllocationError, ExternalMemoryHandleType, ExternalMemoryHandleTypes, MemoryRequirements, }, range_map::RangeMap, sync::{AccessError, CurrentAccess, Sharing}, - DeviceSize, OomError, Version, VulkanError, VulkanObject, + DeviceSize, OomError, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject, }; use ash::vk::Handle; use parking_lot::{Mutex, MutexGuard}; use smallvec::{smallvec, SmallVec}; use std::{ error::Error, - fmt, + fmt::{Display, Error as FmtError, Formatter}, hash::{Hash, Hasher}, iter::{FusedIterator, Peekable}, mem::MaybeUninit, @@ -204,22 +203,22 @@ impl UnsafeImage { let format = format.unwrap(); // Can be None for "external formats" but Vulkano doesn't support that yet // VUID-VkImageCreateInfo-format-parameter - // TODO: format.validate(device)?; + // TODO: format.validate_device(device)?; // VUID-VkImageCreateInfo-samples-parameter - samples.validate(device)?; + samples.validate_device(device)?; // VUID-VkImageCreateInfo-tiling-parameter - tiling.validate(device)?; + tiling.validate_device(device)?; // VUID-VkImageCreateInfo-usage-parameter - usage.validate(device)?; + usage.validate_device(device)?; // VUID-VkImageCreateInfo-usage-requiredbitmask assert!(!usage.is_empty()); // VUID-VkImageCreateInfo-initialLayout-parameter - initial_layout.validate(device)?; + initial_layout.validate_device(device)?; if usage.transient_attachment { // VUID-VkImageCreateInfo-usage-00966 @@ -345,9 +344,12 @@ impl UnsafeImage { // VUID-VkImageCreateInfo-format-06413 if array_layers > 1 && !device.enabled_features().ycbcr_image_arrays { - return Err(ImageCreationError::FeatureNotEnabled { - feature: "ycbcr_image_arrays", - reason: "format was an YCbCr format and array_layers was greater than 1", + return Err(ImageCreationError::RequirementNotMet { + required_for: "`create_info.format.ycbcr_chroma_sampling()` is `Some` and `create_info.dimensions.array_layers()` is greater than `1`", + requires_one_of: RequiresOneOf { + features: &["ycbcr_image_arrays"], + ..Default::default() + }, }); } @@ -422,9 +424,12 @@ impl UnsafeImage { if samples != SampleCount::Sample1 && !device.enabled_features().shader_storage_image_multisample { - return Err(ImageCreationError::FeatureNotEnabled { - feature: "shader_storage_image_multisample", - reason: "usage included `storage` and samples was not `Sample1`", + return Err(ImageCreationError::RequirementNotMet { + required_for: "`create_info.usage.storage` is set and `create_info.samples` is not `SampleCount::Sample1`", + requires_one_of: RequiresOneOf { + features: &["shader_storage_image_multisample"], + ..Default::default() + }, }); } } @@ -501,14 +506,18 @@ impl UnsafeImage { if !(device.api_version() >= Version::V1_1 || device.enabled_extensions().khr_external_memory) { - return Err(ImageCreationError::ExtensionNotEnabled { - extension: "khr_external_memory", - reason: "one or more fields of external_memory_handle_types were set", + return Err(ImageCreationError::RequirementNotMet { + required_for: "`create_info.external_memory_handle_types` is not empty", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_1), + device_extensions: &["khr_external_memory"], + ..Default::default() + }, }); } // VUID-VkExternalMemoryImageCreateInfo-handleTypes-parameter - external_memory_handle_types.validate(device)?; + external_memory_handle_types.validate_device(device)?; // VUID-VkImageCreateInfo-pNext-01443 if initial_layout != ImageLayout::Undefined { @@ -1533,13 +1542,9 @@ pub enum ImageCreationError { /// Allocating memory failed. AllocError(DeviceMemoryAllocationError), - ExtensionNotEnabled { - extension: &'static str, - reason: &'static str, - }, - FeatureNotEnabled { - feature: &'static str, - reason: &'static str, + RequirementNotMet { + required_for: &'static str, + requires_one_of: RequiresOneOf, }, /// The array_2d_compatible flag was enabled, but the image type was not 3D. @@ -1653,129 +1658,125 @@ impl Error for ImageCreationError { } } -impl fmt::Display for ImageCreationError { +impl Display for ImageCreationError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match *self { - Self::AllocError(_) => write!(fmt, "allocating memory failed"), - Self::ExtensionNotEnabled { extension, reason } => write!( - fmt, - "the extension {} must be enabled: {}", - extension, reason + Self::AllocError(_) => write!(f, "allocating memory failed"), + + Self::RequirementNotMet { + required_for, + requires_one_of, + } => write!( + f, + "a requirement was not met for: {}; requires one of: {}", + required_for, requires_one_of, ), - Self::FeatureNotEnabled { feature, reason } => { - write!(fmt, "the feature {} must be enabled: {}", feature, reason) - } + Self::Array2dCompatibleNot3d => { write!( - fmt, + f, "the array_2d_compatible flag was enabled, but the image type was not 3D" ) } Self::BlockTexelViewCompatibleNotCompressed => { - write!(fmt, "the block_texel_view_compatible flag was enabled, but the given format was not compressed") + write!(f, "the block_texel_view_compatible flag was enabled, but the given format was not compressed") } Self::CubeCompatibleNot2d => { write!( - fmt, + f, "the cube_compatible flag was enabled, but the image type was not 2D" ) } Self::CubeCompatibleNotEnoughArrayLayers => { - write!(fmt, "the cube_compatible flag was enabled, but the number of array layers was less than 6") + write!(f, "the cube_compatible flag was enabled, but the number of array layers was less than 6") } Self::CubeCompatibleNotSquare => { - write!(fmt, "the cube_compatible flag was enabled, but the image dimensions were not square") + write!(f, "the cube_compatible flag was enabled, but the image dimensions were not square") } Self::CubeCompatibleMultisampling => { write!( - fmt, + f, "the cube_compatible flag was enabled together with multisampling" ) } Self::ExternalMemoryInvalidInitialLayout => { - write!(fmt, "one or more external memory handle types were provided, but the initial layout was not `Undefined`") + write!(f, "one or more external memory handle types were provided, but the initial layout was not `Undefined`") } Self::FormatNotSupported => { - write!(fmt, "the given format was not supported by the device") + write!(f, "the given format was not supported by the device") } Self::FormatUsageNotSupported { .. } => { write!( - fmt, + f, "a requested usage flag was not supported by the given format" ) } Self::ImageFormatPropertiesNotSupported => { - write!(fmt, "the image configuration as queried through the `image_format_properties` function was not supported by the device") + write!(f, "the image configuration as queried through the `image_format_properties` function was not supported by the device") } Self::MaxArrayLayersExceeded { .. } => { - write!(fmt, "the number of array layers exceeds the maximum supported by the device for this image configuration") + write!(f, "the number of array layers exceeds the maximum supported by the device for this image configuration") } Self::MaxDimensionsExceeded { .. } => { - write!(fmt, "the specified dimensions exceed the maximum supported by the device for this image configuration") + write!(f, "the specified dimensions exceed the maximum supported by the device for this image configuration") } Self::MaxFramebufferDimensionsExceeded { .. } => { - write!(fmt, "the usage included one of the attachment types, and the specified width and height exceeded the `max_framebuffer_width` or `max_framebuffer_height` limits") + write!(f, "the usage included one of the attachment types, and the specified width and height exceeded the `max_framebuffer_width` or `max_framebuffer_height` limits") } Self::MaxMipLevelsExceeded { .. } => { write!( - fmt, + f, "the maximum number of mip levels for the given dimensions has been exceeded" ) } Self::MultisampleCubeCompatible => { write!( - fmt, + f, "multisampling was enabled, and the `cube_compatible` flag was set" ) } Self::MultisampleLinearTiling => { - write!(fmt, "multisampling was enabled, and tiling was `Linear`") + write!(f, "multisampling was enabled, and tiling was `Linear`") } Self::MultisampleMultipleMipLevels => { write!( - fmt, + f, "multisampling was enabled, and multiple mip levels were specified" ) } Self::MultisampleNot2d => { write!( - fmt, + f, "multisampling was enabled, but the image type was not 2D" ) } Self::SampleCountNotSupported { .. } => { write!( - fmt, + f, "the sample count is not supported by the device for this image configuration" ) } Self::SharingInvalidQueueFamilyId { .. } => { - write!(fmt, "the sharing mode was set to `Concurrent`, but one of the specified queue family ids was not valid") + write!(f, "the sharing mode was set to `Concurrent`, but one of the specified queue family ids was not valid") } Self::YcbcrFormatInvalidDimensions => { - write!(fmt, "a YCbCr format was given, but the specified width and/or height was not a multiple of 2 as required by the format's chroma subsampling") + write!(f, "a YCbCr format was given, but the specified width and/or height was not a multiple of 2 as required by the format's chroma subsampling") } Self::YcbcrFormatMultipleMipLevels => { write!( - fmt, + f, "a YCbCr format was given, and multiple mip levels were specified" ) } Self::YcbcrFormatMultisampling => { - write!( - fmt, - "a YCbCr format was given, and multisampling was enabled" - ) + write!(f, "a YCbCr format was given, and multisampling was enabled") } Self::YcbcrFormatNot2d => { - write!( - fmt, - "a YCbCr format was given, but the image type was not 2D" - ) + write!(f, "a YCbCr format was given, but the image type was not 2D") } Self::DirectImageViewCreationFailed(e) => { - write!(fmt, "Image view creation failed {}", e) + write!(f, "Image view creation failed {}", e) } } } @@ -1806,12 +1807,30 @@ impl From for ImageCreationError { } } -impl From for ImageCreationError { +impl From for ImageCreationError { #[inline] - fn from(err: ExtensionNotEnabled) -> Self { - Self::ExtensionNotEnabled { - extension: err.extension, - reason: err.reason, + fn from(err: RequirementNotMet) -> Self { + Self::RequirementNotMet { + required_for: err.required_for, + requires_one_of: err.requires_one_of, + } + } +} + +impl From for ImageCreationError { + #[inline] + fn from(err: ImageFormatPropertiesError) -> Self { + match err { + ImageFormatPropertiesError::OomError(err) => { + Self::AllocError(DeviceMemoryAllocationError::OomError(err)) + } + ImageFormatPropertiesError::RequirementNotMet { + required_for, + requires_one_of, + } => Self::RequirementNotMet { + required_for, + requires_one_of, + }, } } } @@ -2226,7 +2245,7 @@ mod tests { sys::SubresourceRangeIterator, ImageAspect, ImageAspects, ImageDimensions, ImageSubresourceRange, SampleCount, }, - DeviceSize, + DeviceSize, RequiresOneOf, }; use smallvec::SmallVec; @@ -2353,10 +2372,10 @@ mod tests { ); match res { - Err(ImageCreationError::FeatureNotEnabled { - feature: "shader_storage_image_multisample", + Err(ImageCreationError::RequirementNotMet { + requires_one_of: RequiresOneOf { features, .. }, .. - }) => (), + }) if features.contains(&"shader_storage_image_multisample") => (), Err(ImageCreationError::SampleCountNotSupported { .. }) => (), // unlikely but possible _ => panic!(), }; diff --git a/vulkano/src/image/traits.rs b/vulkano/src/image/traits.rs index 1970676685..b2b606f972 100644 --- a/vulkano/src/image/traits.rs +++ b/vulkano/src/image/traits.rs @@ -17,7 +17,7 @@ use crate::{ SafeDeref, }; use std::{ - fmt, + fmt::{Debug, Error as FmtError, Formatter}, hash::{Hash, Hasher}, sync::Arc, }; @@ -223,8 +223,8 @@ pub struct ImageInner<'a> { pub num_mipmap_levels: u32, } -impl fmt::Debug for dyn ImageAccess { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +impl Debug for dyn ImageAccess { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { f.debug_struct("dyn ImageAccess") .field("inner", &self.inner()) .finish() diff --git a/vulkano/src/image/usage.rs b/vulkano/src/image/usage.rs index 1e430e370d..64b025fdc0 100644 --- a/vulkano/src/image/usage.rs +++ b/vulkano/src/image/usage.rs @@ -51,47 +51,47 @@ vulkan_bitflags! { /* // TODO: document video_decode_dst = VIDEO_DECODE_DST_KHR { - extensions: [khr_video_decode_queue], + device_extensions: [khr_video_decode_queue], }, // TODO: document video_decode_src = VIDEO_DECODE_SRC_KHR { - extensions: [khr_video_decode_queue], + device_extensions: [khr_video_decode_queue], }, // TODO: document video_decode_dpb = VIDEO_DECODE_DPB_KHR { - extensions: [khr_video_decode_queue], + device_extensions: [khr_video_decode_queue], }, // TODO: document fragment_density_map = FRAGMENT_DENSITY_MAP_EXT { - extensions: [ext_fragment_density_map], + device_extensions: [ext_fragment_density_map], }, // TODO: document fragment_shading_rate_attachment = FRAGMENT_SHADING_RATE_ATTACHMENT_KHR { - extensions: [khr_fragment_shading_rate], + device_extensions: [khr_fragment_shading_rate], }, // TODO: document video_encode_dst = VIDEO_ENCODE_DST_KHR { - extensions: [khr_video_encode_queue], + device_extensions: [khr_video_encode_queue], }, // TODO: document video_encode_src = VIDEO_ENCODE_SRC_KHR { - extensions: [khr_video_encode_queue], + device_extensions: [khr_video_encode_queue], }, // TODO: document video_encode_dpb = VIDEO_ENCODE_DPB_KHR { - extensions: [khr_video_encode_queue], + device_extensions: [khr_video_encode_queue], }, // TODO: document invocation_mask = INVOCATION_MASK_HUAWEI { - extensions: [huawei_invocation_mask], + device_extensions: [huawei_invocation_mask], }, */ } diff --git a/vulkano/src/image/view.rs b/vulkano/src/image/view.rs index a79d6fea2e..035bb0c998 100644 --- a/vulkano/src/image/view.rs +++ b/vulkano/src/image/view.rs @@ -15,16 +15,16 @@ use super::{ImageAccess, ImageDimensions, ImageFormatInfo, ImageSubresourceRange, ImageUsage}; use crate::{ - device::{Device, DeviceOwned}, + device::{physical::ImageFormatPropertiesError, Device, DeviceOwned}, format::{ChromaSampling, Format, FormatFeatures}, image::{ImageAspects, ImageTiling, ImageType, SampleCount}, - macros::{vulkan_enum, ExtensionNotEnabled}, + macros::vulkan_enum, sampler::{ycbcr::SamplerYcbcrConversion, ComponentMapping}, - OomError, VulkanError, VulkanObject, + OomError, RequirementNotMet, RequiresOneOf, VulkanError, VulkanObject, }; use std::{ error::Error, - fmt, + fmt::{Debug, Display, Error as FmtError, Formatter}, hash::{Hash, Hasher}, mem::MaybeUninit, ptr, @@ -85,25 +85,33 @@ where let image_inner = image.inner().image; let image_type = image.dimensions().image_type(); - let (filter_cubic, filter_cubic_minmax) = if let Some(properties) = image_inner + let (filter_cubic, filter_cubic_minmax) = image .device() .physical_device() - .image_format_properties(ImageFormatInfo { - format: image_inner.format(), - image_type, - tiling: image_inner.tiling(), - usage: *image_inner.usage(), - image_view_type: Some(view_type), - mutable_format: image_inner.mutable_format(), - cube_compatible: image_inner.cube_compatible(), - array_2d_compatible: image_inner.array_2d_compatible(), - block_texel_view_compatible: image_inner.block_texel_view_compatible(), - ..Default::default() - })? { - (properties.filter_cubic, properties.filter_cubic_minmax) - } else { - (false, false) - }; + .supported_extensions() + .ext_filter_cubic + .then_some(()) + .and_then(|_| { + image_inner + .device() + .physical_device() + .image_format_properties(ImageFormatInfo { + format: image_inner.format(), + image_type, + tiling: image_inner.tiling(), + usage: *image_inner.usage(), + image_view_type: Some(view_type), + mutable_format: image_inner.mutable_format(), + cube_compatible: image_inner.cube_compatible(), + array_2d_compatible: image_inner.array_2d_compatible(), + block_texel_view_compatible: image_inner.block_texel_view_compatible(), + ..Default::default() + }) + .unwrap() + }) + .map_or((false, false), |properties| { + (properties.filter_cubic, properties.filter_cubic_minmax) + }); Ok(Arc::new(ImageView { handle, @@ -144,25 +152,25 @@ where assert!(layer_count != 0); // VUID-VkImageViewCreateInfo-viewType-parameter - view_type.validate(image.device())?; + view_type.validate_device(image.device())?; // VUID-VkImageViewCreateInfo-format-parameter - // TODO: format.validate(image.device())?; + // TODO: format.validate_device(image.device())?; // VUID-VkComponentMapping-r-parameter - component_mapping.r.validate(image.device())?; + component_mapping.r.validate_device(image.device())?; // VUID-VkComponentMapping-g-parameter - component_mapping.g.validate(image.device())?; + component_mapping.g.validate_device(image.device())?; // VUID-VkComponentMapping-b-parameter - component_mapping.b.validate(image.device())?; + component_mapping.b.validate_device(image.device())?; // VUID-VkComponentMapping-a-parameter - component_mapping.a.validate(image.device())?; + component_mapping.a.validate_device(image.device())?; // VUID-VkImageSubresourceRange-aspectMask-parameter - subresource_range.aspects.validate(image.device())?; + subresource_range.aspects.validate_device(image.device())?; { let ImageAspects { @@ -277,9 +285,12 @@ where if view_type == ImageViewType::CubeArray && !image_inner.device().enabled_features().image_cube_array { - return Err(ImageViewCreationError::FeatureNotEnabled { - feature: "image_cube_array", - reason: "the `CubeArray` view type was requested", + return Err(ImageViewCreationError::RequirementNotMet { + required_for: "`create_info.viewtype` is `ImageViewType::CubeArray`", + requires_one_of: RequiresOneOf { + features: &["image_cube_array"], + ..Default::default() + }, }); } @@ -730,13 +741,9 @@ pub enum ImageViewCreationError { /// Allocating memory failed. OomError(OomError), - ExtensionNotEnabled { - extension: &'static str, - reason: &'static str, - }, - FeatureNotEnabled { - feature: &'static str, - reason: &'static str, + RequirementNotMet { + required_for: &'static str, + requires_one_of: RequiresOneOf, }, /// A 2D image view was requested from a 3D image, but a range of multiple mip levels was @@ -833,22 +840,24 @@ impl Error for ImageViewCreationError { } } -impl fmt::Display for ImageViewCreationError { +impl Display for ImageViewCreationError { #[inline] - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match *self { Self::OomError(_) => write!( f, "allocating memory failed", ), - Self::ExtensionNotEnabled { extension, reason } => write!( + + Self::RequirementNotMet { + required_for, + requires_one_of, + } => write!( f, - "the extension {} must be enabled: {}", - extension, reason + "a requirement was not met for: {}; requires one of: {}", + required_for, requires_one_of, ), - Self::FeatureNotEnabled { feature, reason } => { - write!(f, "the feature {} must be enabled: {}", feature, reason) - } + Self::Array2dCompatibleMultipleMipLevels => write!( f, "a 2D image view was requested from a 3D image, but a range of multiple mip levels was specified", @@ -959,12 +968,28 @@ impl From for ImageViewCreationError { } } -impl From for ImageViewCreationError { +impl From for ImageViewCreationError { + #[inline] + fn from(err: RequirementNotMet) -> Self { + Self::RequirementNotMet { + required_for: err.required_for, + requires_one_of: err.requires_one_of, + } + } +} + +impl From for ImageViewCreationError { #[inline] - fn from(err: ExtensionNotEnabled) -> Self { - Self::ExtensionNotEnabled { - extension: err.extension, - reason: err.reason, + fn from(err: ImageFormatPropertiesError) -> Self { + match err { + ImageFormatPropertiesError::OomError(err) => Self::OomError(err), + ImageFormatPropertiesError::RequirementNotMet { + required_for, + requires_one_of, + } => Self::RequirementNotMet { + required_for, + requires_one_of, + }, } } } @@ -1027,7 +1052,7 @@ impl ImageViewType { /// Trait for types that represent the GPU can access an image view. pub unsafe trait ImageViewAbstract: - VulkanObject + DeviceOwned + fmt::Debug + Send + Sync + VulkanObject + DeviceOwned + Debug + Send + Sync { /// Returns the wrapped image that this image view was created from. fn image(&self) -> Arc; @@ -1094,7 +1119,7 @@ pub unsafe trait ImageViewAbstract: unsafe impl ImageViewAbstract for ImageView where - I: ImageAccess + fmt::Debug + 'static, + I: ImageAccess + Debug + 'static, { #[inline] fn image(&self) -> Arc { diff --git a/vulkano/src/instance/debug.rs b/vulkano/src/instance/debug.rs index 3fc84076c0..f63a827347 100644 --- a/vulkano/src/instance/debug.rs +++ b/vulkano/src/instance/debug.rs @@ -43,11 +43,11 @@ //! use super::Instance; -use crate::{macros::vulkan_bitflags, VulkanError, VulkanObject}; +use crate::{macros::vulkan_bitflags, RequirementNotMet, RequiresOneOf, VulkanError, VulkanObject}; use std::{ error::Error, ffi::{c_void, CStr}, - fmt, + fmt::{Debug, Display, Error as FmtError, Formatter}, mem::MaybeUninit, panic::{catch_unwind, AssertUnwindSafe, RefUnwindSafe}, ptr, @@ -102,20 +102,23 @@ impl DebugUtilsMessenger { } = create_info; if !instance.enabled_extensions().ext_debug_utils { - return Err(DebugUtilsMessengerCreationError::ExtensionNotEnabled { - extension: "ext_debug_utils", - reason: "tried to create a DebugUtilsMessenger", + return Err(DebugUtilsMessengerCreationError::RequirementNotMet { + required_for: "`DebugUtilsMessenger`", + requires_one_of: RequiresOneOf { + instance_extensions: &["ext_debug_utils"], + ..Default::default() + }, }); } // VUID-VkDebugUtilsMessengerCreateInfoEXT-messageSeverity-parameter - // TODO: message_severity.validate()?; + message_severity.validate_instance(instance)?; // VUID-VkDebugUtilsMessengerCreateInfoEXT-messageSeverity-requiredbitmask assert!(!message_severity.is_empty()); // VUID-VkDebugUtilsMessengerCreateInfoEXT-messageType-parameter - // TODO: message_type.validate()?; + message_type.validate_instance(instance)?; // VUID-VkDebugUtilsMessengerCreateInfoEXT-messageType-requiredbitmask assert!(!message_type.is_empty()); @@ -186,8 +189,8 @@ impl Drop for DebugUtilsMessenger { } } -impl fmt::Debug for DebugUtilsMessenger { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { +impl Debug for DebugUtilsMessenger { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { let Self { handle, instance, @@ -242,21 +245,26 @@ pub(super) unsafe extern "system" fn trampoline( /// Error that can happen when creating a `DebugUtilsMessenger`. #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum DebugUtilsMessengerCreationError { - ExtensionNotEnabled { - extension: &'static str, - reason: &'static str, + RequirementNotMet { + required_for: &'static str, + requires_one_of: RequiresOneOf, }, } impl Error for DebugUtilsMessengerCreationError {} -impl fmt::Display for DebugUtilsMessengerCreationError { +impl Display for DebugUtilsMessengerCreationError { #[inline] - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match self { - Self::ExtensionNotEnabled { extension, reason } => { - write!(f, "the extension {} must be enabled: {}", extension, reason) - } + Self::RequirementNotMet { + required_for, + requires_one_of, + } => write!( + f, + "a requirement was not met for: {}; requires one of: {}", + required_for, requires_one_of, + ), } } } @@ -268,6 +276,16 @@ impl From for DebugUtilsMessengerCreationError { } } +impl From for DebugUtilsMessengerCreationError { + #[inline] + fn from(err: RequirementNotMet) -> Self { + Self::RequirementNotMet { + required_for: err.required_for, + requires_one_of: err.requires_one_of, + } + } +} + /// Parameters to create a `DebugUtilsMessenger`. #[derive(Clone)] pub struct DebugUtilsMessengerCreateInfo { @@ -317,8 +335,8 @@ impl DebugUtilsMessengerCreateInfo { } } -impl fmt::Debug for DebugUtilsMessengerCreateInfo { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { +impl Debug for DebugUtilsMessengerCreateInfo { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { let Self { message_severity, message_type, diff --git a/vulkano/src/instance/extensions.rs b/vulkano/src/instance/extensions.rs index c6b24dec86..6be3a644c9 100644 --- a/vulkano/src/instance/extensions.rs +++ b/vulkano/src/instance/extensions.rs @@ -7,15 +7,7 @@ // notice may not be copied, modified, or distributed except // according to those terms. -pub use crate::{ - extensions::{ExtensionRestriction, ExtensionRestrictionError, OneOfRequirements}, - Version, -}; -use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Sub, SubAssign}; -use std::{ - ffi::{CStr, CString}, - fmt::Formatter, -}; +pub use crate::extensions::{ExtensionRestriction, ExtensionRestrictionError}; // Generated by build.rs include!(concat!(env!("OUT_DIR"), "/instance_extensions.rs")); diff --git a/vulkano/src/instance/mod.rs b/vulkano/src/instance/mod.rs index f2b9c196e7..11188c1f19 100644 --- a/vulkano/src/instance/mod.rs +++ b/vulkano/src/instance/mod.rs @@ -59,7 +59,7 @@ pub use self::{extensions::InstanceExtensions, layers::LayerProperties}; use crate::{ device::physical::{init_physical_devices, PhysicalDeviceInfo}, instance::debug::trampoline, - OomError, VulkanError, VulkanLibrary, VulkanObject, + OomError, RequiresOneOf, VulkanError, VulkanLibrary, VulkanObject, }; pub use crate::{ extensions::{ExtensionRestriction, ExtensionRestrictionError}, @@ -70,7 +70,7 @@ use smallvec::SmallVec; use std::{ error::Error, ffi::{c_void, CString}, - fmt, + fmt::{Debug, Display, Error as FmtError, Formatter}, hash::{Hash, Hasher}, mem::MaybeUninit, panic::{RefUnwindSafe, UnwindSafe}, @@ -386,15 +386,24 @@ impl Instance { // VUID-VkInstanceCreateInfo-pNext-04926 if !enabled_extensions.ext_debug_utils { - return Err(InstanceCreationError::ExtensionNotEnabled { - extension: "ext_debug_utils", - reason: "debug_utils_messengers was not empty", + return Err(InstanceCreationError::RequirementNotMet { + required_for: "`debug_utils_messengers` is not empty", + requires_one_of: RequiresOneOf { + instance_extensions: &["ext_debug_utils"], + ..Default::default() + }, }); } + // VUID-VkDebugUtilsMessengerCreateInfoEXT-messageSeverity-parameter + // TODO: message_severity.validate_instance()?; + // VUID-VkDebugUtilsMessengerCreateInfoEXT-messageSeverity-requiredbitmask assert!(!message_severity.is_empty()); + // VUID-VkDebugUtilsMessengerCreateInfoEXT-messageType-parameter + // TODO: message_type.validate_instance()?; + // VUID-VkDebugUtilsMessengerCreateInfoEXT-messageType-requiredbitmask assert!(!message_type.is_empty()); @@ -539,8 +548,8 @@ impl Hash for Instance { } } -impl fmt::Debug for Instance { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { +impl Debug for Instance { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { let Self { handle, fns, @@ -684,9 +693,9 @@ pub enum InstanceCreationError { /// A restriction for an extension was not met. ExtensionRestrictionNotMet(ExtensionRestrictionError), - ExtensionNotEnabled { - extension: &'static str, - reason: &'static str, + RequirementNotMet { + required_for: &'static str, + requires_one_of: RequiresOneOf, }, } @@ -700,20 +709,24 @@ impl Error for InstanceCreationError { } } -impl fmt::Display for InstanceCreationError { +impl Display for InstanceCreationError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - match *self { - Self::OomError(_) => write!(fmt, "not enough memory available"), - Self::InitializationFailed => write!(fmt, "initialization failed"), - Self::LayerNotPresent => write!(fmt, "layer not present"), - Self::ExtensionNotPresent => write!(fmt, "extension not present"), - Self::IncompatibleDriver => write!(fmt, "incompatible driver"), - Self::ExtensionRestrictionNotMet(err) => err.fmt(fmt), - Self::ExtensionNotEnabled { extension, reason } => write!( - fmt, - "the extension {} must be enabled: {}", - extension, reason + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { + match self { + Self::OomError(_) => write!(f, "not enough memory available"), + Self::InitializationFailed => write!(f, "initialization failed"), + Self::LayerNotPresent => write!(f, "layer not present"), + Self::ExtensionNotPresent => write!(f, "extension not present"), + Self::IncompatibleDriver => write!(f, "incompatible driver"), + Self::ExtensionRestrictionNotMet(err) => Display::fmt(err, f), + + Self::RequirementNotMet { + required_for, + requires_one_of, + } => write!( + f, + "a requirement was not met for: {}; requires one of: {}", + required_for, requires_one_of, ), } } diff --git a/vulkano/src/lib.rs b/vulkano/src/lib.rs index 5cfb0978f5..57a562226c 100644 --- a/vulkano/src/lib.rs +++ b/vulkano/src/lib.rs @@ -85,7 +85,12 @@ pub use ash::vk::Handle; pub use half; pub use library::{LoadingError, VulkanLibrary}; use parking_lot::MutexGuard; -use std::{error::Error, fmt, ops::Deref, sync::Arc}; +use std::{ + error::Error, + fmt::{Display, Error as FmtError, Formatter}, + ops::Deref, + sync::Arc, +}; pub use version::Version; #[macro_use] @@ -155,11 +160,11 @@ pub enum OomError { impl Error for OomError {} -impl fmt::Display for OomError { +impl Display for OomError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { write!( - fmt, + f, "{}", match *self { OomError::OutOfHostMemory => "no memory available on the host", @@ -185,8 +190,8 @@ include!(concat!(env!("OUT_DIR"), "/errors.rs")); impl Error for VulkanError {} -impl fmt::Display for VulkanError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +impl Display for VulkanError { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match self { VulkanError::OutOfHostMemory => write!( f, @@ -301,6 +306,112 @@ impl fmt::Display for VulkanError { } } +/// Used in errors to indicate a set of alternatives that needs to be available/enabled to allow +/// a given operation. +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +pub struct RequiresOneOf { + /// A minimum Vulkan API version that would allow the operation. + pub api_version: Option, + + /// Enabled features that would allow the operation. + pub features: &'static [&'static str], + + /// Available/enabled device extensions that would allow the operation. + pub device_extensions: &'static [&'static str], + + /// Available/enabled instance extensions that would allow the operation. + pub instance_extensions: &'static [&'static str], +} + +impl RequiresOneOf { + /// Returns whether there is more than one possible requirement. + #[inline] + pub fn len(&self) -> usize { + self.api_version.map_or(0, |_| 1) + + self.features.len() + + self.device_extensions.len() + + self.instance_extensions.len() + } +} + +impl Display for RequiresOneOf { + #[inline] + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { + let mut members_written = 0; + + if let Some(version) = self.api_version { + write!(f, "Vulkan API version {}.{}", version.major, version.minor)?; + members_written += 1; + } + + if let Some((last, rest)) = self.features.split_last() { + if members_written != 0 { + write!(f, ", ")?; + } + + members_written += 1; + + if rest.is_empty() { + write!(f, "feature {}", last)?; + } else { + write!(f, "features ")?; + + for feature in rest { + write!(f, "{}, ", feature)?; + } + + write!(f, "{}", last)?; + } + } + + if let Some((last, rest)) = self.device_extensions.split_last() { + if members_written != 0 { + write!(f, ", ")?; + } + + members_written += 1; + + if rest.is_empty() { + write!(f, "device extension {}", last)?; + } else { + write!(f, "device extensions ")?; + + for feature in rest { + write!(f, "{}, ", feature)?; + } + + write!(f, "{}", last)?; + } + } + + if let Some((last, rest)) = self.instance_extensions.split_last() { + if members_written != 0 { + write!(f, ", ")?; + } + + if rest.is_empty() { + write!(f, "instance extension {}", last)?; + } else { + write!(f, "instance extensions ")?; + + for feature in rest { + write!(f, "{}, ", feature)?; + } + + write!(f, "{}", last)?; + } + } + + Ok(()) + } +} + +#[derive(Clone, Copy, Debug)] +pub(crate) struct RequirementNotMet { + pub(crate) required_for: &'static str, + pub(crate) requires_one_of: RequiresOneOf, +} + /// A helper type for non-exhaustive structs. /// /// This type cannot be constructed outside Vulkano. Structures with a field of this type can only diff --git a/vulkano/src/library.rs b/vulkano/src/library.rs index 300a00944c..2b551204c0 100644 --- a/vulkano/src/library.rs +++ b/vulkano/src/library.rs @@ -25,7 +25,14 @@ use crate::{ }; use libloading::{Error as LibloadingError, Library}; use std::{ - error::Error, ffi::CStr, fmt, mem::transmute, os::raw::c_char, path::Path, ptr, sync::Arc, + error::Error, + ffi::CStr, + fmt::{Debug, Display, Error as FmtError, Formatter}, + mem::transmute, + os::raw::c_char, + path::Path, + ptr, + sync::Arc, }; /// A loaded library containing a valid Vulkan implementation. @@ -262,9 +269,9 @@ where } } -impl fmt::Debug for dyn Loader { +impl Debug for dyn Loader { #[inline] - fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, _f: &mut Formatter) -> Result<(), FmtError> { Ok(()) } } @@ -366,11 +373,11 @@ impl Error for LoadingError { } } -impl fmt::Display for LoadingError { +impl Display for LoadingError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { write!( - fmt, + f, "{}", match *self { Self::LibraryLoadFailure(_) => "failed to load the Vulkan shared library", diff --git a/vulkano/src/macros.rs b/vulkano/src/macros.rs index 73b39fc7c2..81605e4ff7 100644 --- a/vulkano/src/macros.rs +++ b/vulkano/src/macros.rs @@ -14,12 +14,7 @@ macro_rules! vulkan_bitflags { $( $(#[doc = $flag_doc:literal])* - $flag_name:ident = $flag_name_ffi:ident - $({ - $(api_version: $api_version:ident,)? - extensions: [$($extension:ident),+ $(,)?], - })? - , + $flag_name:ident = $flag_name_ffi:ident, )+ } => { $(#[doc = $ty_doc])* @@ -134,32 +129,6 @@ macro_rules! vulkan_bitflags { )+ } } - - #[allow(dead_code)] - pub(crate) fn validate( - self, - #[allow(unused_variables)] device: &crate::device::Device - ) -> Result<(), crate::macros::ExtensionNotEnabled> { - $( - $( - if self.$flag_name && !( - $( - device.api_version() >= crate::Version::$api_version || - )? - $( - device.enabled_extensions().$extension - )||+ - ) { - return Err(crate::macros::ExtensionNotEnabled { - extension: stringify!($($extension)?), - reason: concat!(stringify!($ty), "::", stringify!($flag_name), " was used"), - }); - } - )? - )+ - - Ok(()) - } } impl From<$ty> for ash::vk::$ty_ffi { @@ -279,7 +248,8 @@ macro_rules! vulkan_bitflags { $flag_name:ident = $flag_name_ffi:ident $({ $(api_version: $api_version:ident,)? - extensions: [$($extension:ident),+ $(,)?], + $(device_extensions: [$($device_extension:ident),+ $(,)?],)? + $(instance_extensions: [$($instance_extension:ident),+ $(,)?],)? })? , )+ @@ -384,23 +354,95 @@ macro_rules! vulkan_bitflags { } #[allow(dead_code)] - pub(crate) fn validate( + pub(crate) fn validate_device( self, - #[allow(unused_variables)] device: &crate::device::Device - ) -> Result<(), crate::macros::ExtensionNotEnabled> { + #[allow(unused_variables)] device: &crate::device::Device, + ) -> Result<(), crate::RequirementNotMet> { $( $( - if self.$flag_name && !( + if self.$flag_name && ![ $( - device.api_version() >= crate::Version::$api_version || + device.api_version() >= crate::Version::$api_version, )? + $($( + device.enabled_extensions().$device_extension, + )+)? + $($( + device.instance().enabled_extensions().$instance_extension, + )+)? + ].into_iter().any(|x| x) { + return Err(crate::RequirementNotMet { + required_for: concat!("`", stringify!($ty), "::", stringify!($flag_name), "`"), + requires_one_of: crate::RequiresOneOf { + $(api_version: Some(crate::Version::$api_version),)? + $(device_extensions: &[$(stringify!($device_extension)),+],)? + $(instance_extensions: &[$(stringify!($instance_extension)),+],)? + ..Default::default() + }, + }); + } + )? + )+ + + Ok(()) + } + + #[allow(dead_code)] + pub(crate) fn validate_physical_device( + self, + #[allow(unused_variables)] physical_device: &crate::device::physical::PhysicalDevice, + ) -> Result<(), crate::RequirementNotMet> { + $( + $( + if self.$flag_name && ![ $( - device.enabled_extensions().$extension - )||+ - ) { - return Err(crate::macros::ExtensionNotEnabled { - extension: stringify!($($extension)?), - reason: concat!(stringify!($ty), "::", stringify!($flag_name), " was used"), + physical_device.api_version() >= crate::Version::$api_version, + )? + $($( + physical_device.supported_extensions().$device_extension, + )+)? + $($( + physical_device.instance().enabled_extensions().$instance_extension, + )+)? + ].into_iter().any(|x| x) { + return Err(crate::RequirementNotMet { + required_for: concat!("`", stringify!($ty), "::", stringify!($flag_name), "`"), + requires_one_of: crate::RequiresOneOf { + $(api_version: Some(crate::Version::$api_version),)? + $(device_extensions: &[$(stringify!($device_extension)),+],)? + $(instance_extensions: &[$(stringify!($instance_extension)),+],)? + ..Default::default() + }, + }); + } + )? + )+ + + Ok(()) + } + + #[allow(dead_code)] + pub(crate) fn validate_instance( + self, + #[allow(unused_variables)] instance: &crate::instance::Instance, + ) -> Result<(), crate::RequirementNotMet> { + $( + $( + if self.$flag_name && ![ + $( + instance.api_version() >= crate::Version::$api_version, + )? + $($( + instance.enabled_extensions().$instance_extension, + )+)? + ].into_iter().any(|x| x) { + return Err(crate::RequirementNotMet { + required_for: concat!("`", stringify!($ty), "::", stringify!($flag_name), "`"), + requires_one_of: crate::RequiresOneOf { + $(api_version: Some(crate::Version::$api_version),)? + $(instance_extensions: &[$(stringify!($instance_extension)),+],)? + ..Default::default() + }, }); } )? @@ -518,12 +560,7 @@ macro_rules! vulkan_enum { $( $(#[doc = $flag_doc:literal])* - $flag_name:ident = $flag_name_ffi:ident - $({ - $(api_version: $api_version:ident,)? - extensions: [$($extension:ident),+ $(,)?], - })? - , + $flag_name:ident = $flag_name_ffi:ident, )+ } => { $(#[doc = $ty_doc])* @@ -568,7 +605,8 @@ macro_rules! vulkan_enum { $flag_name:ident = $flag_name_ffi:ident $({ $(api_version: $api_version:ident,)? - extensions: [$($extension:ident),+ $(,)?], + $(device_extensions: [$($device_extension:ident),+ $(,)?],)? + $(instance_extensions: [$($instance_extension:ident),+ $(,)?],)? })? , )+ @@ -586,25 +624,107 @@ macro_rules! vulkan_enum { impl $ty { #[allow(dead_code)] - pub(crate) fn validate( + pub(crate) fn validate_device( self, - #[allow(unused_variables)] device: &crate::device::Device - ) -> Result<(), crate::macros::ExtensionNotEnabled> { + #[allow(unused_variables)] device: &crate::device::Device, + ) -> Result<(), crate::RequirementNotMet> { match self { $( $( Self::$flag_name => { - if !( + if ![ $( - device.api_version() >= crate::Version::$api_version || + device.api_version() >= crate::Version::$api_version, )? + $($( + device.enabled_extensions().$device_extension, + )+)? + $($( + device.instance().enabled_extensions().$instance_extension, + )+)? + ].into_iter().any(|x| x) { + return Err(crate::RequirementNotMet { + required_for: concat!("`", stringify!($ty), "::", stringify!($flag_name), "`"), + requires_one_of: crate::RequiresOneOf { + $(api_version: Some(crate::Version::$api_version),)? + $(device_extensions: &[$(stringify!($device_extension)),+],)? + $(instance_extensions: &[$(stringify!($instance_extension)),+],)? + ..Default::default() + }, + }); + } + }, + )? + )+ + _ => (), + } + + Ok(()) + } + + #[allow(dead_code)] + pub(crate) fn validate_physical_device( + self, + #[allow(unused_variables)] physical_device: &crate::device::physical::PhysicalDevice, + ) -> Result<(), crate::RequirementNotMet> { + match self { + $( + $( + Self::$flag_name => { + if ![ $( - device.enabled_extensions().$extension - )||+ - ) { - return Err(crate::macros::ExtensionNotEnabled { - extension: stringify!($($extension)?), - reason: concat!(stringify!($ty), "::", stringify!($flag_name), " was used"), + physical_device.api_version() >= crate::Version::$api_version, + )? + $($( + physical_device.supported_extensions().$device_extension, + )+)? + $($( + physical_device.instance().enabled_extensions().$instance_extension, + )+)? + ].into_iter().any(|x| x) { + return Err(crate::RequirementNotMet { + required_for: concat!("`", stringify!($ty), "::", stringify!($flag_name), "`"), + requires_one_of: crate::RequiresOneOf { + $(api_version: Some(crate::Version::$api_version),)? + $(device_extensions: &[$(stringify!($device_extension)),+],)? + $(instance_extensions: &[$(stringify!($instance_extension)),+],)? + ..Default::default() + }, + }); + } + }, + )? + )+ + _ => (), + } + + Ok(()) + } + + #[allow(dead_code)] + pub(crate) fn validate_instance( + self, + #[allow(unused_variables)] instance: &crate::instance::Instance, + ) -> Result<(), crate::RequirementNotMet> { + match self { + $( + $( + Self::$flag_name => { + if ![ + $( + instance.api_version() >= crate::Version::$api_version, + )? + $($( + instance.enabled_extensions().$instance_extension, + )+)? + ].into_iter().any(|x| x) { + return Err(crate::RequirementNotMet { + required_for: concat!("`", stringify!($ty), "::", stringify!($flag_name), "`"), + requires_one_of: crate::RequiresOneOf { + $(api_version: Some(crate::Version::$api_version),)? + $(instance_extensions: &[$(stringify!($instance_extension)),+],)? + ..Default::default() + }, }); } }, @@ -641,9 +761,3 @@ macro_rules! vulkan_enum { } pub(crate) use {vulkan_bitflags, vulkan_enum}; - -#[derive(Clone, Copy, Debug)] -pub(crate) struct ExtensionNotEnabled { - pub(crate) extension: &'static str, - pub(crate) reason: &'static str, -} diff --git a/vulkano/src/memory/device_memory.rs b/vulkano/src/memory/device_memory.rs index aefcf2cc5f..56e4ea280c 100644 --- a/vulkano/src/memory/device_memory.rs +++ b/vulkano/src/memory/device_memory.rs @@ -10,13 +10,13 @@ use super::DedicatedAllocation; use crate::{ device::{physical::MemoryType, Device, DeviceOwned}, - macros::{vulkan_bitflags, vulkan_enum, ExtensionNotEnabled}, - DeviceSize, OomError, Version, VulkanError, VulkanObject, + macros::{vulkan_bitflags, vulkan_enum}, + DeviceSize, OomError, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject, }; use std::{ error::Error, ffi::c_void, - fmt, + fmt::{Display, Error as FmtError, Formatter}, fs::File, hash::{Hash, Hasher}, mem::MaybeUninit, @@ -161,9 +161,12 @@ impl DeviceMemory { // VUID-VkMemoryAllocateInfo-memoryTypeIndex-01872 if memory_type.is_protected() && !device.enabled_features().protected_memory { - return Err(DeviceMemoryAllocationError::FeatureNotEnabled { - feature: "protected_memory", - reason: "selected memory type is protected", + return Err(DeviceMemoryAllocationError::RequirementNotMet { + required_for: "`allocate_info.memory_type_index` refers to a memory type where `flags.protected` is set", + requires_one_of: RequiresOneOf { + features: &["protected_memory"], + ..Default::default() + }, }); } @@ -220,14 +223,18 @@ impl DeviceMemory { if !(device.api_version() >= Version::V1_1 || device.enabled_extensions().khr_external_memory) { - return Err(DeviceMemoryAllocationError::ExtensionNotEnabled { - extension: "khr_external_memory_fd", - reason: "`import_info` was `MemoryImportInfo::Fd`", + return Err(DeviceMemoryAllocationError::RequirementNotMet { + required_for: "`allocate_info.export_handle_types` is not empty", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_1), + device_extensions: &["khr_external_memory"], + ..Default::default() + }, }); } // VUID-VkExportMemoryAllocateInfo-handleTypes-parameter - export_handle_types.validate(device)?; + export_handle_types.validate_device(device)?; // VUID-VkMemoryAllocateInfo-pNext-00639 // VUID-VkExportMemoryAllocateInfo-handleTypes-00656 @@ -246,9 +253,13 @@ impl DeviceMemory { file: _, } => { if !device.enabled_extensions().khr_external_memory_fd { - return Err(DeviceMemoryAllocationError::ExtensionNotEnabled { - extension: "khr_external_memory_fd", - reason: "`import_info` was `MemoryImportInfo::Fd`", + return Err(DeviceMemoryAllocationError::RequirementNotMet { + required_for: + "`allocate_info.import_info` is `Some(MemoryImportInfo::Fd)`", + requires_one_of: RequiresOneOf { + device_extensions: &["khr_external_memory_fd"], + ..Default::default() + }, }); } @@ -260,7 +271,7 @@ impl DeviceMemory { #[cfg(unix)] { // VUID-VkImportMemoryFdInfoKHR-handleType-parameter - handle_type.validate(device)?; + handle_type.validate_device(device)?; // VUID-VkImportMemoryFdInfoKHR-handleType-00669 match handle_type { @@ -274,14 +285,7 @@ impl DeviceMemory { // VUID-VkMemoryDedicatedAllocateInfo-image-01878 // Can't validate, must be ensured by user } - ExternalMemoryHandleType::DmaBuf => { - if !device.enabled_extensions().ext_external_memory_dma_buf { - return Err(DeviceMemoryAllocationError::ExtensionNotEnabled { - extension: "ext_external_memory_dma_buf", - reason: "`import_info` was `MemoryImportInfo::Fd` and `handle_type` was `ExternalMemoryHandleType::DmaBuf`" - }); - } - } + ExternalMemoryHandleType::DmaBuf => {} _ => { return Err( DeviceMemoryAllocationError::ImportFdHandleTypeNotSupported { @@ -303,9 +307,13 @@ impl DeviceMemory { handle: _, } => { if !device.enabled_extensions().khr_external_memory_win32 { - return Err(DeviceMemoryAllocationError::ExtensionNotEnabled { - extension: "khr_external_memory_win32", - reason: "`import_info` was `MemoryImportInfo::Win32`", + return Err(DeviceMemoryAllocationError::RequirementNotMet { + required_for: + "`allocate_info.import_info` is `Some(MemoryImportInfo::Win32)`", + requires_one_of: RequiresOneOf { + device_extensions: &["khr_external_memory_win32"], + ..Default::default() + }, }); } @@ -317,7 +325,7 @@ impl DeviceMemory { #[cfg(windows)] { // VUID-VkImportMemoryWin32HandleInfoKHR-handleType-parameter - handle_type.validate(device)?; + handle_type.validate_device(device)?; // VUID-VkImportMemoryWin32HandleInfoKHR-handleType-00660 match handle_type { @@ -491,7 +499,7 @@ impl DeviceMemory { handle_type: ExternalMemoryHandleType, ) -> Result { // VUID-VkMemoryGetFdInfoKHR-handleType-parameter - handle_type.validate(&self.device)?; + handle_type.validate_device(&self.device)?; // VUID-VkMemoryGetFdInfoKHR-handleType-00672 if !matches!( @@ -599,13 +607,9 @@ pub enum DeviceMemoryAllocationError { /// An error occurred when mapping the memory. MemoryMapError(MemoryMapError), - ExtensionNotEnabled { - extension: &'static str, - reason: &'static str, - }, - FeatureNotEnabled { - feature: &'static str, - reason: &'static str, + RequirementNotMet { + required_for: &'static str, + requires_one_of: RequiresOneOf, }, /// `dedicated_allocation` was `Some`, but the provided `allocation_size` was different from @@ -658,54 +662,56 @@ impl Error for DeviceMemoryAllocationError { } } -impl fmt::Display for DeviceMemoryAllocationError { +impl Display for DeviceMemoryAllocationError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match *self { - Self::OomError(_) => write!(fmt, "not enough memory available"), + Self::OomError(_) => write!(f, "not enough memory available"), Self::TooManyObjects => { - write!(fmt, "the maximum number of allocations has been exceeded") + write!(f, "the maximum number of allocations has been exceeded") } - Self::MemoryMapError(_) => write!(fmt, "error occurred when mapping the memory"), - Self::ExtensionNotEnabled { extension, reason } => write!( - fmt, - "the extension {} must be enabled: {}", - extension, reason + Self::MemoryMapError(_) => write!(f, "error occurred when mapping the memory"), + + Self::RequirementNotMet { + required_for, + requires_one_of, + } => write!( + f, + "a requirement was not met for: {}; requires one of: {}", + required_for, requires_one_of, ), - Self::FeatureNotEnabled { feature, reason } => { - write!(fmt, "the feature {} must be enabled: {}", feature, reason) - } + Self::DedicatedAllocationSizeMismatch { allocation_size, required_size } => write!( - fmt, + f, "`dedicated_allocation` was `Some`, but the provided `allocation_size` ({}) was different from the required size of the buffer or image ({})", allocation_size, required_size, ), Self::ImportFdHandleTypeNotSupported { handle_type } => write!( - fmt, + f, "the provided `MemoryImportInfo::Fd::handle_type` ({:?}) is not supported for file descriptors", handle_type, ), Self::ImportWin32HandleTypeNotSupported { handle_type } => write!( - fmt, + f, "the provided `MemoryImportInfo::Win32::handle_type` ({:?}) is not supported", handle_type, ), Self::MemoryTypeHeapSizeExceeded { allocation_size, heap_size } => write!( - fmt, + f, "the provided `allocation_size` ({}) was greater than the memory type's heap size ({})", allocation_size, heap_size, ), Self::MemoryTypeIndexOutOfRange { memory_type_index, memory_type_count } => write!( - fmt, + f, "the provided `memory_type_index` ({}) was not less than the number of memory types in the physical device ({})", memory_type_index, memory_type_count, ), Self::SpecViolation(u) => { - write!(fmt, "valid usage ID check {} failed", u) + write!(f, "valid usage ID check {} failed", u) } Self::ImplicitSpecViolation(e) => { - write!(fmt, "Implicit spec violation failed {}", e) + write!(f, "Implicit spec violation failed {}", e) } } } @@ -738,12 +744,12 @@ impl From for DeviceMemoryAllocationError { } } -impl From for DeviceMemoryAllocationError { +impl From for DeviceMemoryAllocationError { #[inline] - fn from(err: ExtensionNotEnabled) -> Self { - Self::ExtensionNotEnabled { - extension: err.extension, - reason: err.reason, + fn from(err: RequirementNotMet) -> Self { + Self::RequirementNotMet { + required_for: err.required_for, + requires_one_of: err.requires_one_of, } } } @@ -886,32 +892,32 @@ vulkan_enum! { // TODO: document DmaBuf = DMA_BUF_EXT { - extensions: [ext_external_memory_dma_buf], + device_extensions: [ext_external_memory_dma_buf], }, // TODO: document AndroidHardwareBuffer = ANDROID_HARDWARE_BUFFER_ANDROID { - extensions: [android_external_memory_android_hardware_buffer], + device_extensions: [android_external_memory_android_hardware_buffer], }, // TODO: document HostAllocation = HOST_ALLOCATION_EXT { - extensions: [ext_external_memory_host], + device_extensions: [ext_external_memory_host], }, // TODO: document HostMappedForeignMemory = HOST_MAPPED_FOREIGN_MEMORY_EXT { - extensions: [ext_external_memory_host], + device_extensions: [ext_external_memory_host], }, // TODO: document ZirconVmo = ZIRCON_VMO_FUCHSIA { - extensions: [fuchsia_external_memory], + device_extensions: [fuchsia_external_memory], }, // TODO: document RdmaAddress = RDMA_ADDRESS_NV { - extensions: [nv_external_memory_rdma], + device_extensions: [nv_external_memory_rdma], }, } @@ -943,32 +949,32 @@ vulkan_bitflags! { // TODO: document dma_buf = DMA_BUF_EXT { - extensions: [ext_external_memory_dma_buf], + device_extensions: [ext_external_memory_dma_buf], }, // TODO: document android_hardware_buffer = ANDROID_HARDWARE_BUFFER_ANDROID { - extensions: [android_external_memory_android_hardware_buffer], + device_extensions: [android_external_memory_android_hardware_buffer], }, // TODO: document host_allocation = HOST_ALLOCATION_EXT { - extensions: [ext_external_memory_host], + device_extensions: [ext_external_memory_host], }, // TODO: document host_mapped_foreign_memory = HOST_MAPPED_FOREIGN_MEMORY_EXT { - extensions: [ext_external_memory_host], + device_extensions: [ext_external_memory_host], }, // TODO: document zircon_vmo = ZIRCON_VMO_FUCHSIA { - extensions: [fuchsia_external_memory], + device_extensions: [fuchsia_external_memory], }, // TODO: document rdma_address = RDMA_ADDRESS_NV { - extensions: [nv_external_memory_rdma], + device_extensions: [nv_external_memory_rdma], }, } @@ -1020,14 +1026,14 @@ pub enum DeviceMemoryExportError { /// Not enough memory available. OomError(OomError), - ExtensionNotEnabled { - extension: &'static str, - reason: &'static str, - }, - /// The maximum number of allocations has been exceeded. TooManyObjects, + RequirementNotMet { + required_for: &'static str, + requires_one_of: RequiresOneOf, + }, + /// The requested export handle type is not supported for this operation, or was not provided in /// `export_handle_types` when allocating the memory. HandleTypeNotSupported { @@ -1045,23 +1051,28 @@ impl Error for DeviceMemoryExportError { } } -impl fmt::Display for DeviceMemoryExportError { +impl Display for DeviceMemoryExportError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match *self { - Self::OomError(_) => write!(fmt, "not enough memory available"), - Self::ExtensionNotEnabled { extension, reason } => write!( - fmt, - "the extension {} must be enabled: {}", - extension, reason - ), + Self::OomError(_) => write!(f, "not enough memory available"), Self::TooManyObjects => { - write!(fmt, "the maximum number of allocations has been exceeded") + write!(f, "the maximum number of allocations has been exceeded") } + + Self::RequirementNotMet { + required_for, + requires_one_of, + } => write!( + f, + "a requirement was not met for: {}; requires one of: {}", + required_for, requires_one_of, + ), + Self::HandleTypeNotSupported { handle_type, } => write!( - fmt, + f, "the requested export handle type ({:?}) is not supported for this operation, or was not provided in `export_handle_types` when allocating the memory", handle_type, ), @@ -1089,12 +1100,12 @@ impl From for DeviceMemoryExportError { } } -impl From for DeviceMemoryExportError { +impl From for DeviceMemoryExportError { #[inline] - fn from(err: ExtensionNotEnabled) -> Self { - Self::ExtensionNotEnabled { - extension: err.extension, - reason: err.reason, + fn from(err: RequirementNotMet) -> Self { + Self::RequirementNotMet { + required_for: err.required_for, + requires_one_of: err.requires_one_of, } } } @@ -1478,23 +1489,23 @@ impl Error for MemoryMapError { } } -impl fmt::Display for MemoryMapError { +impl Display for MemoryMapError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match *self { - Self::OomError(_) => write!(fmt, "not enough memory available"), - Self::MemoryMapFailed => write!(fmt, "memory map failed"), + Self::OomError(_) => write!(f, "not enough memory available"), + Self::MemoryMapFailed => write!(f, "memory map failed"), Self::NotHostVisible => write!( - fmt, + f, "tried to map memory whose type is not host-visible", ), Self::OutOfRange { ref provided_range, ref allowed_range } => write!( - fmt, + f, "the specified `range` ({:?}) was not contained within the allocated or mapped memory range ({:?})", provided_range, allowed_range, ), Self::RangeNotAlignedToAtomSize { ref range, atom_size } => write!( - fmt, + f, "the memory is not host-coherent, and the specified `range` bounds ({:?}) are not a multiple of the `non_coherent_atom_size` device property ({})", range, atom_size, ) diff --git a/vulkano/src/pipeline/compute.rs b/vulkano/src/pipeline/compute.rs index 0de189c4b8..b7a5f59e4e 100644 --- a/vulkano/src/pipeline/compute.rs +++ b/vulkano/src/pipeline/compute.rs @@ -36,7 +36,15 @@ use crate::{ shader::{DescriptorRequirements, EntryPoint, SpecializationConstants}, DeviceSize, OomError, VulkanError, VulkanObject, }; -use std::{collections::HashMap, error::Error, fmt, mem, mem::MaybeUninit, ptr, sync::Arc}; +use std::{ + collections::HashMap, + error::Error, + fmt::{Debug, Display, Error as FmtError, Formatter}, + mem, + mem::MaybeUninit, + ptr, + sync::Arc, +}; /// A pipeline object that describes to the Vulkan implementation how it should perform compute /// operations. @@ -264,10 +272,10 @@ impl Pipeline for ComputePipeline { } } -impl fmt::Debug for ComputePipeline { +impl Debug for ComputePipeline { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!(fmt, "", self.handle) + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { + write!(f, "", self.handle) } } @@ -334,11 +342,11 @@ impl Error for ComputePipelineCreationError { } } -impl fmt::Display for ComputePipelineCreationError { +impl Display for ComputePipelineCreationError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { write!( - fmt, + f, "{}", match *self { ComputePipelineCreationError::OomError(_) => "not enough memory available", diff --git a/vulkano/src/pipeline/graphics/builder.rs b/vulkano/src/pipeline/graphics/builder.rs index f351f29901..5a123726d4 100644 --- a/vulkano/src/pipeline/graphics/builder.rs +++ b/vulkano/src/pipeline/graphics/builder.rs @@ -24,7 +24,10 @@ use super::{ }, render_pass::{PipelineRenderPassType, PipelineRenderingCreateInfo}, tessellation::TessellationState, - vertex_input::{BuffersDefinition, Vertex, VertexDefinition, VertexInputState}, + vertex_input::{ + BuffersDefinition, Vertex, VertexDefinition, VertexInputBindingDescription, + VertexInputState, + }, viewport::{Scissor, Viewport, ViewportState}, GraphicsPipeline, GraphicsPipelineCreationError, }; @@ -46,7 +49,7 @@ use crate::{ DescriptorRequirements, EntryPoint, ShaderExecution, ShaderStage, SpecializationConstants, SpecializationMapEntry, }, - DeviceSize, Version, VulkanError, VulkanObject, + DeviceSize, RequiresOneOf, Version, VulkanError, VulkanObject, }; use smallvec::SmallVec; use std::{ @@ -466,17 +469,23 @@ where // VUID-VkGraphicsPipelineCreateInfo-dynamicRendering-06576 if !device.enabled_features().dynamic_rendering { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "dynamic_rendering", - reason: "render_pass was BeginRendering", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`render_pass` is `PipelineRenderPassType::BeginRendering`", + requires_one_of: RequiresOneOf { + features: &["dynamic_rendering"], + ..Default::default() + }, }); } // VUID-VkGraphicsPipelineCreateInfo-multiview-06577 if view_mask != 0 && !device.enabled_features().multiview { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "multiview", - reason: "PipelineRenderingCreateInfo::view_mask was not 0", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`render_pass` is `PipelineRenderPassType::BeginRendering` where `view_mask` is not `0`", + requires_one_of: RequiresOneOf { + features: &["multiview"], + ..Default::default() + }, }); } @@ -595,6 +604,8 @@ where // Ensured by HashMap. for (&binding, binding_desc) in bindings { + let &VertexInputBindingDescription { stride, input_rate } = binding_desc; + // VUID-VkVertexInputBindingDescription-binding-00618 if binding >= properties.max_vertex_input_bindings { return Err( @@ -606,26 +617,29 @@ where } // VUID-VkVertexInputBindingDescription-stride-00619 - if binding_desc.stride > properties.max_vertex_input_binding_stride { + if stride > properties.max_vertex_input_binding_stride { return Err( GraphicsPipelineCreationError::MaxVertexInputBindingStrideExceeded { binding, max: properties.max_vertex_input_binding_stride, - obtained: binding_desc.stride, + obtained: stride, }, ); } - match binding_desc.input_rate { + match input_rate { VertexInputRate::Instance { divisor } if divisor != 1 => { // VUID-VkVertexInputBindingDivisorDescriptionEXT-vertexAttributeInstanceRateDivisor-02229 if !device .enabled_features() .vertex_attribute_instance_rate_divisor { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "vertex_attribute_instance_rate_divisor", - reason: "VertexInputRate::Instance::divisor was not 1", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`vertex_input_state.bindings` has an element where `input_rate` is `VertexInputRate::Instance`, where `divisor` is not `1`", + requires_one_of: RequiresOneOf { + features: &["vertex_attribute_instance_rate_divisor"], + ..Default::default() + }, }); } @@ -635,9 +649,12 @@ where .enabled_features() .vertex_attribute_instance_rate_zero_divisor { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "vertex_attribute_instance_rate_zero_divisor", - reason: "VertexInputRate::Instance::divisor was 0", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`vertex_input_state.bindings` has an element where `input_rate` is `VertexInputRate::Instance`, where `divisor` is `0`", + requires_one_of: RequiresOneOf { + features: &["vertex_attribute_instance_rate_zero_divisor"], + ..Default::default() + }, }); } @@ -721,7 +738,7 @@ where match topology { PartialStateMode::Fixed(topology) => { // VUID-VkPipelineInputAssemblyStateCreateInfo-topology-parameter - topology.validate(device)?; + topology.validate_device(device)?; match topology { PrimitiveTopology::LineListWithAdjacency @@ -730,18 +747,24 @@ where | PrimitiveTopology::TriangleStripWithAdjacency => { // VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00429 if !device.enabled_features().geometry_shader { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "geometry_shader", - reason: "InputAssemblyState::topology was set to a WithAdjacency PrimitiveTopology", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`input_assembly_state.topology` is `StateMode::Fixed(PrimitiveTopology::*WithAdjacency)`", + requires_one_of: RequiresOneOf { + features: &["geometry_shader"], + ..Default::default() + }, }); } } PrimitiveTopology::PatchList => { // VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00430 if !device.enabled_features().tessellation_shader { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "tessellation_shader", - reason: "InputAssemblyState::topology was set to PrimitiveTopology::PatchList", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`input_assembly_state.topology` is `StateMode::Fixed(PrimitiveTopology::PatchList)`", + requires_one_of: RequiresOneOf { + features: &["tessellation_shader"], + ..Default::default() + }, }); } @@ -753,15 +776,20 @@ where } PartialStateMode::Dynamic(topology_class) => { // VUID-VkPipelineInputAssemblyStateCreateInfo-topology-parameter - topology_class.example().validate(device)?; + topology_class.example().validate_device(device)?; // VUID? if !(device.api_version() >= Version::V1_3 || device.enabled_features().extended_dynamic_state) { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "extended_dynamic_state", - reason: "InputAssemblyState::topology was set to Dynamic", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: + "`input_assembly_state.topology` is `PartialStateMode::Dynamic`", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_3), + features: &["extended_dynamic_state"], + ..Default::default() + }, }); } } @@ -780,9 +808,12 @@ where ) => { // VUID-VkPipelineInputAssemblyStateCreateInfo-topology-06252 if !device.enabled_features().primitive_topology_list_restart { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "primitive_topology_list_restart", - reason: "InputAssemblyState::primitive_restart_enable was set to true in combination with a List PrimitiveTopology", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`input_assembly_state.primitive_restart_enable` is `StateMode::Fixed(true)` and `input_assembly_state.topology` is `StateMode::Fixed(PrimitiveTopology::*List)`", + requires_one_of: RequiresOneOf { + features: &["primitive_topology_list_restart"], + ..Default::default() + }, }); } } @@ -792,9 +823,12 @@ where .enabled_features() .primitive_topology_patch_list_restart { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "primitive_topology_patch_list_restart", - reason: "InputAssemblyState::primitive_restart_enable was set to true in combination with PrimitiveTopology::PatchList", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`input_assembly_state.primitive_restart_enable` is `StateMode::Fixed(true)` and `input_assembly_state.topology` is `StateMode::Fixed(PrimitiveTopology::PatchList)`", + requires_one_of: RequiresOneOf { + features: &["primitive_topology_patch_list_restart"], + ..Default::default() + }, }); } } @@ -807,9 +841,13 @@ where if !(device.api_version() >= Version::V1_3 || device.enabled_features().extended_dynamic_state2) { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "extended_dynamic_state2", - reason: "InputAssemblyState::primitive_restart_enable was set to Dynamic", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`input_assembly_state.primitive_restart_enable` is `StateMode::Dynamic`", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_3), + features: &["extended_dynamic_state2"], + ..Default::default() + }, }); } } @@ -913,9 +951,12 @@ where // VUID-VkPipelineShaderStageCreateInfo-stage-00705 if !device.enabled_features().tessellation_shader { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "tessellation_shader", - reason: "a tessellation shader was provided", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`tessellation_shaders` are provided", + requires_one_of: RequiresOneOf { + features: &["tessellation_shader"], + ..Default::default() + }, }); } @@ -972,9 +1013,12 @@ where // VUID-VkGraphicsPipelineCreateInfo-renderPass-06047 // VUID-VkGraphicsPipelineCreateInfo-renderPass-06057 if view_mask != 0 { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "multiview_tessellation_shader", - reason: "a tessellation shader was provided, and the render pass has multiview enabled with more than zero layers used", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`tessellation_shaders` are provided and `render_pass` has a subpass where `view_mask` is not `0`", + requires_one_of: RequiresOneOf { + features: &["multiview_tessellation_shader"], + ..Default::default() + }, }); } } @@ -1002,9 +1046,12 @@ where // VUID-VkPipelineShaderStageCreateInfo-stage-00704 if !device.enabled_features().geometry_shader { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "geometry_shader", - reason: "a geometry shader was provided", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`geometry_shader` is provided", + requires_one_of: RequiresOneOf { + features: &["geometry_shader"], + ..Default::default() + }, }); } @@ -1035,9 +1082,12 @@ where // VUID-VkGraphicsPipelineCreateInfo-renderPass-06048 // VUID-VkGraphicsPipelineCreateInfo-renderPass-06058 if view_mask != 0 { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "multiview_geometry_shader", - reason: "a geometry shader was provided, and the render pass has multiview enabled with more than zero layers used", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`geometry_shader` is provided and `render_pass` has a subpass where `view_mask` is not `0`", + requires_one_of: RequiresOneOf { + features: &["multiview_geometry_shader"], + ..Default::default() + }, }); } } @@ -1064,13 +1114,16 @@ where } = rasterization_state; // VUID-VkPipelineRasterizationStateCreateInfo-polygonMode-parameter - polygon_mode.validate(device)?; + polygon_mode.validate_device(device)?; // VUID-VkPipelineRasterizationStateCreateInfo-depthClampEnable-00782 if depth_clamp_enable && !device.enabled_features().depth_clamp { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "depth_clamp", - reason: "RasterizationState::depth_clamp_enable was true", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`rasterization_state.depth_clamp_enable` is set", + requires_one_of: RequiresOneOf { + features: &["depth_clamp"], + ..Default::default() + }, }); } @@ -1079,9 +1132,13 @@ where && !(device.api_version() >= Version::V1_3 || device.enabled_features().extended_dynamic_state2) { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "extended_dynamic_state2", - reason: "RasterizationState::rasterizer_discard_enable was set to Dynamic", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`rasterization_state.rasterizer_discard_enable` is `StateMode::Dynamic`", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_3), + features: &["extended_dynamic_state"], + ..Default::default() + }, }); } @@ -1089,25 +1146,34 @@ where if polygon_mode != PolygonMode::Fill && !device.enabled_features().fill_mode_non_solid { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "fill_mode_non_solid", - reason: "RasterizationState::polygon_mode was not Fill", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: + "`rasterization_state.polygon_mode` is not `PolygonMode::Fill`", + requires_one_of: RequiresOneOf { + features: &["fill_mode_non_solid"], + ..Default::default() + }, }); } match cull_mode { StateMode::Fixed(cull_mode) => { // VUID-VkPipelineRasterizationStateCreateInfo-cullMode-parameter - cull_mode.validate(device)?; + cull_mode.validate_device(device)?; } StateMode::Dynamic => { // VUID? if !(device.api_version() >= Version::V1_3 || device.enabled_features().extended_dynamic_state) { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "extended_dynamic_state", - reason: "RasterizationState::cull_mode was set to Dynamic", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: + "`rasterization_state.cull_mode` is `StateMode::Dynamic`", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_3), + features: &["extended_dynamic_state"], + ..Default::default() + }, }); } } @@ -1116,16 +1182,21 @@ where match front_face { StateMode::Fixed(front_face) => { // VUID-VkPipelineRasterizationStateCreateInfo-frontFace-parameter - front_face.validate(device)?; + front_face.validate_device(device)?; } StateMode::Dynamic => { // VUID? if !(device.api_version() >= Version::V1_3 || device.enabled_features().extended_dynamic_state) { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "extended_dynamic_state", - reason: "RasterizationState::front_face was set to Dynamic", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: + "`rasterization_state.front_face` is `StateMode::Dynamic`", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_3), + features: &["extended_dynamic_state"], + ..Default::default() + }, }); } } @@ -1138,10 +1209,17 @@ where } = depth_bias_state; // VUID? - if enable_dynamic && !device.enabled_features().extended_dynamic_state2 { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "extended_dynamic_state2", - reason: "DepthBiasState::enable_dynamic was true", + if enable_dynamic + && !(device.api_version() >= Version::V1_3 + || device.enabled_features().extended_dynamic_state2) + { + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`rasterization_state.depth_bias` is `Some(depth_bias_state)`, where `depth_bias_state.enable_dynamic` is set", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_3), + features: &["extended_dynamic_state2"], + ..Default::default() + }, }); } @@ -1149,9 +1227,12 @@ where if matches!(bias, StateMode::Fixed(bias) if bias.clamp != 0.0) && !device.enabled_features().depth_bias_clamp { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "depth_bias_clamp", - reason: "DepthBias::clamp was not 0.0", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`rasterization_state.depth_bias` is `Some(depth_bias_state)`, where `depth_bias_state.bias` is `StateMode::Fixed(bias)`, where `bias.clamp` is not `0.0`", + requires_one_of: RequiresOneOf { + features: &["depth_bias_clamp"], + ..Default::default() + }, }); } } @@ -1160,44 +1241,54 @@ where if matches!(line_width, StateMode::Fixed(line_width) if line_width != 1.0) && !device.enabled_features().wide_lines { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "wide_lines", - reason: "RasterizationState::line_width was not 1.0", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`rasterization_state.line_width` is `StateMode::Fixed(line_width)`, where `line_width` is not `1.0`", + requires_one_of: RequiresOneOf { + features: &["wide_lines"], + ..Default::default() + }, }); } if device.enabled_extensions().ext_line_rasterization { // VUID-VkPipelineRasterizationLineStateCreateInfoEXT-lineRasterizationMode-parameter - line_rasterization_mode.validate(device)?; + line_rasterization_mode.validate_device(device)?; match line_rasterization_mode { LineRasterizationMode::Default => (), LineRasterizationMode::Rectangular => { // VUID-VkPipelineRasterizationLineStateCreateInfoEXT-lineRasterizationMode-02768 if !device.enabled_features().rectangular_lines { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "rectangular_lines", - reason: - "RasterizationState::line_rasterization_mode was Rectangular", - }); + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`rasterization_state.line_rasterization_mode` is `LineRasterizationMode::Rectangular`", + requires_one_of: RequiresOneOf { + features: &["rectangular_lines"], + ..Default::default() + }, + }); } } LineRasterizationMode::Bresenham => { // VUID-VkPipelineRasterizationLineStateCreateInfoEXT-lineRasterizationMode-02769 if !device.enabled_features().bresenham_lines { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "bresenham_lines", - reason: - "RasterizationState::line_rasterization_mode was Bresenham", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`rasterization_state.line_rasterization_mode` is `LineRasterizationMode::Bresenham`", + requires_one_of: RequiresOneOf { + features: &["bresenham_lines"], + ..Default::default() + }, }); } } LineRasterizationMode::RectangularSmooth => { // VUID-VkPipelineRasterizationLineStateCreateInfoEXT-lineRasterizationMode-02770 if !device.enabled_features().smooth_lines { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "smooth_lines", - reason: "RasterizationState::line_rasterization_mode was RectangularSmooth", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`rasterization_state.line_rasterization_mode` is `LineRasterizationMode::RectangularSmooth`", + requires_one_of: RequiresOneOf { + features: &["smooth_lines"], + ..Default::default() + }, }); } } @@ -1208,9 +1299,12 @@ where LineRasterizationMode::Default => { // VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02774 if !device.enabled_features().stippled_rectangular_lines { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "stippled_rectangular_lines", - reason: "RasterizationState::line_stipple was Some and line_rasterization_mode was Default", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`rasterization_state.line_stipple` is `Some` and `rasterization_state.line_rasterization_mode` is `LineRasterizationMode::Default`", + requires_one_of: RequiresOneOf { + features: &["stippled_rectangular_lines"], + ..Default::default() + }, }); } @@ -1224,27 +1318,36 @@ where LineRasterizationMode::Rectangular => { // VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02771 if !device.enabled_features().stippled_rectangular_lines { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "stippled_rectangular_lines", - reason: "RasterizationState::line_stipple was Some and line_rasterization_mode was Rectangular", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`rasterization_state.line_stipple` is `Some` and `rasterization_state.line_rasterization_mode` is `LineRasterizationMode::Rectangular`", + requires_one_of: RequiresOneOf { + features: &["stippled_rectangular_lines"], + ..Default::default() + }, }); } } LineRasterizationMode::Bresenham => { // VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02772 if !device.enabled_features().stippled_bresenham_lines { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "stippled_bresenham_lines", - reason: "RasterizationState::line_stipple was Some and line_rasterization_mode was Bresenham", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`rasterization_state.line_stipple` is `Some` and `rasterization_state.line_rasterization_mode` is `LineRasterizationMode::Bresenham`", + requires_one_of: RequiresOneOf { + features: &["stippled_bresenham_lines"], + ..Default::default() + }, }); } } LineRasterizationMode::RectangularSmooth => { // VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02773 if !device.enabled_features().stippled_smooth_lines { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "stippled_smooth_lines", - reason: "RasterizationState::line_stipple was Some and line_rasterization_mode was RectangularSmooth", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`rasterization_state.line_stipple` is `Some` and `rasterization_state.line_rasterization_mode` is `LineRasterizationMode::RectangularSmooth`", + requires_one_of: RequiresOneOf { + features: &["stippled_smooth_lines"], + ..Default::default() + }, }); } } @@ -1258,16 +1361,22 @@ where } } else { if line_rasterization_mode != LineRasterizationMode::Default { - return Err(GraphicsPipelineCreationError::ExtensionNotEnabled { - extension: "ext_line_rasterization", - reason: "RasterizationState::line_rasterization_mode was not Default", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`rasterization_state.line_rasterization_mode` is not `LineRasterizationMode::Default`", + requires_one_of: RequiresOneOf { + device_extensions: &["ext_line_rasterization"], + ..Default::default() + }, }); } if line_stipple.is_some() { - return Err(GraphicsPipelineCreationError::ExtensionNotEnabled { - extension: "ext_line_rasterization", - reason: "RasterizationState::line_stipple was not None", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`rasterization_state.line_stipple` is `Some`", + requires_one_of: RequiresOneOf { + device_extensions: &["ext_line_rasterization"], + ..Default::default() + }, }); } } @@ -1282,7 +1391,7 @@ where if device.enabled_extensions().ext_discard_rectangles { // VUID-VkPipelineDiscardRectangleStateCreateInfoEXT-discardRectangleMode-parameter - mode.validate(device)?; + mode.validate_device(device)?; let discard_rectangle_count = match *rectangles { PartialStateMode::Dynamic(count) => count, @@ -1305,10 +1414,12 @@ where }; if error { - return Err(GraphicsPipelineCreationError::ExtensionNotEnabled { - extension: "ext_discard_rectangles", - reason: - "DiscardRectangleState::rectangles was not Fixed with an empty list", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`discard_rectangle_state.rectangles` is not `PartialStateMode::Fixed(vec![])`", + requires_one_of: RequiresOneOf { + device_extensions: &["ext_discard_rectangles"], + ..Default::default() + }, }); } } @@ -1353,9 +1464,13 @@ where .enabled_features() .extended_dynamic_state2_patch_control_points { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "extended_dynamic_state2_patch_control_points", - reason: "TessellationState::patch_control_points was set to Dynamic", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: + "`tessellation_state.patch_control_points` is `StateMode::Dynamic`", + requires_one_of: RequiresOneOf { + features: &["extended_dynamic_state2_patch_control_points"], + ..Default::default() + }, }); } } @@ -1427,10 +1542,14 @@ where if !(device.api_version() >= Version::V1_3 || device.enabled_features().extended_dynamic_state) { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "extended_dynamic_state", - reason: "ViewportState::FixedViewport::scissor_count_dynamic was set to true", - }); + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`viewport_state` is `ViewportState::FixedViewport`, where `scissor_count_dynamic` is set", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_3), + features: &["extended_dynamic_state"], + ..Default::default() + }, + }); } // VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-03380 @@ -1455,10 +1574,14 @@ where if !(device.api_version() >= Version::V1_3 || device.enabled_features().extended_dynamic_state) { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "extended_dynamic_state", - reason: "ViewportState::FixedScissor::viewport_count_dynamic was set to true", - }); + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`viewport_state` is `ViewportState::FixedScissor`, where `viewport_count_dynamic` is set", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_3), + features: &["extended_dynamic_state"], + ..Default::default() + }, + }); } // VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-03379 @@ -1489,10 +1612,13 @@ where if !(device.api_version() >= Version::V1_3 || device.enabled_features().extended_dynamic_state) { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "extended_dynamic_state", - reason: - "ViewportState::Dynamic::viewport_count_dynamic was set to true", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`viewport_state` is `ViewportState::Dynamic`, where `viewport_count_dynamic` is set", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_3), + features: &["extended_dynamic_state"], + ..Default::default() + }, }); } @@ -1507,10 +1633,13 @@ where if !(device.api_version() >= Version::V1_3 || device.enabled_features().extended_dynamic_state) { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "extended_dynamic_state", - reason: - "ViewportState::Dynamic::scissor_count_dynamic was set to true", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`viewport_state` is `ViewportState::Dynamic`, where `scissor_count_dynamic` is set", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_3), + features: &["extended_dynamic_state"], + ..Default::default() + }, }); } @@ -1532,9 +1661,12 @@ where // VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216 // VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217 if viewport_scissor_count > 1 && !device.enabled_features().multi_viewport { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "multi_viewport", - reason: "ViewportState viewport/scissor count was greater than 1", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`viewport_state` has a fixed viewport/scissor count that is greater than `1`", + requires_one_of: RequiresOneOf { + features: &["multi_viewport"], + ..Default::default() + }, }); } @@ -1640,9 +1772,14 @@ where && !(device.api_version() >= Version::V1_3 || device.enabled_features().extended_dynamic_state) { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "extended_dynamic_state", - reason: "DepthState::enable_dynamic was true", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: + "`depth_stencil_state.depth` is `Some(depth_state)`, where `depth_state.enable_dynamic` is set", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_3), + features: &["extended_dynamic_state"], + ..Default::default() + }, }); } @@ -1665,9 +1802,13 @@ where if !(device.api_version() >= Version::V1_3 || device.enabled_features().extended_dynamic_state) { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "extended_dynamic_state", - reason: "DepthState::write_enable was set to Dynamic", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`depth_stencil_state.depth` is `Some(depth_state)`, where `depth_state.write_enable` is `StateMode::Dynamic`", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_3), + features: &["extended_dynamic_state"], + ..Default::default() + }, }); } } @@ -1676,16 +1817,20 @@ where match compare_op { StateMode::Fixed(compare_op) => { // VUID-VkPipelineDepthStencilStateCreateInfo-depthCompareOp-parameter - compare_op.validate(device)?; + compare_op.validate_device(device)?; } StateMode::Dynamic => { // VUID? if !(device.api_version() >= Version::V1_3 || device.enabled_features().extended_dynamic_state) { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "extended_dynamic_state", - reason: "DepthState::compare_op was set to Dynamic", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`depth_stencil_state.depth` is `Some(depth_state)`, where `depth_state.compare_op` is `StateMode::Dynamic`", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_3), + features: &["extended_dynamic_state"], + ..Default::default() + }, }); } } @@ -1700,9 +1845,12 @@ where // VUID-VkPipelineDepthStencilStateCreateInfo-depthBoundsTestEnable-00598 if !device.enabled_features().depth_bounds { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "depth_bounds", - reason: "DepthStencilState::depth_bounds was Some", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`depth_stencil_state.depth_bounds` is `Some`", + requires_one_of: RequiresOneOf { + features: &["depth_bounds"], + ..Default::default() + }, }); } @@ -1711,9 +1859,13 @@ where && !(device.api_version() >= Version::V1_3 || device.enabled_features().extended_dynamic_state) { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "extended_dynamic_state", - reason: "DepthBoundsState::enable_dynamic was true", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`depth_stencil_state.depth_bounds` is `Some(depth_bounds_state)`, where `depth_bounds_state.enable_dynamic` is set", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_3), + features: &["extended_dynamic_state"], + ..Default::default() + }, }); } @@ -1723,10 +1875,13 @@ where && !(0.0..1.0).contains(bounds.start()) && !(0.0..1.0).contains(bounds.end()) { - return Err(GraphicsPipelineCreationError::ExtensionNotEnabled { - extension: "ext_depth_range_unrestricted", - reason: "DepthBoundsState::bounds were not both between 0.0 and 1.0 inclusive", - }); + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`depth_stencil_state.depth_bounds` is `Some(depth_bounds_state)`, where `depth_bounds_state.bounds` is not between `0.0` and `1.0` inclusive", + requires_one_of: RequiresOneOf { + device_extensions: &["ext_depth_range_unrestricted"], + ..Default::default() + }, + }); } } } @@ -1754,9 +1909,14 @@ where && !(device.api_version() >= Version::V1_3 || device.enabled_features().extended_dynamic_state) { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "extended_dynamic_state", - reason: "StencilState::enable_dynamic was true", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: + "`depth_stencil_state.stencil` is `Some(stencil_state)`, where `stencil_state.enable_dynamic` is set", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_3), + features: &["extended_dynamic_state"], + ..Default::default() + }, }); } @@ -1771,16 +1931,16 @@ where } = ops; // VUID-VkStencilOpState-failOp-parameter - fail_op.validate(device)?; + fail_op.validate_device(device)?; // VUID-VkStencilOpState-passOp-parameter - pass_op.validate(device)?; + pass_op.validate_device(device)?; // VUID-VkStencilOpState-depthFailOp-parameter - depth_fail_op.validate(device)?; + depth_fail_op.validate_device(device)?; // VUID-VkStencilOpState-compareOp-parameter - compare_op.validate(device)?; + compare_op.validate_device(device)?; } } (StateMode::Dynamic, StateMode::Dynamic) => { @@ -1788,9 +1948,13 @@ where if !(device.api_version() >= Version::V1_3 || device.enabled_features().extended_dynamic_state) { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "extended_dynamic_state", - reason: "StencilState::ops was set to Dynamic", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`depth_stencil_state.stencil` is `Some(stencil_state)`, where `stencil_state.front.ops` and `stencil_state.back.ops` are `StateMode::Dynamic`", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_3), + features: &["extended_dynamic_state"], + ..Default::default() + }, }); } } @@ -1843,7 +2007,7 @@ where } = multisample_state; // VUID-VkPipelineMultisampleStateCreateInfo-rasterizationSamples-parameter - rasterization_samples.validate(device)?; + rasterization_samples.validate_device(device)?; match render_pass { PipelineRenderPassType::BeginRenderPass(subpass) => { @@ -1869,9 +2033,12 @@ where if let Some(min_sample_shading) = sample_shading { // VUID-VkPipelineMultisampleStateCreateInfo-sampleShadingEnable-00784 if !device.enabled_features().sample_rate_shading { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "sample_rate_shading", - reason: "MultisampleState::sample_shading was Some", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`multisample_state.sample_shading` is `Some`", + requires_one_of: RequiresOneOf { + features: &["sample_rate_shading"], + ..Default::default() + }, }); } @@ -1882,9 +2049,12 @@ where // VUID-VkPipelineMultisampleStateCreateInfo-alphaToOneEnable-00785 if alpha_to_one_enable && !device.enabled_features().alpha_to_one { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "alpha_to_one", - reason: "MultisampleState::alpha_to_one was true", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`multisample_state.alpha_to_one_enable` is set", + requires_one_of: RequiresOneOf { + features: &["alpha_to_one"], + ..Default::default() + }, }); } @@ -1906,23 +2076,30 @@ where if let Some(logic_op) = logic_op { // VUID-VkPipelineColorBlendStateCreateInfo-logicOpEnable-00606 if !device.enabled_features().logic_op { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "logic_op", - reason: "ColorBlendState::logic_op was set to Some", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`color_blend_state.logic_op` is `Some`", + requires_one_of: RequiresOneOf { + features: &["logic_op"], + ..Default::default() + }, }); } match logic_op { StateMode::Fixed(logic_op) => { // VUID-VkPipelineColorBlendStateCreateInfo-logicOpEnable-00607 - logic_op.validate(device)? + logic_op.validate_device(device)? } StateMode::Dynamic => { // VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04869 if !device.enabled_features().extended_dynamic_state2_logic_op { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "extended_dynamic_state2_logic_op", - reason: "ColorBlendState::logic_op was set to Some(Dynamic)", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: + "`color_blend_state.logic_op` is `Some(StateMode::Dynamic)`", + requires_one_of: RequiresOneOf { + features: &["extended_dynamic_state2_logic_op"], + ..Default::default() + }, }); } } @@ -1954,12 +2131,13 @@ where // VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 if !iter.all(|state| state == first) { - return Err( - GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "independent_blend", - reason: "The blend and color_write_mask members of all elements of ColorBlendState::attachments were not identical", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`color_blend_state.attachments` has elements where `blend` and `color_write_mask` do not match the other elements", + requires_one_of: RequiresOneOf { + features: &["independent_blend"], + ..Default::default() }, - ); + }); } } @@ -1981,22 +2159,22 @@ where } = blend; // VUID-VkPipelineColorBlendAttachmentState-colorBlendOp-parameter - color_op.validate(device)?; + color_op.validate_device(device)?; // VUID-VkPipelineColorBlendAttachmentState-srcColorBlendFactor-parameter - color_source.validate(device)?; + color_source.validate_device(device)?; // VUID-VkPipelineColorBlendAttachmentState-dstColorBlendFactor-parameter - color_destination.validate(device)?; + color_destination.validate_device(device)?; // VUID-VkPipelineColorBlendAttachmentState-alphaBlendOp-parameter - alpha_op.validate(device)?; + alpha_op.validate_device(device)?; // VUID-VkPipelineColorBlendAttachmentState-srcAlphaBlendFactor-parameter - alpha_source.validate(device)?; + alpha_source.validate_device(device)?; // VUID-VkPipelineColorBlendAttachmentState-dstAlphaBlendFactor-parameter - alpha_destination.validate(device)?; + alpha_destination.validate_device(device)?; // VUID? if !device.enabled_features().dual_src_blend @@ -2017,10 +2195,12 @@ where ) }) { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "dual_src_blend", - reason: - "One of the BlendFactor members of AttachmentBlend was set to Src1", + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`color_blend_state.attachments` has an element where `blend` is `Some(blend)`, where `blend.color_source`, `blend.color_destination`, `blend.alpha_source` or `blend.alpha_destination` is `BlendFactor::Src1*`", + requires_one_of: RequiresOneOf { + features: &["dual_src_blend"], + ..Default::default() + }, }); } @@ -2058,19 +2238,25 @@ where StateMode::Fixed(enable) => { // VUID-VkPipelineColorWriteCreateInfoEXT-pAttachments-04801 if !enable && !device.enabled_features().color_write_enable { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "color_write_enable", - reason: "ColorBlendAttachmentState::color_blend_enable was set to Fixed(false)", - }); + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`color_blend_state.attachments` has an element where `color_write_enable` is `StateMode::Fixed(false)`", + requires_one_of: RequiresOneOf { + features: &["color_write_enable"], + ..Default::default() + }, + }); } } StateMode::Dynamic => { // VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04800 if !device.enabled_features().color_write_enable { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "color_write_enable", - reason: "ColorBlendAttachmentState::color_blend_enable was set to Dynamic", - }); + return Err(GraphicsPipelineCreationError::RequirementNotMet { + required_for: "`color_blend_state.attachments` has an element where `color_write_enable` is `StateMode::Dynamic`", + requires_one_of: RequiresOneOf { + features: &["color_write_enable"], + ..Default::default() + }, + }); } } } @@ -3117,13 +3303,6 @@ where )); let (logic_op_enable, logic_op) = if let Some(logic_op) = logic_op { - if !device.enabled_features().logic_op { - return Err(GraphicsPipelineCreationError::FeatureNotEnabled { - feature: "logic_op", - reason: "ColorBlendState::logic_op was set to Some", - }); - } - let logic_op = match logic_op { StateMode::Fixed(logic_op) => { dynamic_state.insert(DynamicState::LogicOp, false); diff --git a/vulkano/src/pipeline/graphics/color_blend.rs b/vulkano/src/pipeline/graphics/color_blend.rs index e3c215a0df..ae5606b25d 100644 --- a/vulkano/src/pipeline/graphics/color_blend.rs +++ b/vulkano/src/pipeline/graphics/color_blend.rs @@ -411,232 +411,232 @@ vulkan_enum! { /* // TODO: document Zero = ZERO_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document Src = SRC_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document Dst = DST_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document SrcOver = SRC_OVER_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document DstOver = DST_OVER_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document SrcIn = SRC_IN_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document DstIn = DST_IN_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document SrcOut = SRC_OUT_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document DstOut = DST_OUT_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document SrcAtop = SRC_ATOP_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document DstAtop = DST_ATOP_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document Xor = XOR_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document Multiply = MULTIPLY_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document Screen = SCREEN_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document Overlay = OVERLAY_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document Darken = DARKEN_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document Lighten = LIGHTEN_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document Colordodge = COLORDODGE_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document Colorburn = COLORBURN_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document Hardlight = HARDLIGHT_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document Softlight = SOFTLIGHT_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document Difference = DIFFERENCE_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document Exclusion = EXCLUSION_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document Invert = INVERT_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document InvertRgb = INVERT_RGB_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document Lineardodge = LINEARDODGE_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document Linearburn = LINEARBURN_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document Vividlight = VIVIDLIGHT_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document Linearlight = LINEARLIGHT_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document Pinlight = PINLIGHT_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document Hardmix = HARDMIX_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document HslHue = HSL_HUE_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document HslSaturation = HSL_SATURATION_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document HslColor = HSL_COLOR_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document HslLuminosity = HSL_LUMINOSITY_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document Plus = PLUS_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document PlusClamped = PLUS_CLAMPED_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document PlusClampedAlpha = PLUS_CLAMPED_ALPHA_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document PlusDarker = PLUS_DARKER_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document Minus = MINUS_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document MinusClamped = MINUS_CLAMPED_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document Contrast = CONTRAST_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document InvertOvg = INVERT_OVG_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document Red = RED_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document Green = GREEN_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // TODO: document Blue = BLUE_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, */ } diff --git a/vulkano/src/pipeline/graphics/creation_error.rs b/vulkano/src/pipeline/graphics/creation_error.rs index f6ba55aba5..a081a4048a 100644 --- a/vulkano/src/pipeline/graphics/creation_error.rs +++ b/vulkano/src/pipeline/graphics/creation_error.rs @@ -11,26 +11,21 @@ use super::vertex_input::IncompatibleVertexDefinitionError; use crate::{ descriptor_set::layout::DescriptorSetLayoutCreationError, format::{Format, NumericType}, - macros::ExtensionNotEnabled, pipeline::layout::{PipelineLayoutCreationError, PipelineLayoutSupersetError}, shader::ShaderInterfaceMismatchError, - OomError, VulkanError, + OomError, RequirementNotMet, RequiresOneOf, VulkanError, +}; +use std::{ + error::Error, + fmt::{Display, Error as FmtError, Formatter}, }; -use std::{error::Error, fmt}; /// Error that can happen when creating a graphics pipeline. #[derive(Clone, Debug, PartialEq, Eq)] pub enum GraphicsPipelineCreationError { - /// A device extension that was required for a particular setting on the graphics pipeline was not enabled. - ExtensionNotEnabled { - extension: &'static str, - reason: &'static str, - }, - - /// A device feature that was required for a particular setting on the graphics pipeline was not enabled. - FeatureNotEnabled { - feature: &'static str, - reason: &'static str, + RequirementNotMet { + required_for: &'static str, + requires_one_of: RequiresOneOf, }, /// A color attachment has a format that does not support blending. @@ -215,20 +210,19 @@ impl Error for GraphicsPipelineCreationError { } } -impl fmt::Display for GraphicsPipelineCreationError { +impl Display for GraphicsPipelineCreationError { #[inline] - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match *self { - Self::ExtensionNotEnabled { extension, reason } => write!( - f, - "the extension {} must be enabled: {}", - extension, reason - ), - Self::FeatureNotEnabled { feature, reason } => write!( + Self::RequirementNotMet { + required_for, + requires_one_of, + } => write!( f, - "the feature {} must be enabled: {}", - feature, reason + "a requirement was not met for: {}; requires one of: {}", + required_for, requires_one_of, ), + Self::ColorAttachmentFormatBlendNotSupported { attachment_index } => write!( f, "color attachment {} has a format that does not support blending", @@ -436,12 +430,12 @@ impl From for GraphicsPipelineCreationError { } } -impl From for GraphicsPipelineCreationError { +impl From for GraphicsPipelineCreationError { #[inline] - fn from(err: ExtensionNotEnabled) -> Self { - Self::ExtensionNotEnabled { - extension: err.extension, - reason: err.reason, + fn from(err: RequirementNotMet) -> Self { + Self::RequirementNotMet { + required_for: err.required_for, + requires_one_of: err.requires_one_of, } } } diff --git a/vulkano/src/pipeline/graphics/input_assembly.rs b/vulkano/src/pipeline/graphics/input_assembly.rs index a39825597d..5c0a35c45d 100644 --- a/vulkano/src/pipeline/graphics/input_assembly.rs +++ b/vulkano/src/pipeline/graphics/input_assembly.rs @@ -228,7 +228,7 @@ vulkan_enum! { // TODO: document U8 = UINT8_EXT { - extensions: [ext_index_type_uint8], + device_extensions: [ext_index_type_uint8], }, // TODO: document @@ -240,7 +240,7 @@ vulkan_enum! { /* // TODO: document None = NONE_KHR { - extensions: [khr_acceleration_structure, nv_ray_tracing], + device_extensions: [khr_acceleration_structure, nv_ray_tracing], }, */ } diff --git a/vulkano/src/pipeline/graphics/mod.rs b/vulkano/src/pipeline/graphics/mod.rs index 50b4a26ec5..8db5f46b7d 100644 --- a/vulkano/src/pipeline/graphics/mod.rs +++ b/vulkano/src/pipeline/graphics/mod.rs @@ -72,7 +72,7 @@ use crate::{ }; use std::{ collections::HashMap, - fmt, + fmt::{Debug, Error as FmtError, Formatter}, hash::{Hash, Hasher}, ptr, sync::Arc, @@ -264,10 +264,10 @@ unsafe impl DeviceOwned for GraphicsPipeline { } } -impl fmt::Debug for GraphicsPipeline { +impl Debug for GraphicsPipeline { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!(fmt, "", self.handle) + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { + write!(f, "", self.handle) } } diff --git a/vulkano/src/pipeline/graphics/rasterization.rs b/vulkano/src/pipeline/graphics/rasterization.rs index 66ef838ada..6731125c23 100644 --- a/vulkano/src/pipeline/graphics/rasterization.rs +++ b/vulkano/src/pipeline/graphics/rasterization.rs @@ -245,7 +245,7 @@ vulkan_enum! { /* // TODO: document FillRectangle = FILL_RECTANGLE_NV { - extensions: [nv_fill_rectangle], + device_extensions: [nv_fill_rectangle], }, */ } diff --git a/vulkano/src/pipeline/graphics/tests.rs b/vulkano/src/pipeline/graphics/tests.rs index 42a5756338..df155804f4 100644 --- a/vulkano/src/pipeline/graphics/tests.rs +++ b/vulkano/src/pipeline/graphics/tests.rs @@ -130,7 +130,7 @@ fn bad_primitive_restart() { ); match result { - Err(GraphicsPipelineCreationError::FeatureNotEnabled { .. }) => (), + Err(GraphicsPipelineCreationError::RequirementNotMet { .. }) => (), _ => panic!(), } } diff --git a/vulkano/src/pipeline/graphics/vertex_input/buffers.rs b/vulkano/src/pipeline/graphics/vertex_input/buffers.rs index be7fcaedc1..803e29221b 100644 --- a/vulkano/src/pipeline/graphics/vertex_input/buffers.rs +++ b/vulkano/src/pipeline/graphics/vertex_input/buffers.rs @@ -17,7 +17,10 @@ use crate::{ shader::ShaderInterface, DeviceSize, }; -use std::mem; +use std::{ + fmt::{Debug, Error as FmtError, Formatter}, + mem, +}; /// A vertex definition for any number of vertex and instance buffers. #[derive(Clone, Debug, Default)] @@ -30,8 +33,8 @@ struct VertexBuffer { input_rate: VertexInputRate, } -impl std::fmt::Debug for VertexBuffer { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl Debug for VertexBuffer { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { f.debug_struct("VertexBuffer") .field("stride", &self.stride) .field("input_rate", &self.input_rate) diff --git a/vulkano/src/pipeline/graphics/vertex_input/definition.rs b/vulkano/src/pipeline/graphics/vertex_input/definition.rs index af7e331e1d..65660dbcf9 100644 --- a/vulkano/src/pipeline/graphics/vertex_input/definition.rs +++ b/vulkano/src/pipeline/graphics/vertex_input/definition.rs @@ -55,7 +55,10 @@ use crate::{ pipeline::graphics::vertex_input::{VertexInputState, VertexMemberTy}, shader::ShaderInterface, }; -use std::{error::Error, fmt}; +use std::{ + error::Error, + fmt::{Display, Error as FmtError, Formatter}, +}; /// Trait for types that can create a [`VertexInputState`] from a [`ShaderInterface`]. pub unsafe trait VertexDefinition { @@ -99,15 +102,15 @@ pub enum IncompatibleVertexDefinitionError { impl Error for IncompatibleVertexDefinitionError {} -impl fmt::Display for IncompatibleVertexDefinitionError { +impl Display for IncompatibleVertexDefinitionError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match *self { IncompatibleVertexDefinitionError::MissingAttribute { .. } => { - write!(fmt, "an attribute is missing",) + write!(f, "an attribute is missing",) } IncompatibleVertexDefinitionError::FormatMismatch { .. } => { - write!(fmt, "the format of an attribute does not match") + write!(f, "the format of an attribute does not match") } } } diff --git a/vulkano/src/pipeline/layout.rs b/vulkano/src/pipeline/layout.rs index 083b7fcb77..1c5c170175 100644 --- a/vulkano/src/pipeline/layout.rs +++ b/vulkano/src/pipeline/layout.rs @@ -66,14 +66,13 @@ use crate::{ descriptor_set::layout::{DescriptorRequirementsNotMet, DescriptorSetLayout, DescriptorType}, device::{Device, DeviceOwned}, - macros::ExtensionNotEnabled, shader::{DescriptorRequirements, ShaderStages}, - OomError, VulkanError, VulkanObject, + OomError, RequirementNotMet, RequiresOneOf, VulkanError, VulkanObject, }; use smallvec::SmallVec; use std::{ error::Error, - fmt, + fmt::{Display, Error as FmtError, Formatter}, hash::{Hash, Hasher}, mem::MaybeUninit, ptr, @@ -471,7 +470,7 @@ impl PipelineLayout { } = range; // VUID-VkPushConstantRange-stageFlags-parameter - stages.validate(device)?; + stages.validate_device(device)?; // VUID-VkPushConstantRange-stageFlags-requiredbitmask assert!(!stages.is_empty()); @@ -714,9 +713,9 @@ pub enum PipelineLayoutCreationError { /// Not enough memory. OomError(OomError), - ExtensionNotEnabled { - extension: &'static str, - reason: &'static str, + RequirementNotMet { + required_for: &'static str, + requires_one_of: RequiresOneOf, }, /// The number of elements in `set_layouts` is greater than the @@ -830,15 +829,19 @@ impl Error for PipelineLayoutCreationError { } } -impl fmt::Display for PipelineLayoutCreationError { +impl Display for PipelineLayoutCreationError { #[inline] - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match *self { Self::OomError(_) => write!(f, "not enough memory available"), - Self::ExtensionNotEnabled { extension, reason } => write!( + + Self::RequirementNotMet { + required_for, + requires_one_of, + } => write!( f, - "the extension {} must be enabled: {}", - extension, reason + "a requirement was not met for: {}; requires one of: {}", + required_for, requires_one_of, ), Self::MaxBoundDescriptorSetsExceeded { provided, max_supported } => write!( @@ -960,12 +963,12 @@ impl From for PipelineLayoutCreationError { } } -impl From for PipelineLayoutCreationError { +impl From for PipelineLayoutCreationError { #[inline] - fn from(err: ExtensionNotEnabled) -> Self { - Self::ExtensionNotEnabled { - extension: err.extension, - reason: err.reason, + fn from(err: RequirementNotMet) -> Self { + Self::RequirementNotMet { + required_for: err.required_for, + requires_one_of: err.requires_one_of, } } } @@ -1000,12 +1003,12 @@ impl Error for PipelineLayoutSupersetError { } } -impl fmt::Display for PipelineLayoutSupersetError { +impl Display for PipelineLayoutSupersetError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match self { PipelineLayoutSupersetError::DescriptorRequirementsNotMet { set_num, binding_num, .. } => write!( - fmt, + f, "the descriptor at set {} binding {} does not meet the requirements", set_num, binding_num ), @@ -1013,7 +1016,7 @@ impl fmt::Display for PipelineLayoutSupersetError { set_num, binding_num, } => write!( - fmt, + f, "a descriptor at set {} binding {} is required by the shaders, but is missing from the pipeline layout", set_num, binding_num ), @@ -1022,19 +1025,19 @@ impl fmt::Display for PipelineLayoutSupersetError { second_range, } => { writeln!( - fmt, + f, "our range did not completely encompass the other range" )?; - writeln!(fmt, " our stages: {:?}", first_range.stages)?; + writeln!(f, " our stages: {:?}", first_range.stages)?; writeln!( - fmt, + f, " our range: {} - {}", first_range.offset, first_range.offset + first_range.size )?; - writeln!(fmt, " other stages: {:?}", second_range.stages)?; + writeln!(f, " other stages: {:?}", second_range.stages)?; write!( - fmt, + f, " other range: {} - {}", second_range.offset, second_range.offset + second_range.size diff --git a/vulkano/src/pipeline/mod.rs b/vulkano/src/pipeline/mod.rs index 3e27c60691..01281cad47 100644 --- a/vulkano/src/pipeline/mod.rs +++ b/vulkano/src/pipeline/mod.rs @@ -58,12 +58,12 @@ vulkan_enum! { /* // TODO: document RayTracing = RAY_TRACING_KHR { - extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], + device_extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], }, // TODO: document SubpassShading = SUBPASS_SHADING_HUAWEI { - extensions: [huawei_subpass_shading], + device_extensions: [huawei_subpass_shading], }, */ } @@ -104,156 +104,156 @@ vulkan_enum! { // TODO: document CullMode = CULL_MODE { api_version: V1_3, - extensions: [ext_extended_dynamic_state], + device_extensions: [ext_extended_dynamic_state], }, // TODO: document FrontFace = FRONT_FACE { api_version: V1_3, - extensions: [ext_extended_dynamic_state], + device_extensions: [ext_extended_dynamic_state], }, // TODO: document PrimitiveTopology = PRIMITIVE_TOPOLOGY { api_version: V1_3, - extensions: [ext_extended_dynamic_state], + device_extensions: [ext_extended_dynamic_state], }, // TODO: document ViewportWithCount = VIEWPORT_WITH_COUNT { api_version: V1_3, - extensions: [ext_extended_dynamic_state], + device_extensions: [ext_extended_dynamic_state], }, // TODO: document ScissorWithCount = SCISSOR_WITH_COUNT { api_version: V1_3, - extensions: [ext_extended_dynamic_state], + device_extensions: [ext_extended_dynamic_state], }, // TODO: document VertexInputBindingStride = VERTEX_INPUT_BINDING_STRIDE { api_version: V1_3, - extensions: [ext_extended_dynamic_state], + device_extensions: [ext_extended_dynamic_state], }, // TODO: document DepthTestEnable = DEPTH_TEST_ENABLE { api_version: V1_3, - extensions: [ext_extended_dynamic_state], + device_extensions: [ext_extended_dynamic_state], }, // TODO: document DepthWriteEnable = DEPTH_WRITE_ENABLE { api_version: V1_3, - extensions: [ext_extended_dynamic_state], + device_extensions: [ext_extended_dynamic_state], }, // TODO: document DepthCompareOp = DEPTH_COMPARE_OP { api_version: V1_3, - extensions: [ext_extended_dynamic_state], + device_extensions: [ext_extended_dynamic_state], }, // TODO: document DepthBoundsTestEnable = DEPTH_BOUNDS_TEST_ENABLE { api_version: V1_3, - extensions: [ext_extended_dynamic_state], + device_extensions: [ext_extended_dynamic_state], }, // TODO: document StencilTestEnable = STENCIL_TEST_ENABLE { api_version: V1_3, - extensions: [ext_extended_dynamic_state], + device_extensions: [ext_extended_dynamic_state], }, // TODO: document StencilOp = STENCIL_OP { api_version: V1_3, - extensions: [ext_extended_dynamic_state], + device_extensions: [ext_extended_dynamic_state], }, // TODO: document RasterizerDiscardEnable = RASTERIZER_DISCARD_ENABLE { api_version: V1_3, - extensions: [ext_extended_dynamic_state2], + device_extensions: [ext_extended_dynamic_state2], }, // TODO: document DepthBiasEnable = DEPTH_BIAS_ENABLE { api_version: V1_3, - extensions: [ext_extended_dynamic_state2], + device_extensions: [ext_extended_dynamic_state2], }, // TODO: document PrimitiveRestartEnable = PRIMITIVE_RESTART_ENABLE { api_version: V1_3, - extensions: [ext_extended_dynamic_state2], + device_extensions: [ext_extended_dynamic_state2], }, // TODO: document ViewportWScaling = VIEWPORT_W_SCALING_NV { - extensions: [nv_clip_space_w_scaling], + device_extensions: [nv_clip_space_w_scaling], }, // TODO: document DiscardRectangle = DISCARD_RECTANGLE_EXT { - extensions: [ext_discard_rectangles], + device_extensions: [ext_discard_rectangles], }, // TODO: document SampleLocations = SAMPLE_LOCATIONS_EXT { - extensions: [ext_sample_locations], + device_extensions: [ext_sample_locations], }, // TODO: document RayTracingPipelineStackSize = RAY_TRACING_PIPELINE_STACK_SIZE_KHR { - extensions: [khr_ray_tracing_pipeline], + device_extensions: [khr_ray_tracing_pipeline], }, // TODO: document ViewportShadingRatePalette = VIEWPORT_SHADING_RATE_PALETTE_NV { - extensions: [nv_shading_rate_image], + device_extensions: [nv_shading_rate_image], }, // TODO: document ViewportCoarseSampleOrder = VIEWPORT_COARSE_SAMPLE_ORDER_NV { - extensions: [nv_shading_rate_image], + device_extensions: [nv_shading_rate_image], }, // TODO: document ExclusiveScissor = EXCLUSIVE_SCISSOR_NV { - extensions: [nv_scissor_exclusive], + device_extensions: [nv_scissor_exclusive], }, // TODO: document FragmentShadingRate = FRAGMENT_SHADING_RATE_KHR { - extensions: [khr_fragment_shading_rate], + device_extensions: [khr_fragment_shading_rate], }, // TODO: document LineStipple = LINE_STIPPLE_EXT { - extensions: [ext_line_rasterization], + device_extensions: [ext_line_rasterization], }, // TODO: document VertexInput = VERTEX_INPUT_EXT { - extensions: [ext_vertex_input_dynamic_state], + device_extensions: [ext_vertex_input_dynamic_state], }, // TODO: document PatchControlPoints = PATCH_CONTROL_POINTS_EXT { - extensions: [ext_extended_dynamic_state2], + device_extensions: [ext_extended_dynamic_state2], }, // TODO: document LogicOp = LOGIC_OP_EXT { - extensions: [ext_extended_dynamic_state2], + device_extensions: [ext_extended_dynamic_state2], }, // TODO: document ColorWriteEnable = COLOR_WRITE_ENABLE_EXT { - extensions: [ext_color_write_enable], + device_extensions: [ext_color_write_enable], }, } diff --git a/vulkano/src/query.rs b/vulkano/src/query.rs index e0cda43f66..cafc226ec4 100644 --- a/vulkano/src/query.rs +++ b/vulkano/src/query.rs @@ -15,13 +15,13 @@ use crate::{ device::{Device, DeviceOwned}, - macros::{vulkan_bitflags, ExtensionNotEnabled}, - DeviceSize, OomError, VulkanError, VulkanObject, + macros::vulkan_bitflags, + DeviceSize, OomError, RequirementNotMet, RequiresOneOf, VulkanError, VulkanObject, }; use std::{ error::Error, ffi::c_void, - fmt, + fmt::{Display, Error as FmtError, Formatter}, hash::{Hash, Hasher}, mem::{size_of_val, MaybeUninit}, ops::Range, @@ -255,13 +255,13 @@ impl Error for QueryPoolCreationError { } } -impl fmt::Display for QueryPoolCreationError { +impl Display for QueryPoolCreationError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { write!( - fmt, + f, "{}", - match *self { + match self { QueryPoolCreationError::OomError(_) => "not enough memory available", QueryPoolCreationError::PipelineStatisticsQueryFeatureNotEnabled => { "a pipeline statistics pool was requested but the corresponding feature \ @@ -396,7 +396,7 @@ impl<'a> QueriesRange<'a> { { // VUID-vkGetQueryPoolResults-flags-parameter // VUID-vkCmdCopyQueryPoolResults-flags-parameter - flags.validate(&self.pool.device)?; + flags.validate_device(&self.pool.device)?; assert!(buffer_len > 0); @@ -441,9 +441,9 @@ pub enum GetResultsError { /// Not enough memory. OomError(OomError), - ExtensionNotEnabled { - extension: &'static str, - reason: &'static str, + RequirementNotMet { + required_for: &'static str, + requires_one_of: RequiresOneOf, }, /// The buffer is too small for the operation. @@ -468,15 +468,21 @@ impl Error for GetResultsError { } } -impl fmt::Display for GetResultsError { +impl Display for GetResultsError { #[inline] - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match self { Self::OomError(_) => write!(f, "not enough memory available"), Self::DeviceLost => write!(f, "the connection to the device has been lost"), - Self::ExtensionNotEnabled { extension, reason } => { - write!(f, "the extension {} must be enabled: {}", extension, reason) - } + + Self::RequirementNotMet { + required_for, + requires_one_of, + } => write!( + f, + "a requirement was not met for: {}; requires one of: {}", + required_for, requires_one_of, + ), Self::BufferTooSmall { .. } => write!(f, "the buffer is too small for the operation"), Self::InvalidFlags => write!( @@ -507,12 +513,12 @@ impl From for GetResultsError { } } -impl From for GetResultsError { +impl From for GetResultsError { #[inline] - fn from(err: ExtensionNotEnabled) -> Self { - Self::ExtensionNotEnabled { - extension: err.extension, - reason: err.reason, + fn from(err: RequirementNotMet) -> Self { + Self::RequirementNotMet { + required_for: err.required_for, + requires_one_of: err.requires_one_of, } } } @@ -626,12 +632,12 @@ vulkan_bitflags! { /* // TODO: document task_shader_invocations = TASK_SHADER_INVOCATIONS_NV { - extensions: [nv_mesh_shader], + device_extensions: [nv_mesh_shader], }, // TODO: document mesh_shader_invocations = MESH_SHADER_INVOCATIONS_NV { - extensions: [nv_mesh_shader], + device_extensions: [nv_mesh_shader], }, */ } @@ -730,7 +736,7 @@ vulkan_bitflags! { /* // TODO: document with_status = WITH_STATUS_KHR { - extensions: [khr_video_queue], + device_extensions: [khr_video_queue], }, */ } diff --git a/vulkano/src/range_map.rs b/vulkano/src/range_map.rs index 53d3172d8e..581a2f7006 100644 --- a/vulkano/src/range_map.rs +++ b/vulkano/src/range_map.rs @@ -4,7 +4,7 @@ use std::{ cmp, cmp::Ordering, collections::{btree_map, BTreeMap}, - fmt::{self, Debug}, + fmt::{Debug, Error as FmtError, Formatter}, iter::{FromIterator, FusedIterator, Peekable}, ops::{Add, Bound, Range, Sub}, }; @@ -585,7 +585,7 @@ where K: Ord + Clone, V: Eq + Clone, { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { f.debug_map().entries(self.iter()).finish() } } diff --git a/vulkano/src/render_pass/create.rs b/vulkano/src/render_pass/create.rs index 05cefba959..bfa5c7ee4c 100644 --- a/vulkano/src/render_pass/create.rs +++ b/vulkano/src/render_pass/create.rs @@ -14,12 +14,16 @@ use super::{ use crate::{ device::Device, image::{ImageLayout, SampleCount}, - macros::ExtensionNotEnabled, sync::PipelineStages, - OomError, Version, VulkanError, VulkanObject, + OomError, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject, }; use smallvec::SmallVec; -use std::{error::Error, fmt, mem::MaybeUninit, ptr}; +use std::{ + error::Error, + fmt::{Display, Error as FmtError, Formatter}, + mem::MaybeUninit, + ptr, +}; impl RenderPass { pub(super) fn validate( @@ -79,24 +83,24 @@ impl RenderPass { ); // VUID-VkAttachmentDescription2-samples-parameter - samples.validate(device)?; + samples.validate_device(device)?; for load_op in [load_op, stencil_load_op] { // VUID-VkAttachmentDescription2-loadOp-parameter // VUID-VkAttachmentDescription2-stencilLoadOp-parameter - load_op.validate(device)?; + load_op.validate_device(device)?; } for store_op in [store_op, stencil_store_op] { // VUID-VkAttachmentDescription2-storeOp-parameter // VUID-VkAttachmentDescription2-stencilStoreOp-parameter - store_op.validate(device)?; + store_op.validate_device(device)?; } for layout in [initial_layout, final_layout] { // VUID-VkAttachmentDescription2-initialLayout-parameter // VUID-VkAttachmentDescription2-finalLayout-parameter - layout.validate(device)?; + layout.validate_device(device)?; match layout { ImageLayout::ColorAttachmentOptimal => { @@ -134,9 +138,12 @@ impl RenderPass { // VUID-VkSubpassDescription2-multiview-06558 if is_multiview && !device.enabled_features().multiview { - return Err(RenderPassCreationError::FeatureNotEnabled { - feature: "multiview", - reason: "the subpasses specified a nonzero `view_mask`", + return Err(RenderPassCreationError::RequirementNotMet { + required_for: "`create_info.subpasses[0].view_mask` is not `0`", + requires_one_of: RequiresOneOf { + features: &["multiview"], + ..Default::default() + }, }); } @@ -195,10 +202,10 @@ impl RenderPass { // Common checks for all attachment types let mut check_attachment = |atch_ref: &AttachmentReference| { // VUID-VkAttachmentReference2-layout-parameter - atch_ref.layout.validate(device)?; + atch_ref.layout.validate_device(device)?; // VUID? - atch_ref.aspects.validate(device)?; + atch_ref.aspects.validate_device(device)?; // VUID-VkRenderPassCreateInfo2-attachment-03051 let atch = attachments.get(atch_ref.attachment as usize).ok_or( @@ -416,21 +423,14 @@ impl RenderPass { || device.enabled_extensions().khr_create_renderpass2 || device.enabled_extensions().khr_maintenance2) { - if device - .physical_device() - .supported_extensions() - .khr_create_renderpass2 - { - return Err(RenderPassCreationError::ExtensionNotEnabled { - extension: "khr_create_renderpass2", - reason: "an attachment reference selected a subset of the `aspects` of the attachment's format", - }); - } else { - return Err(RenderPassCreationError::ExtensionNotEnabled { - extension: "khr_maintenance2", - reason: "an attachment reference selected a subset of the `aspects` of the attachment's format", - }); - } + return Err(RenderPassCreationError::RequirementNotMet { + required_for: "`create_info.subpasses` has an element, where `input_attachments` has an element that is `Some(atch_ref)`, where `atch_ref.aspects` does not match the aspects of the attachment itself", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_1), + device_extensions: &["khr_create_renderpass2", "khr_maintenance2"], + ..Default::default() + }, + }); } // VUID-VkSubpassDescription2-attachment-02801 @@ -600,18 +600,21 @@ impl RenderPass { ] { // VUID-VkSubpassDependency2-srcStageMask-parameter // VUID-VkSubpassDependency2-dstStageMask-parameter - stages.validate(device)?; + stages.validate_device(device)?; // VUID-VkSubpassDependency2-srcAccessMask-parameter // VUID-VkSubpassDependency2-dstAccessMask-parameter - access.validate(device)?; + access.validate_device(device)?; // VUID-VkSubpassDependency2-srcStageMask-04090 // VUID-VkSubpassDependency2-dstStageMask-04090 if stages.geometry_shader && !device.enabled_features().geometry_shader { - return Err(RenderPassCreationError::FeatureNotEnabled { - feature: "geometry_shader", - reason: "a dependency specified the `geometry_shader` stage", + return Err(RenderPassCreationError::RequirementNotMet { + required_for: "`create_info.dependencies` has an element where `stages.geometry_shader` is set", + requires_one_of: RequiresOneOf { + features: &["geometry_shader"], + ..Default::default() + }, }); } @@ -620,18 +623,25 @@ impl RenderPass { if (stages.tessellation_control_shader || stages.tessellation_evaluation_shader) && !device.enabled_features().tessellation_shader { - return Err(RenderPassCreationError::FeatureNotEnabled { - feature: "tessellation_shader", - reason: "a dependency specified the `tessellation_control_shader` or `tessellation_evaluation_shader` stage", + return Err(RenderPassCreationError::RequirementNotMet { + required_for: "`create_info.dependencies` has an element where `stages.tessellation_control_shader` or `stages.tessellation_evaluation_shader` are set", + requires_one_of: RequiresOneOf { + features: &["tessellation_shader"], + ..Default::default() + }, }); } // VUID-VkSubpassDependency2-srcStageMask-03937 // VUID-VkSubpassDependency2-dstStageMask-03937 if stages.is_empty() && !device.enabled_features().synchronization2 { - return Err(RenderPassCreationError::FeatureNotEnabled { - feature: "synchronization2", - reason: "a dependency specified no shader stages", + return Err(RenderPassCreationError::RequirementNotMet { + required_for: + "`create_info.dependencies` has an element where `stages` is empty", + requires_one_of: RequiresOneOf { + features: &["synchronization2"], + ..Default::default() + }, }); } @@ -1367,13 +1377,9 @@ pub enum RenderPassCreationError { /// Not enough memory. OomError(OomError), - ExtensionNotEnabled { - extension: &'static str, - reason: &'static str, - }, - FeatureNotEnabled { - feature: &'static str, - reason: &'static str, + RequirementNotMet { + required_for: &'static str, + requires_one_of: RequiresOneOf, }, /// An attachment is first used in the render pass with a read-only layout or as an input @@ -1541,74 +1547,76 @@ impl Error for RenderPassCreationError { } } -impl fmt::Display for RenderPassCreationError { +impl Display for RenderPassCreationError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match *self { - Self::OomError(_) => write!(fmt, "not enough memory available",), - Self::ExtensionNotEnabled { extension, reason } => write!( - fmt, - "the extension {} must be enabled: {}", - extension, reason + Self::OomError(_) => write!(f, "not enough memory available",), + + Self::RequirementNotMet { + required_for, + requires_one_of, + } => write!( + f, + "a requirement was not met for: {}; requires one of: {}", + required_for, requires_one_of, ), - Self::FeatureNotEnabled { feature, reason } => { - write!(fmt, "the feature {} must be enabled: {}", feature, reason) - } + Self::AttachmentFirstUseLoadOpInvalid { attachment, first_use_subpass } => write!( - fmt, + f, "attachment {} is first used in the render pass in subpass {} with a read-only layout or as an input attachment, but its `load_op` or `stencil_load_op` is `LoadOp::Clear`", attachment, first_use_subpass, ), Self::AttachmentLayoutInvalid { attachment } => write!( - fmt, + f, "attachment {} has an `initial_layout` or `final_layout` value that is invalid for the provided `format`", attachment, ), Self::CorrelatedViewMasksMultiviewNotEnabled => write!( - fmt, + f, "correlated view masks were included, but multiview is not enabled on the render pass", ), Self::CorrelatedViewMasksOverlapping => write!( - fmt, + f, "the provided correlated view masks contain a bit that is set in more than one element", ), Self::DependencyAccessNotSupportedByStages { dependency } => write!( - fmt, + f, "subpass dependency {} specified an access type that was not supported by the given stages", dependency, ), Self::DependencySelfDependencyFramebufferStagesWithoutByRegion { dependency } => write!( - fmt, + f, "subpass dependency {} specifies a subpass self-dependency and includes framebuffer stages in both `source_stages` and `destination_stages`, but the `by_region` dependency was not enabled", dependency, ), Self::DependencySelfDependencySourceStageAfterDestinationStage { dependency } => write!( - fmt, + f, "subpass dependency {} specifies a subpass self-dependency and includes non-framebuffer stages, but the latest stage in `source_stages` is after the earliest stage in `destination_stages`", dependency, ), Self::DependencySelfDependencyViewLocalNonzeroOffset { dependency } => write!( - fmt, + f, "subpass dependency {} specifies a subpass self-dependency and has the `view_local` dependency enabled, but the inner offset value was not 0", dependency, ), Self::DependencySelfDependencyViewMaskMultiple { dependency, subpass } => write!( - fmt, + f, "subpass dependency {} specifies a subpass self-dependency without the `view_local` dependency, but the referenced subpass {} has more than one bit set in its `view_mask`", dependency, subpass, ), Self::DependencySourceSubpassAfterDestinationSubpass { dependency } => write!( - fmt, + f, "subpass dependency {} has a `source_subpass` that is later than the `destination_subpass`", dependency, ), Self::DependencyStageNotSupported { dependency } => write!( - fmt, + f, "subpass dependency {} has a bit set in the `source_stages` or `destination_stages` that is not supported for graphics pipelines", dependency, ), Self::DependencyBothSubpassesExternal { dependency } => write!( - fmt, + f, "subpass dependency {} has both `source_subpass` and `destination_subpass` set to `None`", dependency, ), @@ -1616,27 +1624,27 @@ impl fmt::Display for RenderPassCreationError { dependency, subpass, } => write!( - fmt, + f, "the subpass index {} in subpass dependency {} is not less than the number of subpasses in the render pass", subpass, dependency, ), Self::DependencyViewLocalExternalDependency { dependency } => write!( - fmt, + f, "subpass dependency {} has the `view_local` dependency enabled, but `source_subpass` or `destination_subpass` were set to `None`", dependency, ), Self::DependencyViewLocalMultiviewNotEnabled { dependency } => write!( - fmt, + f, "subpass dependency {} has the `view_local` dependency enabled, but multiview is not enabled on the render pass", dependency, ), Self::SubpassAttachmentAspectsNotEmpty { subpass, attachment } => write!( - fmt, + f, "a reference to attachment {} used other than as an input attachment in subpass {} has one or more aspects selected", attachment, subpass, ), Self::SubpassAttachmentLayoutMismatch { subpass, attachment } => write!( - fmt, + f, "the layouts of all uses of attachment {} in subpass {} do not match.", attachment, subpass, ), @@ -1645,27 +1653,27 @@ impl fmt::Display for RenderPassCreationError { attachment, usage, } => write!( - fmt, + f, "attachment {} used as {} attachment in subpass {} has a layout that is not supported for that usage", attachment, usage, subpass, ), Self::SubpassAttachmentOutOfRange { subpass, attachment } => write!( - fmt, + f, "the attachment index {} in subpass {} is not less than the number of attachments in the render pass", attachment, subpass, ), Self::SubpassAttachmentUsageColorDepthStencil { subpass, attachment } => write!( - fmt, + f, "attachment {} is used as both a color attachment and a depth/stencil attachment in subpass {}", attachment, subpass, ), Self::SubpassAttachmentFormatUsageNotSupported { subpass, attachment, usage, } => write!( - fmt, + f, "attachment {} used as {} attachment in subpass {} has a format that does not support that usage", attachment, usage, subpass, ), Self::SubpassColorAttachmentWithResolveNotMultisampled { subpass, attachment } => write!( - fmt, + f, "attachment {} used as a color attachment in subpass {} with resolve attachments has a `samples` value of `SampleCount::Sample1`", attachment, subpass, ), @@ -1675,37 +1683,37 @@ impl fmt::Display for RenderPassCreationError { samples, first_samples, } => write!( - fmt, + f, "attachment {} used as a color or depth/stencil attachment in subpass {} has a `samples` value {:?} that is different from the first color attachment ({:?})", attachment, subpass, samples, first_samples, ), Self::SubpassInputAttachmentAspectsNotCompatible { subpass, attachment } => write!( - fmt, + f, "a reference to attachment {} used as an input attachment in subpass {} selects aspects that are not present in the format of the attachment", attachment, subpass, ), Self::SubpassMaxColorAttachmentsExceeded { .. } => { - write!(fmt, "the `max_color_attachments` limit has been exceeded",) + write!(f, "the `max_color_attachments` limit has been exceeded",) } Self::SubpassMaxMultiviewViewCountExceeded { .. } => { - write!(fmt, "the `max_multiview_view_count` limit has been exceeded for a subpass",) + write!(f, "the `max_multiview_view_count` limit has been exceeded for a subpass",) }, Self::SubpassMultiviewMismatch { subpass, multiview, first_subpass_multiview, } => write!( - fmt, + f, "the multiview state (whether `view_mask` is nonzero) of subpass {} is {}, which is different from the first subpass ({})", subpass, multiview, first_subpass_multiview, ), Self::SubpassPreserveAttachmentUsedElsewhere { subpass, attachment } => write!( - fmt, + f, "attachment {} marked as a preserve attachment in subpass {} is also used as an attachment in that subpass", attachment, subpass, ), Self::SubpassResolveAttachmentsColorAttachmentsLenMismatch { subpass } => write!( - fmt, + f, "the `resolve_attachments` field of subpass {} was not empty, but its length did not match the length of `color_attachments`", subpass, ), @@ -1714,17 +1722,17 @@ impl fmt::Display for RenderPassCreationError { resolve_attachment, color_attachment, } => write!( - fmt, + f, "attachment {} used as a resolve attachment in subpass {} has a `format` value different from the corresponding color attachment {}", subpass, resolve_attachment, color_attachment, ), Self::SubpassResolveAttachmentMultisampled { subpass, attachment } => write!( - fmt, + f, "attachment {} used as a resolve attachment in subpass {} has a `samples` value other than `SampleCount::Sample1`", attachment, subpass, ), Self::SubpassResolveAttachmentWithoutColorAttachment { subpass } => write!( - fmt, + f, "a resolve attachment in subpass {} is `Some`, but the corresponding color attachment is `None`", subpass, ), @@ -1754,12 +1762,12 @@ impl From for RenderPassCreationError { } } -impl From for RenderPassCreationError { +impl From for RenderPassCreationError { #[inline] - fn from(err: ExtensionNotEnabled) -> Self { - Self::ExtensionNotEnabled { - extension: err.extension, - reason: err.reason, + fn from(err: RequirementNotMet) -> Self { + Self::RequirementNotMet { + required_for: err.required_for, + requires_one_of: err.requires_one_of, } } } diff --git a/vulkano/src/render_pass/framebuffer.rs b/vulkano/src/render_pass/framebuffer.rs index 4eaae05c01..58f5fb82cf 100644 --- a/vulkano/src/render_pass/framebuffer.rs +++ b/vulkano/src/render_pass/framebuffer.rs @@ -17,7 +17,7 @@ use crate::{ use smallvec::SmallVec; use std::{ error::Error, - fmt, + fmt::{Display, Error as FmtError, Formatter}, hash::{Hash, Hasher}, mem::MaybeUninit, ops::Range, @@ -602,26 +602,26 @@ impl Error for FramebufferCreationError { } } -impl fmt::Display for FramebufferCreationError { +impl Display for FramebufferCreationError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match *self { Self::OomError(_) => write!( - fmt, + f, "no memory available", ), Self::Attachment2dArrayCompatibleDepthStencil { attachment } => write!( - fmt, + f, "attachment image {} is a 2D image view created from a 3D image, and has a depth/stencil format", attachment, ), Self::AttachmentComponentMappingNotIdentity { attachment } => write!( - fmt, + f, "attachment image {} has a non-identity component mapping", attachment, ), Self::AttachmentCountMismatch { .. } => write!( - fmt, + f, "the number of attachments doesn't match the number expected by the render pass", ), Self::AttachmentExtentTooSmall { @@ -629,7 +629,7 @@ impl fmt::Display for FramebufferCreationError { provided, min, } => write!( - fmt, + f, "attachment image {} has an extent ({:?}) smaller than the provided `extent` ({:?})", attachment, provided, min, ), @@ -638,7 +638,7 @@ impl fmt::Display for FramebufferCreationError { provided, required, } => write!( - fmt, + f, "attachment image {} has a `format` ({:?}) different from what the render pass requires ({:?})", attachment, provided, required, ), @@ -646,14 +646,14 @@ impl fmt::Display for FramebufferCreationError { attachment, usage, } => write!( - fmt, + f, "attachment image {} is missing usage `{}` that the render pass requires it to have", attachment, usage, ), Self::AttachmentMultipleMipLevels { attachment, } => write!( - fmt, + f, "attachment image {} has multiple mip levels", attachment, ), @@ -662,7 +662,7 @@ impl fmt::Display for FramebufferCreationError { provided, min, } => write!( - fmt, + f, "attachment image {} has less layers ({}) than the provided `layers` ({})", attachment, provided, min, ), @@ -671,32 +671,32 @@ impl fmt::Display for FramebufferCreationError { provided, required, } => write!( - fmt, + f, "attachment image {} has a `samples` ({:?}) different from what the render pass requires ({:?})", attachment, provided, required, ), Self::AttachmentViewType3d { attachment, } => write!( - fmt, + f, "attachment image {} has a `ty` of `ImageViewType::Dim3d`", attachment, ), Self::AutoExtentAttachmentsEmpty => write!( - fmt, + f, "one of the elements of `extent` is zero, but no attachment images were given to calculate the extent from", ), Self::AutoLayersAttachmentsEmpty => write!( - fmt, + f, "`layers` is zero, but no attachment images were given to calculate the number of layers from", ), Self::MaxFramebufferExtentExceeded { provided, max } => write!( - fmt, + f, "the provided `extent` ({:?}) exceeds the `max_framebuffer_width` or `max_framebuffer_height` limits ({:?})", provided, max, ), Self::MaxFramebufferLayersExceeded { provided, max } => write!( - fmt, + f, "the provided `layers` ({}) exceeds the `max_framebuffer_layers` limit ({})", provided, max, ), @@ -705,12 +705,12 @@ impl fmt::Display for FramebufferCreationError { provided, min, } => write!( - fmt, + f, "the render pass has multiview enabled, and attachment image {} has less layers ({}) than the number of views in the render pass ({})", attachment, provided, min, ), Self::MultiviewLayersInvalid => write!( - fmt, + f, "the render pass has multiview enabled, but `layers` was not 0 or 1", ), } diff --git a/vulkano/src/render_pass/mod.rs b/vulkano/src/render_pass/mod.rs index 3755450324..aaa1097185 100644 --- a/vulkano/src/render_pass/mod.rs +++ b/vulkano/src/render_pass/mod.rs @@ -1124,7 +1124,7 @@ vulkan_enum! { /* // TODO: document None = NONE_EXT { - extensions: [ext_load_store_op_none], + device_extensions: [ext_load_store_op_none], }, */ } @@ -1155,7 +1155,7 @@ vulkan_enum! { // TODO: document None = NONE { api_version: V1_3, - extensions: [ext_load_store_op_none], + device_extensions: [ext_load_store_op_none], }, */ } diff --git a/vulkano/src/sampler/mod.rs b/vulkano/src/sampler/mod.rs index 13318ab1df..aab702db8e 100644 --- a/vulkano/src/sampler/mod.rs +++ b/vulkano/src/sampler/mod.rs @@ -50,14 +50,14 @@ use self::ycbcr::SamplerYcbcrConversion; use crate::{ device::{Device, DeviceOwned}, image::{view::ImageViewType, ImageViewAbstract}, - macros::{vulkan_enum, ExtensionNotEnabled}, + macros::vulkan_enum, pipeline::graphics::depth_stencil::CompareOp, shader::ShaderScalarType, - OomError, VulkanError, VulkanObject, + OomError, RequirementNotMet, RequiresOneOf, VulkanError, VulkanObject, }; use std::{ error::Error, - fmt, + fmt::{Display, Error as FmtError, Formatter}, hash::{Hash, Hasher}, mem::MaybeUninit, ops::RangeInclusive, @@ -143,46 +143,36 @@ impl Sampler { for filter in [mag_filter, min_filter] { // VUID-VkSamplerCreateInfo-magFilter-parameter // VUID-VkSamplerCreateInfo-minFilter-parameter - filter.validate(&device)?; + filter.validate_device(&device)?; } // VUID-VkSamplerCreateInfo-mipmapMode-parameter - mipmap_mode.validate(&device)?; + mipmap_mode.validate_device(&device)?; for mode in address_mode { // VUID-VkSamplerCreateInfo-addressModeU-parameter // VUID-VkSamplerCreateInfo-addressModeV-parameter // VUID-VkSamplerCreateInfo-addressModeW-parameter - mode.validate(&device)?; + mode.validate_device(&device)?; if mode == SamplerAddressMode::ClampToBorder { // VUID-VkSamplerCreateInfo-addressModeU-01078 - border_color.validate(&device)?; + border_color.validate_device(&device)?; } } - if address_mode - .into_iter() - .any(|mode| mode == SamplerAddressMode::MirrorClampToEdge) - { + if address_mode.contains(&SamplerAddressMode::MirrorClampToEdge) { if !device.enabled_features().sampler_mirror_clamp_to_edge && !device.enabled_extensions().khr_sampler_mirror_clamp_to_edge { - if device - .physical_device() - .supported_features() - .sampler_mirror_clamp_to_edge - { - return Err(SamplerCreationError::FeatureNotEnabled { - feature: "sampler_mirror_clamp_to_edge", - reason: "one or more address modes were MirrorClampToEdge", - }); - } else { - return Err(SamplerCreationError::ExtensionNotEnabled { - extension: "khr_sampler_mirror_clamp_to_edge", - reason: "one or more address modes were MirrorClampToEdge", - }); - } + return Err(SamplerCreationError::RequirementNotMet { + required_for: "`create_info.address_mode` contains `SamplerAddressMode::MirrorClampToEdge`", + requires_one_of: RequiresOneOf { + features: &["sampler_mirror_clamp_to_edge"], + device_extensions: &["khr_sampler_mirror_clamp_to_edge"], + ..Default::default() + }, + }); } } @@ -201,9 +191,12 @@ impl Sampler { assert!(max_anisotropy >= 1.0); if !device.enabled_features().sampler_anisotropy { - return Err(SamplerCreationError::FeatureNotEnabled { - feature: "sampler_anisotropy", - reason: "anisotropy was set to `Some`", + return Err(SamplerCreationError::RequirementNotMet { + required_for: "`create_info.anisotropy` is `Some`", + requires_one_of: RequiresOneOf { + features: &["sampler_anisotropy"], + ..Default::default() + }, }); } @@ -232,7 +225,7 @@ impl Sampler { let (compare_enable, compare_op) = if let Some(compare_op) = compare { // VUID-VkSamplerCreateInfo-compareEnable-01080 - compare_op.validate(&device)?; + compare_op.validate_device(&device)?; if reduction_mode != SamplerReductionMode::WeightedAverage { return Err(SamplerCreationError::CompareInvalidReductionMode { reduction_mode }); @@ -285,38 +278,32 @@ impl Sampler { } } - let mut sampler_reduction_mode_create_info = - if reduction_mode != SamplerReductionMode::WeightedAverage { - if !(device.enabled_features().sampler_filter_minmax - || device.enabled_extensions().ext_sampler_filter_minmax) - { - if device - .physical_device() - .supported_features() - .sampler_filter_minmax - { - return Err(SamplerCreationError::FeatureNotEnabled { - feature: "sampler_filter_minmax", - reason: "reduction_mode was not WeightedAverage", - }); - } else { - return Err(SamplerCreationError::ExtensionNotEnabled { - extension: "ext_sampler_filter_minmax", - reason: "reduction_mode was not WeightedAverage", - }); - } - } + let mut sampler_reduction_mode_create_info = if reduction_mode + != SamplerReductionMode::WeightedAverage + { + if !(device.enabled_features().sampler_filter_minmax + || device.enabled_extensions().ext_sampler_filter_minmax) + { + return Err(SamplerCreationError::RequirementNotMet { + required_for: "`create_info.reduction_mode` is not `SamplerReductionMode::WeightedAverage`", + requires_one_of: RequiresOneOf { + features: &["sampler_filter_minmax"], + device_extensions: &["ext_sampler_filter_minmax"], + ..Default::default() + }, + }); + } - // VUID-VkSamplerReductionModeCreateInfo-reductionMode-parameter - reduction_mode.validate(&device)?; + // VUID-VkSamplerReductionModeCreateInfo-reductionMode-parameter + reduction_mode.validate_device(&device)?; - Some(ash::vk::SamplerReductionModeCreateInfo { - reduction_mode: reduction_mode.into(), - ..Default::default() - }) - } else { - None - }; + Some(ash::vk::SamplerReductionModeCreateInfo { + reduction_mode: reduction_mode.into(), + ..Default::default() + }) + } else { + None + }; // Don't need to check features because you can't create a conversion object without the // feature anyway. @@ -780,13 +767,9 @@ pub enum SamplerCreationError { /// Note the specs guarantee that at least 4000 samplers can exist simultaneously. TooManyObjects, - ExtensionNotEnabled { - extension: &'static str, - reason: &'static str, - }, - FeatureNotEnabled { - feature: &'static str, - reason: &'static str, + RequirementNotMet { + required_for: &'static str, + requires_one_of: RequiresOneOf, }, /// Anisotropy was enabled with an invalid filter. @@ -878,59 +861,61 @@ impl Error for SamplerCreationError { } } -impl fmt::Display for SamplerCreationError { +impl Display for SamplerCreationError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match *self { - Self::OomError(_) => write!(fmt, "not enough memory available"), - Self::TooManyObjects => write!(fmt, "too many simultaneous sampler objects",), - Self::ExtensionNotEnabled { extension, reason } => write!( - fmt, - "the extension {} must be enabled: {}", - extension, reason + Self::OomError(_) => write!(f, "not enough memory available"), + Self::TooManyObjects => write!(f, "too many simultaneous sampler objects",), + + Self::RequirementNotMet { + required_for, + requires_one_of, + } => write!( + f, + "a requirement was not met for: {}; requires one of: {}", + required_for, requires_one_of, ), - Self::FeatureNotEnabled { feature, reason } => { - write!(fmt, "the feature {} must be enabled: {}", feature, reason) - } - Self::AnisotropyInvalidFilter { .. } => write!(fmt, "anisotropy was enabled with an invalid filter"), - Self::CompareInvalidReductionMode { .. } => write!(fmt, "depth comparison was enabled with an invalid reduction mode"), + + Self::AnisotropyInvalidFilter { .. } => write!(f, "anisotropy was enabled with an invalid filter"), + Self::CompareInvalidReductionMode { .. } => write!(f, "depth comparison was enabled with an invalid reduction mode"), Self::MaxSamplerAnisotropyExceeded { .. } => { - write!(fmt, "max_sampler_anisotropy limit exceeded") + write!(f, "max_sampler_anisotropy limit exceeded") } - Self::MaxSamplerLodBiasExceeded { .. } => write!(fmt, "mip lod bias limit exceeded"), + Self::MaxSamplerLodBiasExceeded { .. } => write!(f, "mip lod bias limit exceeded"), Self::SamplerYcbcrConversionAnisotropyEnabled => write!( - fmt, + f, "sampler YCbCr conversion was enabled together with anisotropy" ), - Self::SamplerYcbcrConversionChromaFilterMismatch { .. } => write!(fmt, "sampler YCbCr conversion was enabled, and its format does not support `sampled_image_ycbcr_conversion_separate_reconstruction_filter`, but `mag_filter` or `min_filter` did not match the conversion's `chroma_filter`"), - Self::SamplerYcbcrConversionInvalidAddressMode { .. } => write!(fmt, "sampler YCbCr conversion was enabled, but the address mode for u, v or w was something other than `ClampToEdge`"), - Self::SamplerYcbcrConversionInvalidReductionMode { .. } => write!(fmt, "sampler YCbCr conversion was enabled, but the reduction mode was something other than `WeightedAverage`"), + Self::SamplerYcbcrConversionChromaFilterMismatch { .. } => write!(f, "sampler YCbCr conversion was enabled, and its format does not support `sampled_image_ycbcr_conversion_separate_reconstruction_filter`, but `mag_filter` or `min_filter` did not match the conversion's `chroma_filter`"), + Self::SamplerYcbcrConversionInvalidAddressMode { .. } => write!(f, "sampler YCbCr conversion was enabled, but the address mode for u, v or w was something other than `ClampToEdge`"), + Self::SamplerYcbcrConversionInvalidReductionMode { .. } => write!(f, "sampler YCbCr conversion was enabled, but the reduction mode was something other than `WeightedAverage`"), Self::SamplerYcbcrConversionUnnormalizedCoordinatesEnabled => write!( - fmt, + f, "sampler YCbCr conversion was enabled together with unnormalized coordinates" ), Self::UnnormalizedCoordinatesAnisotropyEnabled => write!( - fmt, + f, "unnormalized coordinates were enabled together with anisotropy" ), Self::UnnormalizedCoordinatesCompareEnabled => write!( - fmt, + f, "unnormalized coordinates were enabled together with depth comparison" ), Self::UnnormalizedCoordinatesFiltersNotEqual { .. } => write!( - fmt, + f, "unnormalized coordinates were enabled, but the min and mag filters were not equal" ), Self::UnnormalizedCoordinatesInvalidAddressMode { .. } => write!( - fmt, + f, "unnormalized coordinates were enabled, but the address mode for u or v was something other than `ClampToEdge` or `ClampToBorder`" ), Self::UnnormalizedCoordinatesInvalidMipmapMode { .. } => write!( - fmt, + f, "unnormalized coordinates were enabled, but the mipmap mode was not `Nearest`" ), Self::UnnormalizedCoordinatesNonzeroLod { .. } => write!( - fmt, + f, "unnormalized coordinates were enabled, but the LOD range was not zero" ), } @@ -956,12 +941,12 @@ impl From for SamplerCreationError { } } -impl From for SamplerCreationError { +impl From for SamplerCreationError { #[inline] - fn from(err: ExtensionNotEnabled) -> Self { - Self::ExtensionNotEnabled { - extension: err.extension, - reason: err.reason, + fn from(err: RequirementNotMet) -> Self { + Self::RequirementNotMet { + required_for: err.required_for, + requires_one_of: err.requires_one_of, } } } @@ -1318,7 +1303,7 @@ vulkan_enum! { /// be enabled on the device, and anisotropy must be disabled. Sampled image views must have /// a type of [`Dim2d`](crate::image::view::ImageViewType::Dim2d). Cubic = CUBIC_EXT { - extensions: [ext_filter_cubic, img_filter_cubic], + device_extensions: [ext_filter_cubic, img_filter_cubic], }, } @@ -1372,7 +1357,7 @@ vulkan_enum! { /// extension must be enabled on the device. MirrorClampToEdge = MIRROR_CLAMP_TO_EDGE { api_version: V1_2, - extensions: [khr_sampler_mirror_clamp_to_edge], + device_extensions: [khr_sampler_mirror_clamp_to_edge], }, } @@ -1407,12 +1392,12 @@ vulkan_enum! { /* // TODO: document FloatCustom = VK_BORDER_COLOR_FLOAT_CUSTOM_EXT { - extensions: [ext_custom_border_color], + device_extensions: [ext_custom_border_color], }, // TODO: document IntCustom = INT_CUSTOM_EXT { - extensions: [ext_custom_border_color], + device_extensions: [ext_custom_border_color], }, */ } @@ -1485,19 +1470,19 @@ pub enum SamplerImageViewIncompatibleError { impl Error for SamplerImageViewIncompatibleError {} -impl fmt::Display for SamplerImageViewIncompatibleError { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { +impl Display for SamplerImageViewIncompatibleError { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match self { - Self::BorderColorFormatNotCompatible => write!(fmt, "the sampler has a border color with a numeric type different from the image view"), - Self::BorderColorOpaqueBlackNotIdentitySwizzled => write!(fmt, "the sampler has an opaque black border color, but the image view is not identity swizzled"), - Self::DepthComparisonNotSupported => write!(fmt, "the sampler has depth comparison enabled, but this is not supported by the image view"), - Self::DepthComparisonWrongAspect => write!(fmt, "the sampler has depth comparison enabled, but the image view does not select the `depth` aspect"), - Self::FilterLinearNotSupported => write!(fmt, "the sampler uses a linear filter, but this is not supported by the image view's format features"), - Self::FilterCubicNotSupported => write!(fmt, "the sampler uses a cubic filter, but this is not supported by the image view's format features"), - Self::FilterCubicMinmaxNotSupported => write!(fmt, "the sampler uses a cubic filter with a `Min` or `Max` reduction mode, but this is not supported by the image view's format features"), - Self::MipmapModeLinearNotSupported => write!(fmt, "the sampler uses a linear mipmap mode, but this is not supported by the image view's format features"), - Self::UnnormalizedCoordinatesMultipleMipLevels => write!(fmt, "the sampler uses unnormalized coordinates, but the image view has multiple mip levels"), - Self::UnnormalizedCoordinatesViewTypeNotCompatible => write!(fmt, "the sampler uses unnormalized coordinates, but the image view has a type other than `Dim1d` or `Dim2d`"), + Self::BorderColorFormatNotCompatible => write!(f, "the sampler has a border color with a numeric type different from the image view"), + Self::BorderColorOpaqueBlackNotIdentitySwizzled => write!(f, "the sampler has an opaque black border color, but the image view is not identity swizzled"), + Self::DepthComparisonNotSupported => write!(f, "the sampler has depth comparison enabled, but this is not supported by the image view"), + Self::DepthComparisonWrongAspect => write!(f, "the sampler has depth comparison enabled, but the image view does not select the `depth` aspect"), + Self::FilterLinearNotSupported => write!(f, "the sampler uses a linear filter, but this is not supported by the image view's format features"), + Self::FilterCubicNotSupported => write!(f, "the sampler uses a cubic filter, but this is not supported by the image view's format features"), + Self::FilterCubicMinmaxNotSupported => write!(f, "the sampler uses a cubic filter with a `Min` or `Max` reduction mode, but this is not supported by the image view's format features"), + Self::MipmapModeLinearNotSupported => write!(f, "the sampler uses a linear mipmap mode, but this is not supported by the image view's format features"), + Self::UnnormalizedCoordinatesMultipleMipLevels => write!(f, "the sampler uses unnormalized coordinates, but the image view has multiple mip levels"), + Self::UnnormalizedCoordinatesViewTypeNotCompatible => write!(f, "the sampler uses unnormalized coordinates, but the image view has a type other than `Dim1d` or `Dim2d`"), } } } @@ -1510,6 +1495,7 @@ mod tests { Filter, Sampler, SamplerAddressMode, SamplerCreateInfo, SamplerCreationError, SamplerReductionMode, }, + RequiresOneOf, }; #[test] @@ -1640,10 +1626,10 @@ mod tests { ); match r { - Err(SamplerCreationError::FeatureNotEnabled { - feature: "sampler_anisotropy", + Err(SamplerCreationError::RequirementNotMet { + requires_one_of: RequiresOneOf { features, .. }, .. - }) => (), + }) if features.contains(&"sampler_anisotropy") => (), _ => panic!(), } } @@ -1710,16 +1696,16 @@ mod tests { ); match r { - Err( - SamplerCreationError::FeatureNotEnabled { - feature: "sampler_mirror_clamp_to_edge", - .. - } - | SamplerCreationError::ExtensionNotEnabled { - extension: "khr_sampler_mirror_clamp_to_edge", - .. - }, - ) => (), + Err(SamplerCreationError::RequirementNotMet { + requires_one_of: + RequiresOneOf { + features, + device_extensions, + .. + }, + .. + }) if features.contains(&"sampler_mirror_clamp_to_edge") + && device_extensions.contains(&"khr_sampler_mirror_clamp_to_edge") => {} _ => panic!(), } } @@ -1739,16 +1725,16 @@ mod tests { ); match r { - Err( - SamplerCreationError::FeatureNotEnabled { - feature: "sampler_filter_minmax", - .. - } - | SamplerCreationError::ExtensionNotEnabled { - extension: "ext_sampler_filter_minmax", - .. - }, - ) => (), + Err(SamplerCreationError::RequirementNotMet { + requires_one_of: + RequiresOneOf { + features, + device_extensions, + .. + }, + .. + }) if features.contains(&"sampler_filter_minmax") + && device_extensions.contains(&"ext_sampler_filter_minmax") => {} _ => panic!(), } } diff --git a/vulkano/src/sampler/ycbcr.rs b/vulkano/src/sampler/ycbcr.rs index 841363c14f..cfc7209a74 100644 --- a/vulkano/src/sampler/ycbcr.rs +++ b/vulkano/src/sampler/ycbcr.rs @@ -87,13 +87,13 @@ use crate::{ device::{Device, DeviceOwned}, format::{ChromaSampling, Format, NumericType}, - macros::{vulkan_enum, ExtensionNotEnabled}, + macros::vulkan_enum, sampler::{ComponentMapping, ComponentSwizzle, Filter}, - OomError, Version, VulkanError, VulkanObject, + OomError, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject, }; use std::{ error::Error, - fmt, + fmt::{Display, Error as FmtError, Formatter}, hash::{Hash, Hasher}, mem::MaybeUninit, ptr, @@ -136,38 +136,41 @@ impl SamplerYcbcrConversion { } = create_info; if !device.enabled_features().sampler_ycbcr_conversion { - return Err(SamplerYcbcrConversionCreationError::FeatureNotEnabled { - feature: "sampler_ycbcr_conversion", - reason: "tried to create a SamplerYcbcrConversion", + return Err(SamplerYcbcrConversionCreationError::RequirementNotMet { + required_for: "`SamplerYcbcrConversion`", + requires_one_of: RequiresOneOf { + features: &["sampler_ycbcr_conversion"], + ..Default::default() + }, }); } // VUID-VkSamplerYcbcrConversionCreateInfo-ycbcrModel-parameter - ycbcr_model.validate(&device)?; + ycbcr_model.validate_device(&device)?; // VUID-VkSamplerYcbcrConversionCreateInfo-ycbcrRange-parameter - ycbcr_range.validate(&device)?; + ycbcr_range.validate_device(&device)?; // VUID-VkComponentMapping-r-parameter - component_mapping.r.validate(&device)?; + component_mapping.r.validate_device(&device)?; // VUID-VkComponentMapping-g-parameter - component_mapping.g.validate(&device)?; + component_mapping.g.validate_device(&device)?; // VUID-VkComponentMapping-b-parameter - component_mapping.b.validate(&device)?; + component_mapping.b.validate_device(&device)?; // VUID-VkComponentMapping-a-parameter - component_mapping.a.validate(&device)?; + component_mapping.a.validate_device(&device)?; for offset in chroma_offset { // VUID-VkSamplerYcbcrConversionCreateInfo-xChromaOffset-parameter // VUID-VkSamplerYcbcrConversionCreateInfo-yChromaOffset-parameter - offset.validate(&device)?; + offset.validate_device(&device)?; } // VUID-VkSamplerYcbcrConversionCreateInfo-chromaFilter-parameter - chroma_filter.validate(&device)?; + chroma_filter.validate_device(&device)?; let format = match format { Some(f) => f, @@ -508,13 +511,9 @@ pub enum SamplerYcbcrConversionCreationError { /// Not enough memory. OomError(OomError), - ExtensionNotEnabled { - extension: &'static str, - reason: &'static str, - }, - FeatureNotEnabled { - feature: &'static str, - reason: &'static str, + RequirementNotMet { + required_for: &'static str, + requires_one_of: RequiresOneOf, }, /// The `Cubic` filter was specified. @@ -559,17 +558,20 @@ impl Error for SamplerYcbcrConversionCreationError { } } -impl fmt::Display for SamplerYcbcrConversionCreationError { +impl Display for SamplerYcbcrConversionCreationError { #[inline] - fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match *self { Self::OomError(_) => write!(f, "not enough memory available"), - Self::ExtensionNotEnabled { extension, reason } => { - write!(f, "the extension {} must be enabled: {}", extension, reason) - } - Self::FeatureNotEnabled { feature, reason } => { - write!(f, "the feature {} must be enabled: {}", feature, reason) - } + + Self::RequirementNotMet { + required_for, + requires_one_of, + } => write!( + f, + "a requirement was not met for: {}; requires one of: {}", + required_for, requires_one_of, + ), Self::CubicFilterNotSupported => { write!(f, "the `Cubic` filter was specified") @@ -636,12 +638,12 @@ impl From for SamplerYcbcrConversionCreationError { } } -impl From for SamplerYcbcrConversionCreationError { +impl From for SamplerYcbcrConversionCreationError { #[inline] - fn from(err: ExtensionNotEnabled) -> Self { - Self::ExtensionNotEnabled { - extension: err.extension, - reason: err.reason, + fn from(err: RequirementNotMet) -> Self { + Self::RequirementNotMet { + required_for: err.required_for, + requires_one_of: err.requires_one_of, } } } @@ -790,6 +792,7 @@ vulkan_enum! { #[cfg(test)] mod tests { use super::{SamplerYcbcrConversion, SamplerYcbcrConversionCreationError}; + use crate::RequiresOneOf; #[test] fn feature_not_enabled() { @@ -798,10 +801,10 @@ mod tests { let r = SamplerYcbcrConversion::new(device, Default::default()); match r { - Err(SamplerYcbcrConversionCreationError::FeatureNotEnabled { - feature: "sampler_ycbcr_conversion", + Err(SamplerYcbcrConversionCreationError::RequirementNotMet { + requires_one_of: RequiresOneOf { features, .. }, .. - }) => (), + }) if features.contains(&"sampler_ycbcr_conversion") => (), _ => panic!(), } } diff --git a/vulkano/src/shader/mod.rs b/vulkano/src/shader/mod.rs index 871c0fea09..2348b727e5 100644 --- a/vulkano/src/shader/mod.rs +++ b/vulkano/src/shader/mod.rs @@ -33,8 +33,7 @@ use std::{ collections::{HashMap, HashSet}, error::Error, ffi::{CStr, CString}, - fmt, - fmt::Display, + fmt::{Display, Error as FmtError, Formatter}, mem, mem::MaybeUninit, ptr, @@ -308,7 +307,7 @@ impl Error for ShaderCreationError { } impl Display for ShaderCreationError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match self { Self::OomError(_) => write!(f, "not enough memory available"), Self::SpirvCapabilityNotSupported { capability, .. } => write!( @@ -353,7 +352,7 @@ pub enum ShaderSupportError { impl Error for ShaderSupportError {} impl Display for ShaderSupportError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match self { Self::NotSupportedByVulkan => write!(f, "not supported by Vulkan"), Self::RequirementsNotMet(requirements) => write!( @@ -686,24 +685,24 @@ pub enum DescriptorRequirementsIncompatible { impl Error for DescriptorRequirementsIncompatible {} impl Display for DescriptorRequirementsIncompatible { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match self { DescriptorRequirementsIncompatible::DescriptorType => write!( - fmt, + f, "the allowed descriptor types of the two descriptors do not overlap", ), DescriptorRequirementsIncompatible::ImageFormat => { - write!(fmt, "the descriptors require different formats",) + write!(f, "the descriptors require different formats",) } DescriptorRequirementsIncompatible::ImageMultisampled => write!( - fmt, + f, "the multisampling requirements of the descriptors differ", ), DescriptorRequirementsIncompatible::ImageScalarType => { - write!(fmt, "the descriptors require different scalar types",) + write!(f, "the descriptors require different scalar types",) } DescriptorRequirementsIncompatible::ImageViewType => { - write!(fmt, "the descriptors require different image view types",) + write!(f, "the descriptors require different image view types",) } } } @@ -1020,11 +1019,11 @@ pub enum ShaderInterfaceMismatchError { impl Error for ShaderInterfaceMismatchError {} -impl fmt::Display for ShaderInterfaceMismatchError { +impl Display for ShaderInterfaceMismatchError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { write!( - fmt, + f, "{}", match *self { ShaderInterfaceMismatchError::ElementsCountMismatch { .. } => { @@ -1064,48 +1063,48 @@ vulkan_enum! { // TODO: document Raygen = RAYGEN_KHR { - extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], + device_extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], }, // TODO: document AnyHit = ANY_HIT_KHR { - extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], + device_extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], }, // TODO: document ClosestHit = CLOSEST_HIT_KHR { - extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], + device_extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], }, // TODO: document Miss = MISS_KHR { - extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], + device_extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], }, // TODO: document Intersection = INTERSECTION_KHR { - extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], + device_extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], }, // TODO: document Callable = CALLABLE_KHR { - extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], + device_extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], }, /* // TODO: document Task = TASK_NV { - extensions: [nv_mesh_shader], + device_extensions: [nv_mesh_shader], }, // TODO: document Mesh = MESH_NV { - extensions: [nv_mesh_shader], + device_extensions: [nv_mesh_shader], }, // TODO: document SubpassShading = SUBPASS_SHADING_HUAWEI { - extensions: [huawei_subpass_shading], + device_extensions: [huawei_subpass_shading], }, */ } @@ -1211,48 +1210,48 @@ vulkan_bitflags! { // TODO: document raygen = RAYGEN_KHR { - extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], + device_extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], }, // TODO: document any_hit = ANY_HIT_KHR { - extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], + device_extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], }, // TODO: document closest_hit = CLOSEST_HIT_KHR { - extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], + device_extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], }, // TODO: document miss = MISS_KHR { - extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], + device_extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], }, // TODO: document intersection = INTERSECTION_KHR { - extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], + device_extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], }, // TODO: document callable = CALLABLE_KHR { - extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], + device_extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], }, /* // TODO: document task = TASK_NV { - extensions: [nv_mesh_shader], + device_extensions: [nv_mesh_shader], }, // TODO: document mesh = MESH_NV { - extensions: [nv_mesh_shader], + device_extensions: [nv_mesh_shader], }, // TODO: document subpass_shading = SUBPASS_SHADING_HUAWEI { - extensions: [huawei_subpass_shading], + device_extensions: [huawei_subpass_shading], }, */ } diff --git a/vulkano/src/shader/spirv.rs b/vulkano/src/shader/spirv.rs index cdace1f402..bf02263b6f 100644 --- a/vulkano/src/shader/spirv.rs +++ b/vulkano/src/shader/spirv.rs @@ -19,7 +19,7 @@ use crate::Version; use std::{ collections::HashMap, error::Error, - fmt::{self, Display, Formatter}, + fmt::{Display, Error as FmtError, Formatter}, ops::Range, string::FromUtf8Error, }; @@ -571,7 +571,7 @@ impl From for u32 { } impl Display for Id { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { write!(f, "%{}", self.0) } } @@ -687,7 +687,7 @@ pub enum SpirvError { impl Display for SpirvError { #[inline] - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { match self { Self::BadLayout { index } => write!( f, @@ -746,7 +746,7 @@ pub struct ParseError { impl Display for ParseError { #[inline] - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { write!( f, "at instruction {}, word {}: {}", @@ -771,7 +771,7 @@ pub enum ParseErrors { impl Display for ParseErrors { #[inline] - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { match self { Self::FromUtf8Error(_) => write!(f, "invalid UTF-8 in string literal"), Self::LeftoverOperands => write!(f, "unparsed operands remaining"), diff --git a/vulkano/src/swapchain/display.rs b/vulkano/src/swapchain/display.rs index 03e8dd94b0..c3c97d75e6 100644 --- a/vulkano/src/swapchain/display.rs +++ b/vulkano/src/swapchain/display.rs @@ -32,7 +32,13 @@ use crate::{ device::physical::PhysicalDevice, instance::Instance, swapchain::SupportedSurfaceTransforms, OomError, VulkanError, VulkanObject, }; -use std::{ffi::CStr, fmt, fmt::Formatter, ptr, sync::Arc, vec::IntoIter}; +use std::{ + ffi::CStr, + fmt::{Display as FmtDisplay, Error as FmtError, Formatter}, + ptr, + sync::Arc, + vec::IntoIter, +}; // TODO: extract this to a `display` module and solve the visibility problems @@ -421,9 +427,9 @@ impl DisplayMode { } } -impl fmt::Display for DisplayMode { +impl FmtDisplay for DisplayMode { #[inline] - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { let visible_region = self.visible_region(); write!( diff --git a/vulkano/src/swapchain/surface.rs b/vulkano/src/swapchain/surface.rs index b130983bdb..55d5ae9033 100644 --- a/vulkano/src/swapchain/surface.rs +++ b/vulkano/src/swapchain/surface.rs @@ -16,7 +16,7 @@ use crate::{ display::{DisplayMode, DisplayPlane}, SurfaceSwapchainLock, }, - OomError, VulkanError, VulkanObject, + OomError, RequiresOneOf, VulkanError, VulkanObject, }; #[cfg(target_os = "ios")] @@ -24,7 +24,7 @@ use objc::{class, msg_send, runtime::Object, sel, sel_impl}; use std::{ error::Error, - fmt, + fmt::{Debug, Display, Error as FmtError, Formatter}, hash::{Hash, Hasher}, mem::MaybeUninit, os::raw::c_ulong, @@ -91,8 +91,12 @@ impl Surface { .enabled_extensions() .khr_display { - return Err(SurfaceCreationError::MissingExtension { - name: "VK_KHR_display", + return Err(SurfaceCreationError::RequirementNotMet { + required_for: "`from_display_plane`", + requires_one_of: RequiresOneOf { + instance_extensions: &["khr_display"], + ..Default::default() + }, }); } @@ -159,8 +163,12 @@ impl Surface { win: W, ) -> Result>, SurfaceCreationError> { if !instance.enabled_extensions().khr_android_surface { - return Err(SurfaceCreationError::MissingExtension { - name: "VK_KHR_android_surface", + return Err(SurfaceCreationError::RequirementNotMet { + required_for: "`from_android`", + requires_one_of: RequiresOneOf { + instance_extensions: &["khr_android_surface"], + ..Default::default() + }, }); } @@ -211,8 +219,12 @@ impl Surface { win: W, ) -> Result>, SurfaceCreationError> { if !instance.enabled_extensions().mvk_ios_surface { - return Err(SurfaceCreationError::MissingExtension { - name: "VK_MVK_ios_surface", + return Err(SurfaceCreationError::RequirementNotMet { + required_for: "`from_ios`", + requires_one_of: RequiresOneOf { + instance_extensions: &["mvk_ios_surface"], + ..Default::default() + }, }); } @@ -262,8 +274,12 @@ impl Surface { win: W, ) -> Result>, SurfaceCreationError> { if !instance.enabled_extensions().mvk_macos_surface { - return Err(SurfaceCreationError::MissingExtension { - name: "VK_MVK_macos_surface", + return Err(SurfaceCreationError::RequirementNotMet { + required_for: "`from_mac_os`", + requires_one_of: RequiresOneOf { + instance_extensions: &["mvk_macos_surface"], + ..Default::default() + }, }); } @@ -312,8 +328,12 @@ impl Surface { win: W, ) -> Result>, SurfaceCreationError> { if !instance.enabled_extensions().ext_metal_surface { - return Err(SurfaceCreationError::MissingExtension { - name: "VK_EXT_metal_surface", + return Err(SurfaceCreationError::RequirementNotMet { + required_for: "`from_metal`", + requires_one_of: RequiresOneOf { + instance_extensions: &["ext_metal_surface"], + ..Default::default() + }, }); } @@ -362,8 +382,12 @@ impl Surface { win: W, ) -> Result>, SurfaceCreationError> { if !instance.enabled_extensions().nn_vi_surface { - return Err(SurfaceCreationError::MissingExtension { - name: "VK_NN_vi_surface", + return Err(SurfaceCreationError::RequirementNotMet { + required_for: "`from_vi`", + requires_one_of: RequiresOneOf { + instance_extensions: &["nn_vi_surface"], + ..Default::default() + }, }); } @@ -415,8 +439,12 @@ impl Surface { win: W, ) -> Result>, SurfaceCreationError> { if !instance.enabled_extensions().khr_wayland_surface { - return Err(SurfaceCreationError::MissingExtension { - name: "VK_KHR_wayland_surface", + return Err(SurfaceCreationError::RequirementNotMet { + required_for: "`from_wayland`", + requires_one_of: RequiresOneOf { + instance_extensions: &["khr_wayland_surface"], + ..Default::default() + }, }); } @@ -469,8 +497,12 @@ impl Surface { win: W, ) -> Result>, SurfaceCreationError> { if !instance.enabled_extensions().khr_win32_surface { - return Err(SurfaceCreationError::MissingExtension { - name: "VK_KHR_win32_surface", + return Err(SurfaceCreationError::RequirementNotMet { + required_for: "`from_win32`", + requires_one_of: RequiresOneOf { + instance_extensions: &["khr_win32_surface"], + ..Default::default() + }, }); } @@ -523,8 +555,12 @@ impl Surface { win: W, ) -> Result>, SurfaceCreationError> { if !instance.enabled_extensions().khr_xcb_surface { - return Err(SurfaceCreationError::MissingExtension { - name: "VK_KHR_xcb_surface", + return Err(SurfaceCreationError::RequirementNotMet { + required_for: "`from_xcb`", + requires_one_of: RequiresOneOf { + instance_extensions: &["khr_xcb_surface"], + ..Default::default() + }, }); } @@ -577,8 +613,12 @@ impl Surface { win: W, ) -> Result>, SurfaceCreationError> { if !instance.enabled_extensions().khr_xlib_surface { - return Err(SurfaceCreationError::MissingExtension { - name: "VK_KHR_xlib_surface", + return Err(SurfaceCreationError::RequirementNotMet { + required_for: "`from_xlib`", + requires_one_of: RequiresOneOf { + instance_extensions: &["khr_xlib_surface"], + ..Default::default() + }, }); } @@ -675,9 +715,9 @@ unsafe impl VulkanObject for Surface { } } -impl fmt::Debug for Surface { +impl Debug for Surface { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { let Self { handle, instance, @@ -687,7 +727,7 @@ impl fmt::Debug for Surface { .. } = self; - fmt.debug_struct("Surface") + f.debug_struct("Surface") .field("handle", handle) .field("instance", instance) .field("api", api) @@ -727,36 +767,37 @@ pub enum SurfaceCreationError { /// Not enough memory. OomError(OomError), - /// The extension required for this function was not enabled. - MissingExtension { - /// Name of the missing extension. - name: &'static str, + RequirementNotMet { + required_for: &'static str, + requires_one_of: RequiresOneOf, }, } impl Error for SurfaceCreationError { #[inline] fn source(&self) -> Option<&(dyn Error + 'static)> { - match *self { - SurfaceCreationError::OomError(ref err) => Some(err), + match self { + SurfaceCreationError::OomError(err) => Some(err), _ => None, } } } -impl fmt::Display for SurfaceCreationError { +impl Display for SurfaceCreationError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!( - fmt, - "{}", - match *self { - SurfaceCreationError::OomError(_) => "not enough memory available", - SurfaceCreationError::MissingExtension { .. } => { - "the extension required for this function was not enabled" - } - } - ) + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { + match self { + SurfaceCreationError::OomError(_) => write!(f, "not enough memory available"), + + Self::RequirementNotMet { + required_for, + requires_one_of, + } => write!( + f, + "a requirement was not met for: {}; requires one of: {}", + required_for, requires_one_of, + ), + } } } @@ -830,12 +871,12 @@ vulkan_enum! { /* // TODO: document SharedDemandRefresh = SHARED_DEMAND_REFRESH_KHR { - extensions: [khr_shared_presentable_image], + device_extensions: [khr_shared_presentable_image], }, // TODO: document SharedContinuousRefresh = SHARED_CONTINUOUS_REFRESH_KHR { - extensions: [khr_shared_presentable_image], + device_extensions: [khr_shared_presentable_image], }, */ } @@ -1114,78 +1155,78 @@ vulkan_enum! { /* // TODO: document DisplayP3NonLinear = DISPLAY_P3_NONLINEAR_EXT { - extensions: [ext_swapchain_colorspace], + device_extensions: [ext_swapchain_colorspace], }, // TODO: document ExtendedSrgbLinear = EXTENDED_SRGB_LINEAR_EXT { - extensions: [ext_swapchain_colorspace], + device_extensions: [ext_swapchain_colorspace], }, // TODO: document ExtendedSrgbNonLinear = EXTENDED_SRGB_NONLINEAR_EXT { - extensions: [ext_swapchain_colorspace], + device_extensions: [ext_swapchain_colorspace], }, // TODO: document DisplayP3Linear = DISPLAY_P3_LINEAR_EXT { - extensions: [ext_swapchain_colorspace], + device_extensions: [ext_swapchain_colorspace], }, // TODO: document DciP3NonLinear = DCI_P3_NONLINEAR_EXT { - extensions: [ext_swapchain_colorspace], + device_extensions: [ext_swapchain_colorspace], }, // TODO: document Bt709Linear = BT709_LINEAR_EXT { - extensions: [ext_swapchain_colorspace], + device_extensions: [ext_swapchain_colorspace], }, // TODO: document Bt709NonLinear = BT709_NONLINEAR_EXT { - extensions: [ext_swapchain_colorspace], + device_extensions: [ext_swapchain_colorspace], }, // TODO: document Bt2020Linear = BT2020_LINEAR_EXT { - extensions: [ext_swapchain_colorspace], + device_extensions: [ext_swapchain_colorspace], }, // TODO: document Hdr10St2084 = HDR10_ST2084_EXT { - extensions: [ext_swapchain_colorspace], + device_extensions: [ext_swapchain_colorspace], }, // TODO: document DolbyVision = DOLBYVISION_EXT { - extensions: [ext_swapchain_colorspace], + device_extensions: [ext_swapchain_colorspace], }, // TODO: document Hdr10Hlg = HDR10_HLG_EXT { - extensions: [ext_swapchain_colorspace], + device_extensions: [ext_swapchain_colorspace], }, // TODO: document AdobeRgbLinear = ADOBERGB_LINEAR_EXT { - extensions: [ext_swapchain_colorspace], + device_extensions: [ext_swapchain_colorspace], }, // TODO: document AdobeRgbNonLinear = ADOBERGB_NONLINEAR_EXT { - extensions: [ext_swapchain_colorspace], + device_extensions: [ext_swapchain_colorspace], }, // TODO: document PassThrough = PASS_THROUGH_EXT { - extensions: [ext_swapchain_colorspace], + device_extensions: [ext_swapchain_colorspace], }, */ // TODO: document DisplayNative = DISPLAY_NATIVE_AMD { - extensions: [amd_display_native_hdr], + device_extensions: [amd_display_native_hdr], }, } @@ -1289,14 +1330,24 @@ pub struct SurfaceCapabilities { #[cfg(test)] mod tests { - use crate::swapchain::{Surface, SurfaceCreationError}; + use crate::{ + swapchain::{Surface, SurfaceCreationError}, + RequiresOneOf, + }; use std::ptr; #[test] fn khr_win32_surface_ext_missing() { let instance = instance!(); match unsafe { Surface::from_win32(instance, ptr::null::(), ptr::null::(), ()) } { - Err(SurfaceCreationError::MissingExtension { .. }) => (), + Err(SurfaceCreationError::RequirementNotMet { + requires_one_of: + RequiresOneOf { + instance_extensions, + .. + }, + .. + }) if instance_extensions.contains(&"khr_win32_surface") => (), _ => panic!(), } } @@ -1305,7 +1356,14 @@ mod tests { fn khr_xcb_surface_ext_missing() { let instance = instance!(); match unsafe { Surface::from_xcb(instance, ptr::null::(), 0, ()) } { - Err(SurfaceCreationError::MissingExtension { .. }) => (), + Err(SurfaceCreationError::RequirementNotMet { + requires_one_of: + RequiresOneOf { + instance_extensions, + .. + }, + .. + }) if instance_extensions.contains(&"khr_xcb_surface") => (), _ => panic!(), } } @@ -1314,7 +1372,14 @@ mod tests { fn khr_xlib_surface_ext_missing() { let instance = instance!(); match unsafe { Surface::from_xlib(instance, ptr::null::(), 0, ()) } { - Err(SurfaceCreationError::MissingExtension { .. }) => (), + Err(SurfaceCreationError::RequirementNotMet { + requires_one_of: + RequiresOneOf { + instance_extensions, + .. + }, + .. + }) if instance_extensions.contains(&"khr_xlib_surface") => (), _ => panic!(), } } @@ -1323,7 +1388,14 @@ mod tests { fn khr_wayland_surface_ext_missing() { let instance = instance!(); match unsafe { Surface::from_wayland(instance, ptr::null::(), ptr::null::(), ()) } { - Err(SurfaceCreationError::MissingExtension { .. }) => (), + Err(SurfaceCreationError::RequirementNotMet { + requires_one_of: + RequiresOneOf { + instance_extensions, + .. + }, + .. + }) if instance_extensions.contains(&"khr_wayland_surface") => (), _ => panic!(), } } @@ -1332,7 +1404,14 @@ mod tests { fn khr_android_surface_ext_missing() { let instance = instance!(); match unsafe { Surface::from_android(instance, ptr::null::(), ()) } { - Err(SurfaceCreationError::MissingExtension { .. }) => (), + Err(SurfaceCreationError::RequirementNotMet { + requires_one_of: + RequiresOneOf { + instance_extensions, + .. + }, + .. + }) if instance_extensions.contains(&"khr_android_surface") => (), _ => panic!(), } } diff --git a/vulkano/src/swapchain/swapchain.rs b/vulkano/src/swapchain/swapchain.rs index a4d7f620f0..98dd4b6c69 100644 --- a/vulkano/src/swapchain/swapchain.rs +++ b/vulkano/src/swapchain/swapchain.rs @@ -16,25 +16,28 @@ use crate::{ command_buffer::submit::{ SubmitAnyBuilder, SubmitPresentBuilder, SubmitPresentError, SubmitSemaphoresWaitBuilder, }, - device::{physical::SurfacePropertiesError, Device, DeviceOwned, Queue}, + device::{ + physical::{ImageFormatPropertiesError, SurfacePropertiesError}, + Device, DeviceOwned, Queue, + }, format::Format, image::{ sys::UnsafeImage, ImageCreateFlags, ImageDimensions, ImageFormatInfo, ImageInner, ImageLayout, ImageTiling, ImageType, ImageUsage, SampleCount, SwapchainImage, }, - macros::{vulkan_enum, ExtensionNotEnabled}, + macros::vulkan_enum, swapchain::{SurfaceApi, SurfaceInfo, SurfaceSwapchainLock}, sync::{ AccessCheckError, AccessError, AccessFlags, Fence, FlushError, GpuFuture, PipelineStages, Semaphore, SemaphoreCreationError, Sharing, }, - DeviceSize, OomError, VulkanError, VulkanObject, + DeviceSize, OomError, RequirementNotMet, RequiresOneOf, VulkanError, VulkanObject, }; use parking_lot::Mutex; use smallvec::SmallVec; use std::{ error::Error, - fmt, + fmt::{Display, Error as FmtError, Formatter}, hash::{Hash, Hasher}, mem::MaybeUninit, ops::Range, @@ -113,9 +116,12 @@ impl Swapchain { ); if !device.enabled_extensions().khr_swapchain { - return Err(SwapchainCreationError::ExtensionNotEnabled { - extension: "khr_swapchain", - reason: "created a new swapchain", + return Err(SwapchainCreationError::RequirementNotMet { + required_for: "`Swapchain`", + requires_one_of: RequiresOneOf { + device_extensions: &["khr_swapchain"], + ..Default::default() + }, }); } @@ -297,33 +303,37 @@ impl Swapchain { } = create_info; // VUID-VkSwapchainCreateInfoKHR-imageColorSpace-parameter - image_color_space.validate(device)?; + image_color_space.validate_device(device)?; // VUID-VkSwapchainCreateInfoKHR-imageUsage-parameter - image_usage.validate(device)?; + image_usage.validate_device(device)?; // VUID-VkSwapchainCreateInfoKHR-imageUsage-requiredbitmask assert!(!image_usage.is_empty()); // VUID-VkSwapchainCreateInfoKHR-preTransform-parameter - pre_transform.validate(device)?; + pre_transform.validate_device(device)?; // VUID-VkSwapchainCreateInfoKHR-compositeAlpha-parameter - composite_alpha.validate(device)?; + composite_alpha.validate_device(device)?; // VUID-VkSwapchainCreateInfoKHR-presentMode-parameter - present_mode.validate(device)?; + present_mode.validate_device(device)?; if full_screen_exclusive != FullScreenExclusive::Default { if !device.enabled_extensions().ext_full_screen_exclusive { - return Err(SwapchainCreationError::ExtensionNotEnabled { - extension: "ext_full_screen_exclusive", - reason: "`full_screen_exclusive` was not `FullScreenExclusive::Default`", + return Err(SwapchainCreationError::RequirementNotMet { + required_for: + "`create_info.full_screen_exclusive` is not `FullScreenExclusive::Default`", + requires_one_of: RequiresOneOf { + device_extensions: &["ext_full_screen_exclusive"], + ..Default::default() + }, }); } // VUID-VkSurfaceFullScreenExclusiveInfoEXT-fullScreenExclusive-parameter - full_screen_exclusive.validate(device)?; + full_screen_exclusive.validate_device(device)?; } if surface.api() == SurfaceApi::Win32 @@ -351,7 +361,7 @@ impl Swapchain { if let Some(format) = image_format { // VUID-VkSwapchainCreateInfoKHR-imageFormat-parameter - // TODO: format.validate(device)?; + // TODO: format.validate_device(device)?; // VUID-VkSwapchainCreateInfoKHR-imageFormat-01273 if !surface_formats @@ -1063,9 +1073,9 @@ pub enum SwapchainCreationError { /// The window is already in use by another API. NativeWindowInUse, - ExtensionNotEnabled { - extension: &'static str, - reason: &'static str, + RequirementNotMet { + required_for: &'static str, + requires_one_of: RequiresOneOf, }, /// The provided `composite_alpha` is not supported by the surface for this device. @@ -1145,80 +1155,83 @@ impl Error for SwapchainCreationError { } } -impl fmt::Display for SwapchainCreationError { +impl Display for SwapchainCreationError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match *self { - Self::OomError(_) => write!(fmt, "not enough memory available",), - Self::DeviceLost => write!(fmt, "the device was lost",), - Self::SurfaceLost => write!(fmt, "the surface was lost",), + Self::OomError(_) => write!(f, "not enough memory available",), + Self::DeviceLost => write!(f, "the device was lost",), + Self::SurfaceLost => write!(f, "the surface was lost",), Self::SurfaceInUse => { - write!(fmt, "the surface is already used by another swapchain",) + write!(f, "the surface is already used by another swapchain",) } Self::NativeWindowInUse => { - write!(fmt, "the window is already in use by another API") + write!(f, "the window is already in use by another API") } - Self::ExtensionNotEnabled { extension, reason } => write!( - fmt, - "the extension {} must be enabled: {}", - extension, reason + Self::RequirementNotMet { + required_for, + requires_one_of, + } => write!( + f, + "a requirement was not met for: {}; requires one of: {}", + required_for, requires_one_of, ), Self::CompositeAlphaNotSupported { .. } => write!( - fmt, + f, "the provided `composite_alpha` is not supported by the surface for this device", ), Self::FormatColorSpaceNotSupported => write!( - fmt, + f, "the provided `format` and `color_space` are not supported by the surface for this device", ), Self::ImageArrayLayersNotSupported { provided, max_supported } => write!( - fmt, + f, "the provided `image_array_layers` ({}) is greater than what is supported ({}) by the surface for this device", provided, max_supported, ), Self::ImageExtentNotSupported { provided, min_supported, max_supported } => write!( - fmt, + f, "the provided `image_extent` ({:?}) is not within the range (min: {:?}, max: {:?}) supported by the surface for this device", provided, min_supported, max_supported, ), Self::ImageExtentZeroLengthDimensions => write!( - fmt, + f, "the provided `image_extent` contained at least one dimension of zero length", ), Self::ImageFormatPropertiesNotSupported => write!( - fmt, + f, "the provided image parameters are not supported as queried from `image_format_properties`", ), Self::ImageSharingInvalidQueueFamilyId { id } => write!( - fmt, + f, "the provided `image_sharing` was set to `Concurrent`, but one of the specified queue family ids ({}) was not valid", id, ), Self::ImageUsageNotSupported { .. } => write!( - fmt, + f, "the provided `image_usage` has fields set that are not supported by the surface for this device", ), Self::MinImageCountNotSupported { provided, min_supported, max_supported } => write!( - fmt, + f, "the provided `min_image_count` ({}) is not within the range (min: {}, max: {:?}) supported by the surface for this device", provided, min_supported, max_supported, ), Self::PresentModeNotSupported => write!( - fmt, + f, "the provided `present_mode` is not supported by the surface for this device", ), Self::PreTransformNotSupported { .. } => write!( - fmt, + f, "the provided `pre_transform` is not supported by the surface for this device", ), Self::SwapchainAlreadyRetired => write!( - fmt, + f, "the swapchain has already been used to create a new one", ), Self::Win32MonitorInvalid => write!( - fmt, + f, "the `win32_monitor` value was `Some` when it must be `None` or vice-versa", ), } @@ -1257,12 +1270,28 @@ impl From for SwapchainCreationError { } } -impl From for SwapchainCreationError { +impl From for SwapchainCreationError { + #[inline] + fn from(err: RequirementNotMet) -> Self { + Self::RequirementNotMet { + required_for: err.required_for, + requires_one_of: err.requires_one_of, + } + } +} + +impl From for SwapchainCreationError { #[inline] - fn from(err: ExtensionNotEnabled) -> Self { - Self::ExtensionNotEnabled { - extension: err.extension, - reason: err.reason, + fn from(err: ImageFormatPropertiesError) -> Self { + match err { + ImageFormatPropertiesError::OomError(err) => Self::OomError(err), + ImageFormatPropertiesError::RequirementNotMet { + required_for, + requires_one_of, + } => Self::RequirementNotMet { + required_for, + requires_one_of, + }, } } } @@ -1345,11 +1374,11 @@ impl Error for FullScreenExclusiveError { } } -impl fmt::Display for FullScreenExclusiveError { +impl Display for FullScreenExclusiveError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { write!( - fmt, + f, "{}", match *self { FullScreenExclusiveError::OomError(_) => "not enough memory", @@ -1688,11 +1717,11 @@ impl Error for AcquireError { } } -impl fmt::Display for AcquireError { +impl Display for AcquireError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { write!( - fmt, + f, "{}", match *self { AcquireError::OomError(_) => "not enough memory", diff --git a/vulkano/src/sync/fence.rs b/vulkano/src/sync/fence.rs index 124bfb792a..8010829fd6 100644 --- a/vulkano/src/sync/fence.rs +++ b/vulkano/src/sync/fence.rs @@ -14,7 +14,7 @@ use crate::{ use smallvec::SmallVec; use std::{ error::Error, - fmt, + fmt::{Display, Error as FmtError, Formatter}, hash::{Hash, Hasher}, mem::MaybeUninit, ptr, @@ -413,11 +413,11 @@ impl Error for FenceWaitError { } } -impl fmt::Display for FenceWaitError { +impl Display for FenceWaitError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { write!( - fmt, + f, "{}", match *self { FenceWaitError::OomError(_) => "no memory available", diff --git a/vulkano/src/sync/future/mod.rs b/vulkano/src/sync/future/mod.rs index 67a5b4f61f..392bde9038 100644 --- a/vulkano/src/sync/future/mod.rs +++ b/vulkano/src/sync/future/mod.rs @@ -27,7 +27,12 @@ use crate::{ swapchain::{self, PresentFuture, PresentRegion, Swapchain}, DeviceSize, OomError, }; -use std::{error::Error, fmt, ops::Range, sync::Arc}; +use std::{ + error::Error, + fmt::{Display, Error as FmtError, Formatter}, + ops::Range, + sync::Arc, +}; mod fence_signal; mod join; @@ -407,11 +412,11 @@ pub enum AccessError { impl Error for AccessError {} -impl fmt::Display for AccessError { +impl Display for AccessError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { write!( - fmt, + f, "{}", match *self { AccessError::ExclusiveDenied => "only shared access is allowed for this resource", @@ -448,11 +453,11 @@ pub enum AccessCheckError { impl Error for AccessCheckError {} -impl fmt::Display for AccessCheckError { +impl Display for AccessCheckError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { write!( - fmt, + f, "{}", match *self { AccessCheckError::Denied(_) => "access to the resource has been denied", @@ -507,11 +512,11 @@ impl Error for FlushError { } } -impl fmt::Display for FlushError { +impl Display for FlushError { #[inline] - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { write!( - fmt, + f, "{}", match *self { FlushError::AccessError(_) => "access to a resource has been denied", diff --git a/vulkano/src/sync/pipeline.rs b/vulkano/src/sync/pipeline.rs index 5771d8ea18..3e627140b9 100644 --- a/vulkano/src/sync/pipeline.rs +++ b/vulkano/src/sync/pipeline.rs @@ -75,49 +75,49 @@ vulkan_enum! { /* // TODO: document TransformFeedback = TRANSFORM_FEEDBACK_EXT { - extensions: [ext_transform_feedback], + device_extensions: [ext_transform_feedback], }, // TODO: document ConditionalRendering = CONDITIONAL_RENDERING_EXT { - extensions: [ext_conditional_rendering], + device_extensions: [ext_conditional_rendering], }, // TODO: document AccelerationStructureBuild = ACCELERATION_STRUCTURE_BUILD_KHR { - extensions: [khr_acceleration_structure, nv_ray_tracing], + device_extensions: [khr_acceleration_structure, nv_ray_tracing], }, */ // TODO: document RayTracingShader = RAY_TRACING_SHADER_KHR { - extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], + device_extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], }, /* // TODO: document FragmentDensityProcess = FRAGMENT_DENSITY_PROCESS_EXT { - extensions: [ext_fragment_density_map], + device_extensions: [ext_fragment_density_map], }, // TODO: document FragmentShadingRateAttachment = FRAGMENT_SHADING_RATE_ATTACHMENT_KHR { - extensions: [khr_fragment_shading_rate], + device_extensions: [khr_fragment_shading_rate], }, // TODO: document CommandPreprocess = COMMAND_PREPROCESS_NV { - extensions: [nv_device_generated_commands], + device_extensions: [nv_device_generated_commands], }, // TODO: document TaskShader = TASK_SHADER_NV { - extensions: [nv_mesh_shader], + device_extensions: [nv_mesh_shader], }, // TODO: document MeshShader = MESH_SHADER_NV { - extensions: [nv_mesh_shader], + device_extensions: [nv_mesh_shader], }, */ } @@ -222,49 +222,49 @@ vulkan_bitflags! { /* // TODO: document transform_feedback = TRANSFORM_FEEDBACK_EXT { - extensions: [ext_transform_feedback], + device_extensions: [ext_transform_feedback], }, // TODO: document conditional_rendering = CONDITIONAL_RENDERING_EXT { - extensions: [ext_conditional_rendering], + device_extensions: [ext_conditional_rendering], }, // TODO: document acceleration_structure_build = ACCELERATION_STRUCTURE_BUILD_KHR { - extensions: [khr_acceleration_structure, nv_ray_tracing], + device_extensions: [khr_acceleration_structure, nv_ray_tracing], }, */ // TODO: document ray_tracing_shader = RAY_TRACING_SHADER_KHR { - extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], + device_extensions: [khr_ray_tracing_pipeline, nv_ray_tracing], }, /* // TODO: document fragment_density_process = FRAGMENT_DENSITY_PROCESS_EXT { - extensions: [ext_fragment_density_map], + device_extensions: [ext_fragment_density_map], }, // TODO: document fragment_shading_rate_attachment = FRAGMENT_SHADING_RATE_ATTACHMENT_KHR { - extensions: [khr_fragment_shading_rate], + device_extensions: [khr_fragment_shading_rate], }, // TODO: document command_preprocess = COMMAND_PREPROCESS_NV { - extensions: [nv_device_generated_commands], + device_extensions: [nv_device_generated_commands], }, // TODO: document task_shader = TASK_SHADER_NV { - extensions: [nv_mesh_shader], + device_extensions: [nv_mesh_shader], }, // TODO: document mesh_shader = MESH_SHADER_NV { - extensions: [nv_mesh_shader], + device_extensions: [nv_mesh_shader], }, */ } @@ -459,57 +459,57 @@ vulkan_bitflags! { /* // Provided by VK_EXT_transform_feedback transform_feedback_write = TRANSFORM_FEEDBACK_WRITE_EXT { - extensions: [ext_transform_feedback], + device_extensions: [ext_transform_feedback], }, // Provided by VK_EXT_transform_feedback transform_feedback_counter_read = TRANSFORM_FEEDBACK_COUNTER_READ_EXT { - extensions: [ext_transform_feedback], + device_extensions: [ext_transform_feedback], }, // Provided by VK_EXT_transform_feedback transform_feedback_counter_write = TRANSFORM_FEEDBACK_COUNTER_WRITE_EXT { - extensions: [ext_transform_feedback], + device_extensions: [ext_transform_feedback], }, // Provided by VK_EXT_conditional_rendering conditional_rendering_read = CONDITIONAL_RENDERING_READ_EXT { - extensions: [ext_conditional_rendering], + device_extensions: [ext_conditional_rendering], }, // Provided by VK_EXT_blend_operation_advanced color_attachment_read_noncoherent = COLOR_ATTACHMENT_READ_NONCOHERENT_EXT { - extensions: [ext_blend_operation_advanced], + device_extensions: [ext_blend_operation_advanced], }, // Provided by VK_KHR_acceleration_structure acceleration_structure_read = ACCELERATION_STRUCTURE_READ_KHR { - extensions: [khr_acceleration_structure, nv_ray_tracing], + device_extensions: [khr_acceleration_structure, nv_ray_tracing], }, // Provided by VK_KHR_acceleration_structure acceleration_structure_write = ACCELERATION_STRUCTURE_WRITE_KHR { - extensions: [khr_acceleration_structure, nv_ray_tracing], + device_extensions: [khr_acceleration_structure, nv_ray_tracing], }, // Provided by VK_EXT_fragment_density_map fragment_density_map_read = FRAGMENT_DENSITY_MAP_READ_EXT { - extensions: [ext_fragment_density_map], + device_extensions: [ext_fragment_density_map], }, // Provided by VK_KHR_fragment_shading_rate fragment_shading_rate_attachment_read = FRAGMENT_SHADING_RATE_ATTACHMENT_READ_KHR { - extensions: [khr_fragment_shading_rate], + device_extensions: [khr_fragment_shading_rate], }, // Provided by VK_NV_device_generated_commands command_preprocess_read = COMMAND_PREPROCESS_READ_NV { - extensions: [nv_device_generated_commands], + device_extensions: [nv_device_generated_commands], }, // Provided by VK_NV_device_generated_commands command_preprocess_write = COMMAND_PREPROCESS_WRITE_NV { - extensions: [nv_device_generated_commands], + device_extensions: [nv_device_generated_commands], }, */ } diff --git a/vulkano/src/sync/semaphore.rs b/vulkano/src/sync/semaphore.rs index 2f323f0715..e5bc6535e4 100644 --- a/vulkano/src/sync/semaphore.rs +++ b/vulkano/src/sync/semaphore.rs @@ -9,12 +9,12 @@ use crate::{ device::{Device, DeviceOwned}, - macros::{vulkan_bitflags, vulkan_enum, ExtensionNotEnabled}, - OomError, Version, VulkanError, VulkanObject, + macros::{vulkan_bitflags, vulkan_enum}, + OomError, RequirementNotMet, RequiresOneOf, Version, VulkanError, VulkanObject, }; use std::{ error::Error, - fmt, + fmt::{Display, Error as FmtError, Formatter}, fs::File, hash::{Hash, Hasher}, mem::MaybeUninit, @@ -50,14 +50,18 @@ impl Semaphore { if !(device.api_version() >= Version::V1_1 || device.enabled_extensions().khr_external_semaphore) { - return Err(SemaphoreCreationError::ExtensionNotEnabled { - extension: "khr_external_semaphore", - reason: "export_handle_types was not empty", + return Err(SemaphoreCreationError::RequirementNotMet { + required_for: "`create_info.export_handle_types` is not empty", + requires_one_of: RequiresOneOf { + api_version: Some(Version::V1_1), + device_extensions: &["khr_external_semaphore"], + ..Default::default() + }, }); } // VUID-VkExportSemaphoreCreateInfo-handleTypes-parameter - export_handle_types.validate(&device)?; + export_handle_types.validate_device(&device)?; // VUID-VkExportSemaphoreCreateInfo-handleTypes-01124 // TODO: `vkGetPhysicalDeviceExternalSemaphoreProperties` can only be called with one @@ -258,9 +262,9 @@ pub enum SemaphoreCreationError { /// Not enough memory available. OomError(OomError), - ExtensionNotEnabled { - extension: &'static str, - reason: &'static str, + RequirementNotMet { + required_for: &'static str, + requires_one_of: RequiresOneOf, }, } @@ -274,13 +278,19 @@ impl Error for SemaphoreCreationError { } } -impl fmt::Display for SemaphoreCreationError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl Display for SemaphoreCreationError { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match self { Self::OomError(_) => write!(f, "not enough memory available"), - Self::ExtensionNotEnabled { extension, reason } => { - write!(f, "the extension {} must be enabled: {}", extension, reason) - } + + Self::RequirementNotMet { + required_for, + requires_one_of, + } => write!( + f, + "a requirement was not met for: {}; requires one of: {}", + required_for, requires_one_of, + ), } } } @@ -304,12 +314,12 @@ impl From for SemaphoreCreationError { } } -impl From for SemaphoreCreationError { +impl From for SemaphoreCreationError { #[inline] - fn from(err: ExtensionNotEnabled) -> Self { - Self::ExtensionNotEnabled { - extension: err.extension, - reason: err.reason, + fn from(err: RequirementNotMet) -> Self { + Self::RequirementNotMet { + required_for: err.required_for, + requires_one_of: err.requires_one_of, } } } @@ -358,7 +368,7 @@ vulkan_enum! { /* // TODO: document ZirconEvent = ZIRCON_EVENT_FUCHSIA { - extensions: [fuchsia_external_semaphore], + device_extensions: [fuchsia_external_semaphore], }, */ } @@ -386,7 +396,7 @@ vulkan_bitflags! { /* // TODO: document zircon_event = ZIRCON_EVENT_FUCHSIA { - extensions: [fuchsia_external_semaphore], + device_extensions: [fuchsia_external_semaphore], }, */ } @@ -446,12 +456,12 @@ pub enum SemaphoreExportError { }, } -impl fmt::Display for SemaphoreExportError { - fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl Display for SemaphoreExportError { + fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { match *self { - Self::OomError(_) => write!(fmt, "not enough memory available"), + Self::OomError(_) => write!(f, "not enough memory available"), Self::HandleTypeNotSupported { handle_type } => write!( - fmt, + f, "the requested export handle type ({:?}) was not provided in `export_handle_types` when creating the semaphore", handle_type, ), diff --git a/vulkano/src/version.rs b/vulkano/src/version.rs index c355864b4d..da71340a5d 100644 --- a/vulkano/src/version.rs +++ b/vulkano/src/version.rs @@ -9,7 +9,11 @@ // The `Version` object is reexported from the `instance` module. -use std::{fmt, num::ParseIntError, str::FromStr}; +use std::{ + fmt::{Debug, Display, Error as FmtError, Formatter}, + num::ParseIntError, + str::FromStr, +}; // Generated by build.rs include!(concat!(env!("OUT_DIR"), "/version.rs")); @@ -94,15 +98,15 @@ impl FromStr for Version { } } -impl fmt::Debug for Version { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { +impl Debug for Version { + fn fmt(&self, formatter: &mut Formatter) -> Result<(), FmtError> { write!(formatter, "{}.{}.{}", self.major, self.minor, self.patch) } } -impl fmt::Display for Version { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(self, formatter) +impl Display for Version { + fn fmt(&self, formatter: &mut Formatter) -> Result<(), FmtError> { + Debug::fmt(self, formatter) } }