Box ValidationError (#2253)

This commit is contained in:
Rua 2023-07-06 12:43:45 +02:00 committed by GitHub
parent 622ec47970
commit b74ce40b2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
70 changed files with 2904 additions and 2771 deletions

View File

@ -6,14 +6,14 @@ use raw_window_handle::{
HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle,
};
use std::{any::Any, sync::Arc};
use vulkano::{instance::Instance, swapchain::Surface, VulkanError};
use vulkano::{instance::Instance, swapchain::Surface, Validated, VulkanError};
/// Creates a Vulkan surface from a generic window which implements `HasRawWindowHandle` and thus
/// can reveal the OS-dependent handle.
pub fn create_surface_from_handle(
window: Arc<impl Any + Send + Sync + HasRawWindowHandle + HasRawDisplayHandle>,
instance: Arc<Instance>,
) -> Result<Arc<Surface>, VulkanError> {
) -> Result<Arc<Surface>, Validated<VulkanError>> {
unsafe {
match window.raw_window_handle() {
RawWindowHandle::AndroidNdk(h) => {
@ -82,7 +82,7 @@ pub fn create_surface_from_handle(
pub unsafe fn create_surface_from_handle_ref(
window: &(impl HasRawWindowHandle + HasRawDisplayHandle),
instance: Arc<Instance>,
) -> Result<Arc<Surface>, VulkanError> {
) -> Result<Arc<Surface>, Validated<VulkanError>> {
unsafe {
match window.raw_window_handle() {
RawWindowHandle::AndroidNdk(h) => {

View File

@ -6,7 +6,7 @@ use std::{
use vulkano::{
instance::{Instance, InstanceExtensions},
swapchain::Surface,
VulkanError, VulkanLibrary,
Validated, VulkanError, VulkanLibrary,
};
use winit::{
error::OsError as WindowCreationError,
@ -37,7 +37,7 @@ pub fn required_extensions(library: &VulkanLibrary) -> InstanceExtensions {
pub fn create_surface_from_winit(
window: Arc<Window>,
instance: Arc<Instance>,
) -> Result<Arc<Surface>, VulkanError> {
) -> Result<Arc<Surface>, Validated<VulkanError>> {
unsafe { winit_to_surface(instance, window) }
}
@ -65,17 +65,17 @@ impl<E> VkSurfaceBuild<E> for WindowBuilder {
#[derive(Debug)]
pub enum CreationError {
/// Error when creating the surface.
VulkanError(VulkanError),
Surface(Validated<VulkanError>),
/// Error when creating the window.
WindowCreationError(WindowCreationError),
Window(WindowCreationError),
}
impl Error for CreationError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
CreationError::VulkanError(err) => Some(err),
CreationError::WindowCreationError(err) => Some(err),
CreationError::Surface(err) => Some(err),
CreationError::Window(err) => Some(err),
}
}
}
@ -86,22 +86,22 @@ impl Display for CreationError {
f,
"{}",
match self {
CreationError::VulkanError(_) => "error while creating the surface",
CreationError::WindowCreationError(_) => "error while creating the window",
CreationError::Surface(_) => "error while creating the surface",
CreationError::Window(_) => "error while creating the window",
}
)
}
}
impl From<VulkanError> for CreationError {
fn from(err: VulkanError) -> CreationError {
CreationError::VulkanError(err)
impl From<Validated<VulkanError>> for CreationError {
fn from(err: Validated<VulkanError>) -> CreationError {
CreationError::Surface(err)
}
}
impl From<WindowCreationError> for CreationError {
fn from(err: WindowCreationError) -> CreationError {
CreationError::WindowCreationError(err)
CreationError::Window(err)
}
}
@ -109,7 +109,7 @@ impl From<WindowCreationError> for CreationError {
unsafe fn winit_to_surface(
instance: Arc<Instance>,
window: Arc<Window>,
) -> Result<Arc<Surface>, VulkanError> {
) -> Result<Arc<Surface>, Validated<VulkanError>> {
use raw_window_handle::HasRawWindowHandle;
use raw_window_handle::RawWindowHandle::AndroidNdk;
if let AndroidNdk(handle) = window.raw_window_handle() {
@ -128,7 +128,7 @@ unsafe fn winit_to_surface(
unsafe fn winit_to_surface(
instance: Arc<Instance>,
window: Arc<Window>,
) -> Result<Arc<Surface>, VulkanError> {
) -> Result<Arc<Surface>, Validated<VulkanError>> {
use winit::platform::{wayland::WindowExtWayland, x11::WindowExtX11};
match (window.wayland_display(), window.wayland_surface()) {
@ -194,7 +194,7 @@ pub(crate) unsafe fn get_metal_layer_macos(view: *mut std::ffi::c_void) -> *mut
unsafe fn winit_to_surface(
instance: Arc<Instance>,
window: Arc<Window>,
) -> Result<Arc<Surface>, VulkanError> {
) -> Result<Arc<Surface>, Validated<VulkanError>> {
use winit::platform::macos::WindowExtMacOS;
let layer = get_metal_layer_macos(window.ns_view());
Surface::from_mac_os(instance, layer as *const (), Some(window))
@ -225,7 +225,7 @@ pub(crate) unsafe fn get_metal_layer_ios(view: *mut std::ffi::c_void) -> IOSMeta
unsafe fn winit_to_surface(
instance: Arc<Instance>,
window: Arc<Window>,
) -> Result<Arc<Surface>, VulkanError> {
) -> Result<Arc<Surface>, Validated<VulkanError>> {
use winit::platform::ios::WindowExtIOS;
let layer = get_metal_layer_ios(window.ui_view());
Surface::from_ios(instance, layer, Some(window))
@ -235,7 +235,7 @@ unsafe fn winit_to_surface(
unsafe fn winit_to_surface(
instance: Arc<Instance>,
window: Arc<Window>,
) -> Result<Arc<Surface>, VulkanError> {
) -> Result<Arc<Surface>, Validated<VulkanError>> {
use winit::platform::windows::WindowExtWindows;
Surface::from_win32(

View File

@ -42,13 +42,13 @@ fn errors_output(members: &[ErrorsMember]) -> TokenStream {
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[repr(i32)]
#[non_exhaustive]
pub enum RuntimeError {
pub enum VulkanError {
#(#enum_items)*
Unnamed(ash::vk::Result),
}
impl From<ash::vk::Result> for RuntimeError {
fn from(val: ash::vk::Result) -> RuntimeError {
impl From<ash::vk::Result> for VulkanError {
fn from(val: ash::vk::Result) -> VulkanError {
match val {
#(#try_from_items)*
x => Self::Unnamed(x),

View File

@ -160,13 +160,13 @@ fn device_extensions_output(members: &[ExtensionsMember]) -> TokenStream {
quote! {
if !(#(#condition_items)||*) {
return Err(crate::ValidationError {
return Err(Box::new(crate::ValidationError {
problem: #problem.into(),
requires_one_of: crate::RequiresOneOf(&[
#(#requires_one_of_items)*
]),
..Default::default()
});
}));
}
}
})
@ -180,10 +180,10 @@ fn device_extensions_output(members: &[ExtensionsMember]) -> TokenStream {
quote! {
if self.#name {
if !supported.#name {
return Err(crate::ValidationError {
return Err(Box::new(crate::ValidationError {
problem: #problem.into(),
..Default::default()
});
}));
}
#(#dependency_check_items)*
@ -277,7 +277,7 @@ fn device_extensions_output(members: &[ExtensionsMember]) -> TokenStream {
supported: &DeviceExtensions,
api_version: crate::Version,
instance_extensions: &crate::instance::InstanceExtensions,
) -> Result<(), crate::ValidationError> {
) -> Result<(), Box<crate::ValidationError>> {
#(#check_requirements_items)*
Ok(())
}
@ -317,7 +317,7 @@ fn instance_extensions_output(members: &[ExtensionsMember]) -> TokenStream {
quote! {
if !(api_version >= crate::Version::#version) {
return Err(crate::ValidationError {
return Err(Box::new(crate::ValidationError {
problem: #problem.into(),
requires_one_of: crate::RequiresOneOf(&[
crate::RequiresAllOf(&[
@ -325,7 +325,7 @@ fn instance_extensions_output(members: &[ExtensionsMember]) -> TokenStream {
]),
]),
..Default::default()
});
}));
}
}
})
@ -339,10 +339,10 @@ fn instance_extensions_output(members: &[ExtensionsMember]) -> TokenStream {
quote! {
if self.#name {
if !supported.#name {
return Err(crate::ValidationError {
return Err(Box::new(crate::ValidationError {
problem: #problem.into(),
..Default::default()
});
}));
}
#(#dependency_check_items)*
@ -435,7 +435,7 @@ fn instance_extensions_output(members: &[ExtensionsMember]) -> TokenStream {
&self,
supported: &InstanceExtensions,
api_version: crate::Version,
) -> Result<(), crate::ValidationError> {
) -> Result<(), Box<crate::ValidationError>> {
#(#check_requirements_items)*
Ok(())
}

View File

@ -101,7 +101,7 @@ fn features_output(members: &[FeaturesMember]) -> TokenStream {
let name_string = name.to_string();
quote! {
if self.#name && !supported.#name {
return Err(crate::ValidationError {
return Err(Box::new(crate::ValidationError {
problem: format!(
"contains `{}`, but this feature is not supported \
by the physical device",
@ -109,7 +109,7 @@ fn features_output(members: &[FeaturesMember]) -> TokenStream {
)
.into(),
..Default::default()
});
}));
}
}
});
@ -291,7 +291,7 @@ fn features_output(members: &[FeaturesMember]) -> TokenStream {
pub(super) fn check_requirements(
&self,
supported: &Features,
) -> Result<(), crate::ValidationError> {
) -> Result<(), Box<crate::ValidationError>> {
#(#check_requirements_items)*
Ok(())
}

View File

@ -97,8 +97,8 @@ use crate::{
format::{Format, FormatFeatures},
instance::InstanceOwnedDebugWrapper,
macros::{impl_id_counter, vulkan_bitflags, vulkan_enum},
DeviceSize, NonZeroDeviceSize, Packed24_8, Requires, RequiresAllOf, RequiresOneOf,
RuntimeError, ValidationError, VulkanError, VulkanObject,
DeviceSize, NonZeroDeviceSize, Packed24_8, Requires, RequiresAllOf, RequiresOneOf, Validated,
ValidationError, VulkanError, VulkanObject,
};
use bytemuck::{Pod, Zeroable};
use std::{fmt::Debug, hash::Hash, mem::MaybeUninit, num::NonZeroU64, ptr, sync::Arc};
@ -130,7 +130,7 @@ impl AccelerationStructure {
pub unsafe fn new(
device: Arc<Device>,
create_info: AccelerationStructureCreateInfo,
) -> Result<Arc<Self>, VulkanError> {
) -> Result<Arc<Self>, Validated<VulkanError>> {
Self::validate_new(&device, &create_info)?;
Ok(Self::new_unchecked(device, create_info)?)
@ -139,24 +139,24 @@ impl AccelerationStructure {
fn validate_new(
device: &Device,
create_info: &AccelerationStructureCreateInfo,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
if !device.enabled_extensions().khr_acceleration_structure {
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceExtension(
"khr_acceleration_structure",
)])]),
..Default::default()
});
}));
}
if !device.enabled_features().acceleration_structure {
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"acceleration_structure",
)])]),
vuids: &["VUID-vkCreateAccelerationStructureKHR-accelerationStructure-03611"],
..Default::default()
});
}));
}
// VUID-vkCreateAccelerationStructureKHR-pCreateInfo-parameter
@ -171,7 +171,7 @@ impl AccelerationStructure {
pub unsafe fn new_unchecked(
device: Arc<Device>,
create_info: AccelerationStructureCreateInfo,
) -> Result<Arc<Self>, RuntimeError> {
) -> Result<Arc<Self>, VulkanError> {
let &AccelerationStructureCreateInfo {
create_flags,
ref buffer,
@ -200,7 +200,7 @@ impl AccelerationStructure {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -370,7 +370,7 @@ impl AccelerationStructureCreateInfo {
}
}
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
create_flags,
ref buffer,
@ -397,26 +397,26 @@ impl AccelerationStructureCreateInfo {
.usage()
.intersects(BufferUsage::ACCELERATION_STRUCTURE_STORAGE)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "buffer".into(),
problem: "the buffer was not created with the `ACCELERATION_STRUCTURE_STORAGE` \
usage"
.into(),
vuids: &["VUID-VkAccelerationStructureCreateInfoKHR-buffer-03614"],
..Default::default()
});
}));
}
// VUID-VkAccelerationStructureCreateInfoKHR-offset-03616
// Ensured by the definition of `Subbuffer`.
if buffer.offset() % 256 != 0 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "buffer".into(),
problem: "the offset of the buffer is not a multiple of 256".into(),
vuids: &["VUID-VkAccelerationStructureCreateInfoKHR-offset-03734"],
..Default::default()
});
}));
}
Ok(())
@ -503,7 +503,7 @@ impl AccelerationStructureBuildGeometryInfo {
}
}
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
flags,
ref mode,
@ -537,12 +537,12 @@ impl AccelerationStructureBuildGeometryInfo {
}
if geometries.len() as u64 > max_geometry_count {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "geometries".into(),
problem: "the length exceeds the `max_geometry_count` limit".into(),
vuids: &["VUID-VkAccelerationStructureBuildGeometryInfoKHR-type-03793"],
..Default::default()
});
}));
}
// VUID-VkAccelerationStructureBuildGeometryInfoKHR-type-03795
@ -558,12 +558,12 @@ impl AccelerationStructureBuildGeometryInfo {
}
if geometries.len() as u64 > max_geometry_count {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "geometries".into(),
problem: "the length exceeds the `max_geometry_count` limit".into(),
vuids: &["VUID-VkAccelerationStructureBuildGeometryInfoKHR-type-03793"],
..Default::default()
});
}));
}
// VUID-VkAccelerationStructureBuildGeometryInfoKHR-type-03794
@ -589,14 +589,14 @@ impl AccelerationStructureBuildGeometryInfo {
BuildAccelerationStructureFlags::PREFER_FAST_TRACE
| BuildAccelerationStructureFlags::PREFER_FAST_BUILD,
) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "flags".into(),
problem: "contains both `BuildAccelerationStructureFlags::PREFER_FAST_TRACE` and \
`BuildAccelerationStructureFlags::PREFER_FAST_BUILD`"
.into(),
vuids: &["VUID-VkAccelerationStructureBuildGeometryInfoKHR-flags-03796"],
..Default::default()
});
}));
}
Ok(())
@ -997,7 +997,7 @@ impl AccelerationStructureGeometryTrianglesData {
}
}
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
flags,
vertex_format,
@ -1034,14 +1034,14 @@ impl AccelerationStructureGeometryTrianglesData {
.buffer_features
.intersects(FormatFeatures::ACCELERATION_STRUCTURE_VERTEX_BUFFER)
} {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "vertex_format".into(),
problem: "format features do not contain \
`FormatFeature::ACCELERATION_STRUCTURE_VERTEX_BUFFER`"
.into(),
vuids: &["VUID-VkAccelerationStructureGeometryTrianglesDataKHR-vertexFormat-03797"],
..Default::default()
});
}));
}
let smallest_component_bits = vertex_format
@ -1053,25 +1053,25 @@ impl AccelerationStructureGeometryTrianglesData {
let smallest_component_bytes = (smallest_component_bits + 7) & !7;
if vertex_stride % smallest_component_bytes != 0 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`vertex_stride` is not a multiple of the byte size of the \
smallest component of `vertex_format`"
.into(),
vuids: &["VUID-VkAccelerationStructureGeometryTrianglesDataKHR-vertexStride-03735"],
..Default::default()
});
}));
}
if let Some(index_data) = index_data.as_ref() {
if !matches!(index_data, IndexBuffer::U16(_) | IndexBuffer::U32(_)) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "index_data".into(),
problem: "is not `IndexBuffer::U16` or `IndexBuffer::U32`".into(),
vuids: &[
"VUID-VkAccelerationStructureGeometryTrianglesDataKHR-indexType-03798",
],
..Default::default()
});
}));
}
}
@ -1119,7 +1119,7 @@ impl AccelerationStructureGeometryAabbsData {
}
}
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
flags,
data: _,
@ -1136,12 +1136,12 @@ impl AccelerationStructureGeometryAabbsData {
})?;
if stride % 8 != 0 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "stride".into(),
problem: "is not a multiple of 8".into(),
vuids: &["VUID-VkAccelerationStructureGeometryAabbsDataKHR-stride-03545"],
..Default::default()
});
}));
}
Ok(())
@ -1192,7 +1192,7 @@ impl AccelerationStructureGeometryInstancesData {
}
}
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
flags,
data: _,
@ -1390,7 +1390,7 @@ impl CopyAccelerationStructureInfo {
}
}
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
ref src,
ref dst,
@ -1413,22 +1413,22 @@ impl CopyAccelerationStructureInfo {
mode,
CopyAccelerationStructureMode::Compact | CopyAccelerationStructureMode::Clone
) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "mode".into(),
problem: "is not `CopyAccelerationStructureMode::Compact` or \
`CopyAccelerationStructureMode::Clone`"
.into(),
vuids: &["VUID-VkCopyAccelerationStructureInfoKHR-mode-03410"],
..Default::default()
});
}));
}
if src.buffer() == dst.buffer() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`src` and `dst` share the same buffer".into(),
vuids: &["VUID-VkCopyAccelerationStructureInfoKHR-dst-07791"],
..Default::default()
});
}));
}
// VUID-VkCopyAccelerationStructureInfoKHR-src-04963
@ -1474,7 +1474,7 @@ impl CopyAccelerationStructureToMemoryInfo {
}
}
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
ref src,
ref dst,
@ -1493,12 +1493,12 @@ impl CopyAccelerationStructureToMemoryInfo {
})?;
if !matches!(mode, CopyAccelerationStructureMode::Serialize) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "mode".into(),
problem: "is not `CopyAccelerationStructureMode::Serialize`".into(),
vuids: &["VUID-VkCopyAccelerationStructureToMemoryInfoKHR-mode-03412"],
..Default::default()
});
}));
}
// VUID-VkCopyAccelerationStructureToMemoryInfoKHR-src-04959
@ -1544,7 +1544,7 @@ impl CopyMemoryToAccelerationStructureInfo {
}
}
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
ref src,
ref dst,
@ -1563,12 +1563,12 @@ impl CopyMemoryToAccelerationStructureInfo {
})?;
if !matches!(mode, CopyAccelerationStructureMode::Deserialize) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "mode".into(),
problem: "is not `CopyAccelerationStructureMode::Deserialize`".into(),
vuids: &["VUID-VkCopyMemoryToAccelerationStructureInfoKHR-mode-03413"],
..Default::default()
});
}));
}
// VUID-VkCopyMemoryToAccelerationStructureInfoKHR-src-04960

View File

@ -22,7 +22,7 @@ use crate::{
},
DeviceAlignment,
},
DeviceSize, NonZeroDeviceSize,
DeviceSize, NonZeroDeviceSize, Validated,
};
use crossbeam_queue::ArrayQueue;
use std::{
@ -355,7 +355,7 @@ where
DeviceLayout::from_size_alignment(self.arena_size, 1).unwrap(),
)
.map_err(|err| match err {
BufferAllocateError::AllocateMemory(err) => err,
Validated::Error(BufferAllocateError::AllocateMemory(err)) => err,
// We don't use sparse-binding, concurrent sharing or external memory, therefore the
// other errors can't happen.
_ => unreachable!(),

View File

@ -116,7 +116,7 @@ use crate::{
},
range_map::RangeMap,
sync::{future::AccessError, AccessConflict, CurrentAccess, Sharing},
DeviceSize, NonZeroDeviceSize, Requires, RequiresAllOf, RequiresOneOf, RuntimeError,
DeviceSize, NonZeroDeviceSize, Requires, RequiresAllOf, RequiresOneOf, Validated,
ValidationError, Version, VulkanError, VulkanObject,
};
use parking_lot::{Mutex, MutexGuard};
@ -262,14 +262,14 @@ impl Buffer {
/// - Panics if the chosen memory type is not host-visible.
pub fn from_data<T>(
allocator: &(impl MemoryAllocator + ?Sized),
buffer_info: BufferCreateInfo,
create_info: BufferCreateInfo,
allocation_info: AllocationCreateInfo,
data: T,
) -> Result<Subbuffer<T>, BufferAllocateError>
) -> Result<Subbuffer<T>, Validated<BufferAllocateError>>
where
T: BufferContents,
{
let buffer = Buffer::new_sized(allocator, buffer_info, allocation_info)?;
let buffer = Buffer::new_sized(allocator, create_info, allocation_info)?;
{
let mut write_guard = buffer
@ -295,10 +295,10 @@ impl Buffer {
/// - Panics if `iter` is empty.
pub fn from_iter<T, I>(
allocator: &(impl MemoryAllocator + ?Sized),
buffer_info: BufferCreateInfo,
create_info: BufferCreateInfo,
allocation_info: AllocationCreateInfo,
iter: I,
) -> Result<Subbuffer<[T]>, BufferAllocateError>
) -> Result<Subbuffer<[T]>, Validated<BufferAllocateError>>
where
T: BufferContents,
I: IntoIterator<Item = T>,
@ -307,7 +307,7 @@ impl Buffer {
let iter = iter.into_iter();
let buffer = Buffer::new_slice(
allocator,
buffer_info,
create_info,
allocation_info,
iter.len().try_into().unwrap(),
)?;
@ -333,16 +333,16 @@ impl Buffer {
/// - Panics if `buffer_info.size` is not zero.
pub fn new_sized<T>(
allocator: &(impl MemoryAllocator + ?Sized),
buffer_info: BufferCreateInfo,
create_info: BufferCreateInfo,
allocation_info: AllocationCreateInfo,
) -> Result<Subbuffer<T>, BufferAllocateError>
) -> Result<Subbuffer<T>, Validated<BufferAllocateError>>
where
T: BufferContents,
{
let layout = T::LAYOUT.unwrap_sized();
let buffer = Subbuffer::new(Buffer::new(
allocator,
buffer_info,
create_info,
allocation_info,
layout,
)?);
@ -359,14 +359,14 @@ impl Buffer {
/// - Panics if `len` is zero.
pub fn new_slice<T>(
allocator: &(impl MemoryAllocator + ?Sized),
buffer_info: BufferCreateInfo,
create_info: BufferCreateInfo,
allocation_info: AllocationCreateInfo,
len: DeviceSize,
) -> Result<Subbuffer<[T]>, BufferAllocateError>
) -> Result<Subbuffer<[T]>, Validated<BufferAllocateError>>
where
T: BufferContents,
{
Buffer::new_unsized(allocator, buffer_info, allocation_info, len)
Buffer::new_unsized(allocator, create_info, allocation_info, len)
}
/// Creates a new uninitialized `Buffer` for unsized data. Returns a [`Subbuffer`] spanning the
@ -378,10 +378,10 @@ impl Buffer {
/// - Panics if `len` is zero.
pub fn new_unsized<T>(
allocator: &(impl MemoryAllocator + ?Sized),
buffer_info: BufferCreateInfo,
create_info: BufferCreateInfo,
allocation_info: AllocationCreateInfo,
len: DeviceSize,
) -> Result<Subbuffer<T>, BufferAllocateError>
) -> Result<Subbuffer<T>, Validated<BufferAllocateError>>
where
T: BufferContents + ?Sized,
{
@ -389,7 +389,7 @@ impl Buffer {
let layout = T::LAYOUT.layout_for_len(len).unwrap();
let buffer = Subbuffer::new(Buffer::new(
allocator,
buffer_info,
create_info,
allocation_info,
layout,
)?);
@ -405,24 +405,27 @@ impl Buffer {
/// - Panics if `layout.alignment()` is greater than 64.
pub fn new(
allocator: &(impl MemoryAllocator + ?Sized),
mut buffer_info: BufferCreateInfo,
mut create_info: BufferCreateInfo,
allocation_info: AllocationCreateInfo,
layout: DeviceLayout,
) -> Result<Arc<Self>, BufferAllocateError> {
) -> Result<Arc<Self>, Validated<BufferAllocateError>> {
assert!(layout.alignment().as_devicesize() <= 64);
// TODO: Enable once sparse binding materializes
// assert!(!allocate_info.flags.contains(BufferCreateFlags::SPARSE_BINDING));
assert!(
buffer_info.size == 0,
create_info.size == 0,
"`Buffer::new*` functions set the `buffer_info.size` field themselves, you should not \
set it yourself",
);
buffer_info.size = layout.size();
create_info.size = layout.size();
let raw_buffer = RawBuffer::new(allocator.device().clone(), buffer_info)
.map_err(BufferAllocateError::CreateBuffer)?;
let raw_buffer =
RawBuffer::new(allocator.device().clone(), create_info).map_err(|err| match err {
Validated::Error(err) => Validated::Error(BufferAllocateError::CreateBuffer(err)),
Validated::ValidationError(err) => err.into(),
})?;
let mut requirements = *raw_buffer.memory_requirements();
requirements.layout = requirements.layout.align_to(layout.alignment()).unwrap();
@ -448,7 +451,7 @@ impl Buffer {
unsafe { raw_buffer.bind_memory_unchecked(allocation) }
.map(Arc::new)
.map_err(|(err, _, _)| BufferAllocateError::BindMemory(err))
.map_err(|(err, _, _)| BufferAllocateError::BindMemory(err).into())
}
fn from_raw(inner: RawBuffer, memory: BufferMemory) -> Self {
@ -505,32 +508,32 @@ impl Buffer {
/// Returns the device address for this buffer.
// TODO: Caching?
pub fn device_address(&self) -> Result<NonZeroDeviceSize, ValidationError> {
pub fn device_address(&self) -> Result<NonZeroDeviceSize, Box<ValidationError>> {
self.validate_device_address()?;
unsafe { Ok(self.device_address_unchecked()) }
}
fn validate_device_address(&self) -> Result<(), ValidationError> {
fn validate_device_address(&self) -> Result<(), Box<ValidationError>> {
let device = self.device();
if !device.enabled_features().buffer_device_address {
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"buffer_device_address",
)])]),
vuids: &["VUID-vkGetBufferDeviceAddress-bufferDeviceAddress-03324"],
..Default::default()
});
}));
}
if !self.usage().intersects(BufferUsage::SHADER_DEVICE_ADDRESS) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "self.usage()".into(),
problem: "does not contain `BufferUsage::SHADER_DEVICE_ADDRESS`".into(),
vuids: &["VUID-VkBufferDeviceAddressInfo-buffer-02601"],
..Default::default()
});
}));
}
Ok(())
@ -601,7 +604,7 @@ impl Hash for Buffer {
pub enum BufferAllocateError {
CreateBuffer(VulkanError),
AllocateMemory(MemoryAllocatorError),
BindMemory(RuntimeError),
BindMemory(VulkanError),
}
impl Error for BufferAllocateError {
@ -624,6 +627,12 @@ impl Display for BufferAllocateError {
}
}
impl From<BufferAllocateError> for Validated<BufferAllocateError> {
fn from(err: BufferAllocateError) -> Self {
Self::Error(err)
}
}
/// The current state of a buffer.
#[derive(Debug)]
pub(crate) struct BufferState {
@ -915,7 +924,10 @@ impl ExternalBufferInfo {
}
}
pub(crate) fn validate(&self, physical_device: &PhysicalDevice) -> Result<(), ValidationError> {
pub(crate) fn validate(
&self,
physical_device: &PhysicalDevice,
) -> Result<(), Box<ValidationError>> {
let &Self {
handle_type,
usage,
@ -932,12 +944,12 @@ impl ExternalBufferInfo {
})?;
if usage.is_empty() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "usage".into(),
problem: "is empty".into(),
vuids: &["VUID-VkPhysicalDeviceExternalBufferInfo-usage-requiredbitmask"],
..Default::default()
});
}));
}
handle_type

View File

@ -134,7 +134,7 @@ impl<T: ?Sized> Subbuffer<T> {
}
/// Returns the device address for this subbuffer.
pub fn device_address(&self) -> Result<NonZeroDeviceSize, ValidationError> {
pub fn device_address(&self) -> Result<NonZeroDeviceSize, Box<ValidationError>> {
self.buffer().device_address().map(|ptr| {
// SAFETY: The original address came from the Vulkan implementation, and allocation
// sizes are guaranteed to not exceed `DeviceLayout::MAX_SIZE`, so the offset better be

View File

@ -24,7 +24,7 @@ use crate::{
MemoryPropertyFlags, MemoryRequirements,
},
sync::Sharing,
DeviceSize, Requires, RequiresAllOf, RequiresOneOf, RuntimeError, ValidationError, Version,
DeviceSize, Requires, RequiresAllOf, RequiresOneOf, Validated, ValidationError, Version,
VulkanError, VulkanObject,
};
use smallvec::SmallVec;
@ -60,7 +60,10 @@ impl RawBuffer {
/// - Panics if `create_info.size` is zero.
/// - Panics if `create_info.usage` is empty.
#[inline]
pub fn new(device: Arc<Device>, create_info: BufferCreateInfo) -> Result<Self, VulkanError> {
pub fn new(
device: Arc<Device>,
create_info: BufferCreateInfo,
) -> Result<Self, Validated<VulkanError>> {
Self::validate_new(&device, &create_info)?;
unsafe { Ok(Self::new_unchecked(device, create_info)?) }
@ -69,7 +72,7 @@ impl RawBuffer {
fn validate_new(
device: &Device,
create_info: &BufferCreateInfo,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
create_info
.validate(device)
.map_err(|err| err.add_context("create_info"))?;
@ -81,7 +84,7 @@ impl RawBuffer {
pub unsafe fn new_unchecked(
device: Arc<Device>,
create_info: BufferCreateInfo,
) -> Result<Self, RuntimeError> {
) -> Result<Self, VulkanError> {
let &BufferCreateInfo {
flags,
ref sharing,
@ -133,7 +136,7 @@ impl RawBuffer {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -274,7 +277,7 @@ impl RawBuffer {
pub fn bind_memory(
self,
allocation: MemoryAlloc,
) -> Result<Buffer, (VulkanError, RawBuffer, MemoryAlloc)> {
) -> Result<Buffer, (Validated<VulkanError>, RawBuffer, MemoryAlloc)> {
if let Err(err) = self.validate_bind_memory(&allocation) {
return Err((err.into(), self, allocation));
}
@ -283,7 +286,7 @@ impl RawBuffer {
.map_err(|(err, buffer, allocation)| (err.into(), buffer, allocation))
}
fn validate_bind_memory(&self, allocation: &MemoryAlloc) -> Result<(), ValidationError> {
fn validate_bind_memory(&self, allocation: &MemoryAlloc) -> Result<(), Box<ValidationError>> {
assert_ne!(allocation.allocation_type(), AllocationType::NonLinear);
let memory_requirements = &self.memory_requirements;
@ -309,58 +312,58 @@ impl RawBuffer {
// Assume that `allocation` was created correctly.
if memory_requirements.memory_type_bits & (1 << memory.memory_type_index()) == 0 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`allocation.device_memory().memory_type_index()` is not a bit set in \
`self.memory_requirements().memory_type_bits`"
.into(),
vuids: &["VUID-VkBindBufferMemoryInfo-memory-01035"],
..Default::default()
});
}));
}
if !is_aligned(memory_offset, memory_requirements.layout.alignment()) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`allocation.offset()` is not aligned according to \
`self.memory_requirements().layout.alignment()`"
.into(),
vuids: &["VUID-VkBindBufferMemoryInfo-memoryOffset-01036"],
..Default::default()
});
}));
}
if allocation.size() < memory_requirements.layout.size() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`allocation.size()` is less than \
`self.memory_requirements().layout.size()`"
.into(),
vuids: &["VUID-VkBindBufferMemoryInfo-size-01037"],
..Default::default()
});
}));
}
if let Some(dedicated_to) = memory.dedicated_to() {
match dedicated_to {
DedicatedTo::Buffer(id) if id == self.id => {}
_ => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`allocation.device_memory()` is a dedicated allocation, but \
it is not dedicated to this buffer"
.into(),
vuids: &["VUID-VkBindBufferMemoryInfo-memory-01508"],
..Default::default()
});
}));
}
}
debug_assert!(memory_offset == 0); // This should be ensured by the allocator
} else {
if memory_requirements.requires_dedicated_allocation {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`self.memory_requirements().requires_dedicated_allocation` is \
`true`, but `allocation.device_memory()` is not a dedicated allocation"
.into(),
vuids: &["VUID-VkBindBufferMemoryInfo-buffer-01444"],
..Default::default()
});
}));
}
}
@ -368,13 +371,13 @@ impl RawBuffer {
.property_flags
.intersects(MemoryPropertyFlags::PROTECTED)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the `property_flags` of the memory type of \
`allocation.device_memory()` contains `MemoryPropertyFlags::PROTECTED`"
.into(),
vuids: &["VUID-VkBindBufferMemoryInfo-None-01899"],
..Default::default()
});
}));
}
if !memory.export_handle_types().is_empty()
@ -382,26 +385,26 @@ impl RawBuffer {
.external_memory_handle_types
.intersects(memory.export_handle_types())
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`allocation.device_memory().export_handle_types()` is not empty, but \
it does not share at least one memory type with \
`self.external_memory_handle_types()`"
.into(),
vuids: &["VUID-VkBindBufferMemoryInfo-memory-02726"],
..Default::default()
});
}));
}
if let Some(handle_type) = memory.imported_handle_type() {
if !self.external_memory_handle_types.contains_enum(handle_type) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`allocation.device_memory()` is imported, but \
`self.external_memory_handle_types()` does not contain the imported \
handle type"
.into(),
vuids: &["VUID-VkBindBufferMemoryInfo-memory-02985"],
..Default::default()
});
}));
}
}
@ -411,14 +414,14 @@ impl RawBuffer {
.flags()
.intersects(MemoryAllocateFlags::DEVICE_ADDRESS)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`self.usage()` contains `BufferUsage::SHADER_DEVICE_ADDRESS`, but \
`allocation.device_memory().flags()` does not contain \
`MemoryAllocateFlags::DEVICE_ADDRESS`"
.into(),
vuids: &["VUID-VkBindBufferMemoryInfo-bufferDeviceAddress-03339"],
..Default::default()
});
}));
}
Ok(())
@ -428,7 +431,7 @@ impl RawBuffer {
pub unsafe fn bind_memory_unchecked(
self,
allocation: MemoryAlloc,
) -> Result<Buffer, (RuntimeError, RawBuffer, MemoryAlloc)> {
) -> Result<Buffer, (VulkanError, RawBuffer, MemoryAlloc)> {
let memory = allocation.device_memory();
let memory_offset = allocation.offset();
@ -468,7 +471,7 @@ impl RawBuffer {
.result();
if let Err(err) = result {
return Err((RuntimeError::from(err), self, allocation));
return Err((VulkanError::from(err), self, allocation));
}
Ok(Buffer::from_raw(self, BufferMemory::Normal(allocation)))
@ -594,7 +597,7 @@ impl Default for BufferCreateInfo {
}
impl BufferCreateInfo {
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
flags,
ref sharing,
@ -621,56 +624,56 @@ impl BufferCreateInfo {
})?;
if usage.is_empty() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "usage".into(),
problem: "is empty".into(),
vuids: &["VUID-VkBufferCreateInfo-usage-requiredbitmask"],
..Default::default()
});
}));
}
if size == 0 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "size".into(),
problem: "is zero".into(),
vuids: &["VUID-VkBufferCreateInfo-size-00912"],
..Default::default()
});
}));
}
/* Enable when sparse binding is properly handled
if let Some(sparse_level) = sparse {
if !device.enabled_features().sparse_binding {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "sparse".into(),
problem: "is `Some`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"sparse_binding",
)])]),
vuids: &["VUID-VkBufferCreateInfo-flags-00915"],
});
}));
}
if sparse_level.sparse_residency && !device.enabled_features().sparse_residency_buffer {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "sparse".into(),
problem: "contains `BufferCreateFlags::SPARSE_RESIDENCY`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"sparse_residency_buffer",
)])]),
vuids: &["VUID-VkBufferCreateInfo-flags-00916"],
});
}));
}
if sparse_level.sparse_aliased && !device.enabled_features().sparse_residency_aliased {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "sparse".into(),
problem: "contains `BufferCreateFlags::SPARSE_ALIASED`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"sparse_residency_aliased",
)])]),
vuids: &["VUID-VkBufferCreateInfo-flags-00917"],
});
}));
}
// TODO:
@ -681,13 +684,13 @@ impl BufferCreateInfo {
Sharing::Exclusive => (),
Sharing::Concurrent(queue_family_indices) => {
if queue_family_indices.len() < 2 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "sharing".into(),
problem: "is `Sharing::Concurrent`, but contains less than 2 elements"
.into(),
vuids: &["VUID-VkBufferCreateInfo-sharingMode-00914"],
..Default::default()
});
}));
}
let queue_family_count =
@ -695,7 +698,7 @@ impl BufferCreateInfo {
for (index, &queue_family_index) in queue_family_indices.iter().enumerate() {
if queue_family_indices[..index].contains(&queue_family_index) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "queue_family_indices".into(),
problem: format!(
"the queue family index in the list at index {} is contained in \
@ -705,17 +708,17 @@ impl BufferCreateInfo {
.into(),
vuids: &["VUID-VkBufferCreateInfo-sharingMode-01419"],
..Default::default()
});
}));
}
if queue_family_index >= queue_family_count {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("sharing[{}]", index).into(),
problem: "is not less than the number of queue families in the device"
.into(),
vuids: &["VUID-VkBufferCreateInfo-sharingMode-01419"],
..Default::default()
});
}));
}
}
}
@ -723,12 +726,12 @@ impl BufferCreateInfo {
if let Some(max_buffer_size) = device.physical_device().properties().max_buffer_size {
if size > max_buffer_size {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "size".into(),
problem: "exceeds the `max_buffer_size` limit".into(),
vuids: &["VUID-VkBufferCreateInfo-size-06409"],
..Default::default()
});
}));
}
}
@ -736,7 +739,7 @@ impl BufferCreateInfo {
if !(device.api_version() >= Version::V1_1
|| device.enabled_extensions().khr_external_memory)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "external_memory_handle_types".into(),
problem: "is not empty".into(),
requires_one_of: RequiresOneOf(&[
@ -744,7 +747,7 @@ impl BufferCreateInfo {
RequiresAllOf(&[Requires::DeviceExtension("khr_external_memory")]),
]),
..Default::default()
});
}));
}
external_memory_handle_types

View File

@ -53,7 +53,7 @@ use crate::{
format::{Format, FormatFeatures},
macros::impl_id_counter,
memory::{is_aligned, DeviceAlignment},
DeviceSize, RuntimeError, ValidationError, Version, VulkanError, VulkanObject,
DeviceSize, Validated, ValidationError, Version, VulkanError, VulkanObject,
};
use std::{mem::MaybeUninit, num::NonZeroU64, ops::Range, ptr, sync::Arc};
@ -76,7 +76,7 @@ impl BufferView {
pub fn new(
subbuffer: Subbuffer<impl ?Sized>,
create_info: BufferViewCreateInfo,
) -> Result<Arc<BufferView>, VulkanError> {
) -> Result<Arc<BufferView>, Validated<VulkanError>> {
let subbuffer = subbuffer.into_bytes();
Self::validate_new(&subbuffer, &create_info)?;
@ -86,7 +86,7 @@ impl BufferView {
fn validate_new(
subbuffer: &Subbuffer<[u8]>,
create_info: &BufferViewCreateInfo,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
let device = subbuffer.device();
create_info
@ -110,66 +110,66 @@ impl BufferView {
.usage()
.intersects(BufferUsage::UNIFORM_TEXEL_BUFFER | BufferUsage::STORAGE_TEXEL_BUFFER)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "subbuffer".into(),
problem: "was not created with the `BufferUsage::UNIFORM_TEXEL_BUFFER` \
or `BufferUsage::STORAGE_TEXEL_BUFFER` usage"
.into(),
vuids: &["VUID-VkBufferViewCreateInfo-buffer-00932"],
..Default::default()
});
}));
}
if buffer.usage().intersects(BufferUsage::UNIFORM_TEXEL_BUFFER)
&& !format_features.intersects(FormatFeatures::UNIFORM_TEXEL_BUFFER)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`subbuffer` was created with the `BufferUsage::UNIFORM_TEXEL_BUFFER` \
usage, but the format features of `create_info.format` do not include \
`FormatFeatures::UNIFORM_TEXEL_BUFFER`"
.into(),
vuids: &["VUID-VkBufferViewCreateInfo-buffer-00933"],
..Default::default()
});
}));
}
if buffer.usage().intersects(BufferUsage::STORAGE_TEXEL_BUFFER)
&& !format_features.intersects(FormatFeatures::STORAGE_TEXEL_BUFFER)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`subbuffer` was created with the `BufferUsage::STORAGE_TEXEL_BUFFER` \
usage, but the format features of `create_info.format` do not include \
`FormatFeatures::STORAGE_TEXEL_BUFFER`"
.into(),
vuids: &["VUID-VkBufferViewCreateInfo-buffer-00934"],
..Default::default()
});
}));
}
let block_size = format.block_size().unwrap();
let texels_per_block = format.texels_per_block();
if subbuffer.size() % block_size != 0 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`subbuffer.size()` is not a multiple of \
`create_info.format.block_size()`"
.into(),
vuids: &["VUID-VkBufferViewCreateInfo-range-00929"],
..Default::default()
});
}));
}
if ((subbuffer.size() / block_size) * texels_per_block as DeviceSize) as u32
> properties.max_texel_buffer_elements
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`subbuffer.size() / create_info.format.block_size() * \
create_info.format.texels_per_block()` is greater than the \
`max_texel_buffer_elements` limit"
.into(),
vuids: &["VUID-VkBufferViewCreateInfo-range-00930"],
..Default::default()
});
}));
}
if device.api_version() >= Version::V1_3 || device.enabled_features().texel_buffer_alignment
@ -193,7 +193,7 @@ impl BufferView {
.unwrap()
.min(element_size),
) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`subbuffer` was created with the \
`BufferUsage::STORAGE_TEXEL_BUFFER` usage, and the \
`storage_texel_buffer_offset_single_texel_alignment` \
@ -204,7 +204,7 @@ impl BufferView {
.into(),
vuids: &["VUID-VkBufferViewCreateInfo-buffer-02750"],
..Default::default()
});
}));
}
} else {
if !is_aligned(
@ -213,7 +213,7 @@ impl BufferView {
.storage_texel_buffer_offset_alignment_bytes
.unwrap(),
) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`subbuffer` was created with the \
`BufferUsage::STORAGE_TEXEL_BUFFER` usage, and the \
`storage_texel_buffer_offset_single_texel_alignment` \
@ -223,7 +223,7 @@ impl BufferView {
.into(),
vuids: &["VUID-VkBufferViewCreateInfo-buffer-02750"],
..Default::default()
});
}));
}
}
}
@ -240,7 +240,7 @@ impl BufferView {
.unwrap()
.min(element_size),
) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`subbuffer` was created with the \
`BufferUsage::UNIFORM_TEXEL_BUFFER` usage, and the \
`uniform_texel_buffer_offset_single_texel_alignment` \
@ -251,7 +251,7 @@ impl BufferView {
.into(),
vuids: &["VUID-VkBufferViewCreateInfo-buffer-02751"],
..Default::default()
});
}));
}
} else {
if !is_aligned(
@ -260,7 +260,7 @@ impl BufferView {
.uniform_texel_buffer_offset_alignment_bytes
.unwrap(),
) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`subbuffer` was created with the \
`BufferUsage::UNIFORM_TEXEL_BUFFER` usage, and the \
`uniform_texel_buffer_offset_single_texel_alignment` \
@ -270,7 +270,7 @@ impl BufferView {
.into(),
vuids: &["VUID-VkBufferViewCreateInfo-buffer-02751"],
..Default::default()
});
}));
}
}
}
@ -279,13 +279,13 @@ impl BufferView {
subbuffer.offset(),
properties.min_texel_buffer_offset_alignment,
) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`subbuffer.offset()` is not a multiple of the \
`min_texel_buffer_offset_alignment` limit"
.into(),
vuids: &["VUID-VkBufferViewCreateInfo-offset-02749"],
..Default::default()
});
}));
}
}
@ -296,7 +296,7 @@ impl BufferView {
pub unsafe fn new_unchecked(
subbuffer: Subbuffer<impl ?Sized>,
create_info: BufferViewCreateInfo,
) -> Result<Arc<BufferView>, RuntimeError> {
) -> Result<Arc<BufferView>, VulkanError> {
let &BufferViewCreateInfo { format, _ne: _ } = &create_info;
let device = subbuffer.device();
@ -320,7 +320,7 @@ impl BufferView {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -438,7 +438,7 @@ impl Default for BufferViewCreateInfo {
}
impl BufferViewCreateInfo {
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let Self { format, _ne: _ } = self;
let format = format.ok_or(ValidationError {

File diff suppressed because it is too large Load Diff

View File

@ -766,14 +766,14 @@ where
pipeline_layout: &PipelineLayout,
set_num: u32,
descriptor_writes: &[WriteDescriptorSet],
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
if !self.device().enabled_extensions().khr_push_descriptor {
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceExtension(
"khr_push_descriptor",
)])]),
..Default::default()
});
}));
}
pipeline_bind_point
@ -792,7 +792,7 @@ where
.queue_flags
.intersects(QueueFlags::COMPUTE)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "self".into(),
problem: "`pipeline_bind_point` is `PipelineBindPoint::Compute`, and the \
queue family does not support compute operations"
@ -802,7 +802,7 @@ where
"VUID-vkCmdPushDescriptorSetKHR-commandBuffer-cmdpool",
],
..Default::default()
});
}));
}
}
PipelineBindPoint::Graphics => {
@ -810,7 +810,7 @@ where
.queue_flags
.intersects(QueueFlags::GRAPHICS)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "self".into(),
problem: "`pipeline_bind_point` is `PipelineBindPoint::Graphics`, and the \
queue family does not support graphics operations"
@ -820,7 +820,7 @@ where
"VUID-vkCmdPushDescriptorSetKHR-commandBuffer-cmdpool",
],
..Default::default()
});
}));
}
}
}
@ -829,13 +829,13 @@ where
assert_eq!(self.device(), pipeline_layout.device());
if set_num as usize > pipeline_layout.set_layouts().len() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`set_num` is greater than the number of descriptor set layouts in \
`pipeline_layout`"
.into(),
vuids: &["VUID-vkCmdPushDescriptorSetKHR-set-00364"],
..Default::default()
});
}));
}
let descriptor_set_layout = &pipeline_layout.set_layouts()[set_num as usize];
@ -844,14 +844,14 @@ where
.flags()
.intersects(DescriptorSetLayoutCreateFlags::PUSH_DESCRIPTOR)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the descriptor set layout with the number `set_num` in \
`pipeline_layout` was not created with the \
`DescriptorSetLayoutCreateFlags::PUSH_DESCRIPTOR` flag"
.into(),
vuids: &["VUID-vkCmdPushDescriptorSetKHR-set-00365"],
..Default::default()
});
}));
}
for (index, write) in descriptor_writes.iter().enumerate() {

View File

@ -2675,7 +2675,7 @@ pub enum DescriptorResourceInvalidError {
image_view_set_num: u32,
image_view_binding_num: u32,
image_view_index: u32,
error: ValidationError,
error: Box<ValidationError>,
},
SamplerUnnormalizedCoordinatesNotAllowed,
SamplerYcbcrConversionNotAllowed,

View File

@ -20,7 +20,7 @@ use crate::{
device::{Device, DeviceOwned},
instance::InstanceOwnedDebugWrapper,
macros::impl_id_counter,
OomError, Requires, RequiresAllOf, RequiresOneOf, RuntimeError, Version, VulkanObject,
OomError, Requires, RequiresAllOf, RequiresOneOf, Version, VulkanError, VulkanObject,
};
use smallvec::SmallVec;
use std::{
@ -170,7 +170,7 @@ impl CommandPool {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -196,7 +196,7 @@ impl CommandPool {
let fns = self.device.fns();
(fns.v1_0.reset_command_pool)(self.device.handle(), self.handle, flags)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
Ok(())
}
@ -233,7 +233,7 @@ impl CommandPool {
out.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
out.set_len(command_buffer_count as usize);
out
}
@ -390,10 +390,10 @@ impl Display for CommandPoolCreationError {
}
}
impl From<RuntimeError> for CommandPoolCreationError {
fn from(err: RuntimeError) -> Self {
impl From<VulkanError> for CommandPoolCreationError {
fn from(err: VulkanError) -> Self {
match err {
err @ RuntimeError::OutOfHostMemory => Self::OomError(OomError::from(err)),
err @ VulkanError::OutOfHostMemory => Self::OomError(OomError::from(err)),
_ => panic!("unexpected error: {:?}", err),
}
}
@ -522,8 +522,8 @@ impl Display for CommandPoolTrimError {
}
}
impl From<RuntimeError> for CommandPoolTrimError {
fn from(err: RuntimeError) -> CommandPoolTrimError {
impl From<VulkanError> for CommandPoolTrimError {
fn from(err: VulkanError) -> CommandPoolTrimError {
panic!("unexpected error: {:?}", err)
}
}

View File

@ -21,7 +21,7 @@ use crate::{
},
device::{Device, DeviceOwned},
query::QueryControlFlags,
OomError, RuntimeError, VulkanObject,
OomError, VulkanError, VulkanObject,
};
use smallvec::SmallVec;
use std::{fmt::Debug, ptr, sync::Arc};
@ -173,7 +173,7 @@ where
let fns = builder_alloc.device().fns();
(fns.v1_0.begin_command_buffer)(builder_alloc.inner().handle(), &begin_info_vk)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
}
Ok(UnsafeCommandBufferBuilder {
@ -191,7 +191,7 @@ where
let fns = self.device().fns();
(fns.v1_0.end_command_buffer)(self.handle())
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
Ok(UnsafeCommandBuffer {
alloc: self.builder_alloc.into_alloc(),

View File

@ -19,7 +19,7 @@
use crate::{
device::{Device, DeviceOwned},
instance::InstanceOwnedDebugWrapper,
Requires, RequiresAllOf, RequiresOneOf, RuntimeError, VulkanObject,
Requires, RequiresAllOf, RequiresOneOf, VulkanError, VulkanObject,
};
use std::{
error::Error,
@ -66,7 +66,7 @@ impl DeferredOperation {
}
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
pub unsafe fn new_unchecked(device: Arc<Device>) -> Result<Arc<Self>, RuntimeError> {
pub unsafe fn new_unchecked(device: Arc<Device>) -> Result<Arc<Self>, VulkanError> {
let handle = {
let fns = device.fns();
let mut output = MaybeUninit::uninit();
@ -75,7 +75,7 @@ impl DeferredOperation {
device.handle(), ptr::null(), output.as_mut_ptr()
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -99,7 +99,7 @@ impl DeferredOperation {
}
/// Executes a portion of the operation on the current thread.
pub fn join(&self) -> Result<DeferredOperationJoinStatus, RuntimeError> {
pub fn join(&self) -> Result<DeferredOperationJoinStatus, VulkanError> {
let result = unsafe {
let fns = self.device.fns();
(fns.khr_deferred_host_operations.deferred_operation_join_khr)(
@ -112,12 +112,12 @@ impl DeferredOperation {
ash::vk::Result::SUCCESS => Ok(DeferredOperationJoinStatus::Complete),
ash::vk::Result::THREAD_DONE_KHR => Ok(DeferredOperationJoinStatus::ThreadDone),
ash::vk::Result::THREAD_IDLE_KHR => Ok(DeferredOperationJoinStatus::ThreadIdle),
err => Err(RuntimeError::from(err)),
err => Err(VulkanError::from(err)),
}
}
/// Returns the result of the operation, or `None` if the operation is not yet complete.
pub fn result(&self) -> Option<Result<(), RuntimeError>> {
pub fn result(&self) -> Option<Result<(), VulkanError>> {
let result = unsafe {
let fns = self.device.fns();
(fns.khr_deferred_host_operations
@ -127,12 +127,12 @@ impl DeferredOperation {
match result {
ash::vk::Result::NOT_READY => None,
ash::vk::Result::SUCCESS => Some(Ok(())),
err => Some(Err(RuntimeError::from(err))),
err => Some(Err(VulkanError::from(err))),
}
}
/// Waits for the operation to complete, then returns its result.
pub fn wait(&self) -> Result<Result<(), RuntimeError>, RuntimeError> {
pub fn wait(&self) -> Result<Result<(), VulkanError>, VulkanError> {
// Based on example code on the extension's spec page.
// Call `join` until we get `Complete` or `ThreadDone`.
@ -210,7 +210,7 @@ unsafe impl DeviceOwned for DeferredOperation {
/// Error that can happen when creating a `DeferredOperation`.
#[derive(Clone, Debug)]
pub enum DeferredOperationCreateError {
RuntimeError(RuntimeError),
VulkanError(VulkanError),
RequirementNotMet {
required_for: &'static str,
@ -221,7 +221,7 @@ pub enum DeferredOperationCreateError {
impl Display for DeferredOperationCreateError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::RuntimeError(_) => write!(f, "a runtime error occurred"),
Self::VulkanError(_) => write!(f, "a runtime error occurred"),
Self::RequirementNotMet {
required_for,
requires_one_of,
@ -237,15 +237,15 @@ impl Display for DeferredOperationCreateError {
impl Error for DeferredOperationCreateError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
Self::RuntimeError(err) => Some(err),
Self::VulkanError(err) => Some(err),
_ => None,
}
}
}
impl From<RuntimeError> for DeferredOperationCreateError {
fn from(err: RuntimeError) -> Self {
Self::RuntimeError(err)
impl From<VulkanError> for DeferredOperationCreateError {
fn from(err: VulkanError) -> Self {
Self::VulkanError(err)
}
}

View File

@ -26,7 +26,7 @@ use crate::{
descriptor_set::layout::{DescriptorSetLayoutCreateFlags, DescriptorType},
device::{Device, DeviceOwned},
instance::InstanceOwnedDebugWrapper,
RuntimeError, VulkanError,
Validated, VulkanError,
};
use crossbeam_queue::ArrayQueue;
use std::{cell::UnsafeCell, mem::ManuallyDrop, num::NonZeroU64, sync::Arc, thread};
@ -60,7 +60,7 @@ pub unsafe trait DescriptorSetAllocator: DeviceOwned {
&self,
layout: &Arc<DescriptorSetLayout>,
variable_descriptor_count: u32,
) -> Result<Self::Alloc, RuntimeError>;
) -> Result<Self::Alloc, VulkanError>;
}
/// An allocated descriptor set.
@ -154,7 +154,7 @@ unsafe impl DescriptorSetAllocator for StandardDescriptorSetAllocator {
&self,
layout: &Arc<DescriptorSetLayout>,
variable_descriptor_count: u32,
) -> Result<StandardDescriptorSetAlloc, RuntimeError> {
) -> Result<StandardDescriptorSetAlloc, VulkanError> {
assert!(
!layout
.flags()
@ -197,7 +197,7 @@ unsafe impl DescriptorSetAllocator for Arc<StandardDescriptorSetAllocator> {
&self,
layout: &Arc<DescriptorSetLayout>,
variable_descriptor_count: u32,
) -> Result<Self::Alloc, RuntimeError> {
) -> Result<Self::Alloc, VulkanError> {
(**self).allocate(layout, variable_descriptor_count)
}
}
@ -221,7 +221,7 @@ struct FixedEntry {
}
impl FixedEntry {
fn new(layout: Arc<DescriptorSetLayout>) -> Result<Self, RuntimeError> {
fn new(layout: Arc<DescriptorSetLayout>) -> Result<Self, VulkanError> {
Ok(FixedEntry {
pool: FixedPool::new(&layout, MAX_SETS)?,
set_count: MAX_SETS,
@ -229,7 +229,7 @@ impl FixedEntry {
})
}
fn allocate(&mut self) -> Result<StandardDescriptorSetAlloc, RuntimeError> {
fn allocate(&mut self) -> Result<StandardDescriptorSetAlloc, VulkanError> {
let inner = if let Some(inner) = self.pool.reserve.pop() {
inner
} else {
@ -257,7 +257,7 @@ struct FixedPool {
}
impl FixedPool {
fn new(layout: &Arc<DescriptorSetLayout>, set_count: usize) -> Result<Arc<Self>, RuntimeError> {
fn new(layout: &Arc<DescriptorSetLayout>, set_count: usize) -> Result<Arc<Self>, VulkanError> {
let inner = DescriptorPool::new(
layout.device().clone(),
DescriptorPoolCreateInfo {
@ -273,7 +273,7 @@ impl FixedPool {
..Default::default()
},
)
.map_err(VulkanError::unwrap_runtime)?;
.map_err(Validated::unwrap)?;
let allocate_infos = (0..set_count).map(|_| DescriptorSetAllocateInfo {
layout,
@ -284,12 +284,12 @@ impl FixedPool {
inner
.allocate_descriptor_sets(allocate_infos)
.map_err(|err| match err {
RuntimeError::OutOfHostMemory | RuntimeError::OutOfDeviceMemory => err,
RuntimeError::FragmentedPool => {
VulkanError::OutOfHostMemory | VulkanError::OutOfDeviceMemory => err,
VulkanError::FragmentedPool => {
// This can't happen as we don't free individual sets.
unreachable!();
}
RuntimeError::OutOfPoolMemory => {
VulkanError::OutOfPoolMemory => {
// We created the pool with an exact size.
unreachable!();
}
@ -326,7 +326,7 @@ struct VariableEntry {
}
impl VariableEntry {
fn new(layout: Arc<DescriptorSetLayout>) -> Result<Self, RuntimeError> {
fn new(layout: Arc<DescriptorSetLayout>) -> Result<Self, VulkanError> {
let reserve = Arc::new(ArrayQueue::new(MAX_POOLS));
Ok(VariableEntry {
@ -340,7 +340,7 @@ impl VariableEntry {
fn allocate(
&mut self,
variable_descriptor_count: u32,
) -> Result<StandardDescriptorSetAlloc, RuntimeError> {
) -> Result<StandardDescriptorSetAlloc, VulkanError> {
if self.allocations >= MAX_SETS {
self.pool = if let Some(inner) = self.reserve.pop() {
Arc::new(VariablePool {
@ -363,12 +363,12 @@ impl VariableEntry {
.inner
.allocate_descriptor_sets([allocate_info])
.map_err(|err| match err {
RuntimeError::OutOfHostMemory | RuntimeError::OutOfDeviceMemory => err,
RuntimeError::FragmentedPool => {
VulkanError::OutOfHostMemory | VulkanError::OutOfDeviceMemory => err,
VulkanError::FragmentedPool => {
// This can't happen as we don't free individual sets.
unreachable!();
}
RuntimeError::OutOfPoolMemory => {
VulkanError::OutOfPoolMemory => {
// We created the pool to fit the maximum variable descriptor count.
unreachable!();
}
@ -399,7 +399,7 @@ impl VariablePool {
fn new(
layout: &Arc<DescriptorSetLayout>,
reserve: Arc<ArrayQueue<DescriptorPool>>,
) -> Result<Arc<Self>, RuntimeError> {
) -> Result<Arc<Self>, VulkanError> {
DescriptorPool::new(
layout.device().clone(),
DescriptorPoolCreateInfo {
@ -421,7 +421,7 @@ impl VariablePool {
reserve,
})
})
.map_err(VulkanError::unwrap_runtime)
.map_err(Validated::unwrap)
}
}

View File

@ -17,7 +17,7 @@ use crate::{
instance::InstanceOwnedDebugWrapper,
macros::{impl_id_counter, vulkan_bitflags, vulkan_enum},
shader::{DescriptorBindingRequirements, ShaderStages},
Requires, RequiresAllOf, RequiresOneOf, RuntimeError, ValidationError, Version, VulkanError,
Requires, RequiresAllOf, RequiresOneOf, Validated, ValidationError, Version, VulkanError,
VulkanObject,
};
use ahash::HashMap;
@ -42,7 +42,7 @@ impl DescriptorSetLayout {
pub fn new(
device: Arc<Device>,
create_info: DescriptorSetLayoutCreateInfo,
) -> Result<Arc<DescriptorSetLayout>, VulkanError> {
) -> Result<Arc<DescriptorSetLayout>, Validated<VulkanError>> {
Self::validate_new(&device, &create_info)?;
unsafe { Ok(Self::new_unchecked(device, create_info)?) }
@ -51,7 +51,7 @@ impl DescriptorSetLayout {
fn validate_new(
device: &Device,
create_info: &DescriptorSetLayoutCreateInfo,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
// VUID-vkCreateDescriptorSetLayout-pCreateInfo-parameter
create_info
.validate(device)
@ -77,13 +77,13 @@ impl DescriptorSetLayout {
.is_none()
}
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the total number of descriptors across all bindings is greater than \
the `max_per_set_descriptors` limit, and \
`device.descriptor_set_layout_support` returned `None`"
.into(),
..Default::default()
});
}));
}
}
@ -94,7 +94,7 @@ impl DescriptorSetLayout {
pub unsafe fn new_unchecked(
device: Arc<Device>,
create_info: DescriptorSetLayoutCreateInfo,
) -> Result<Arc<DescriptorSetLayout>, RuntimeError> {
) -> Result<Arc<DescriptorSetLayout>, VulkanError> {
let &DescriptorSetLayoutCreateInfo {
flags,
ref bindings,
@ -177,7 +177,7 @@ impl DescriptorSetLayout {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -322,7 +322,7 @@ pub struct DescriptorSetLayoutCreateInfo {
}
impl DescriptorSetLayoutCreateInfo {
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
flags,
ref bindings,
@ -366,7 +366,7 @@ impl DescriptorSetLayoutCreateInfo {
| DescriptorType::StorageBufferDynamic
| DescriptorType::InlineUniformBlock
) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: format!(
"`flags` contains `DescriptorSetLayoutCreateFlags::PUSH_DESCRIPTOR`, \
and `bindings[{}].descriptor_type` is
@ -381,11 +381,11 @@ impl DescriptorSetLayoutCreateInfo {
"VUID-VkDescriptorSetLayoutCreateInfo-flags-02208",
],
..Default::default()
});
}));
}
if binding_flags.intersects(DescriptorBindingFlags::VARIABLE_DESCRIPTOR_COUNT) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: format!(
"`flags` contains `DescriptorSetLayoutCreateFlags::PUSH_DESCRIPTOR`, \
and `bindings[{}].flags` contains \
@ -395,14 +395,14 @@ impl DescriptorSetLayoutCreateInfo {
.into(),
vuids: &["VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-flags-03003"],
..Default::default()
});
}));
}
}
if binding_flags.intersects(DescriptorBindingFlags::VARIABLE_DESCRIPTOR_COUNT)
&& Some(binding_num) != highest_binding_num
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: format!(
"`bindings[{}].flags` contains \
`DescriptorBindingFlags::VARIABLE_DESCRIPTOR_COUNT`, but {0} is not the
@ -414,7 +414,7 @@ impl DescriptorSetLayoutCreateInfo {
"VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-pBindingFlags-03004",
],
..Default::default()
});
}));
}
}
@ -427,14 +427,14 @@ impl DescriptorSetLayoutCreateInfo {
if flags.intersects(DescriptorSetLayoutCreateFlags::PUSH_DESCRIPTOR)
&& total_descriptor_count > max_push_descriptors
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`flags` contains `DescriptorSetLayoutCreateFlags::PUSH_DESCRIPTOR`, and \
the total number of descriptors in `bindings` exceeds the \
`max_push_descriptors` limit"
.into(),
vuids: &["VUID-VkDescriptorSetLayoutCreateInfo-flags-00281"],
..Default::default()
});
}));
}
Ok(())
@ -563,10 +563,10 @@ impl DescriptorSetLayoutBinding {
/// Checks whether the descriptor of a pipeline layout `self` is compatible with the
/// requirements of a shader `other`.
#[inline]
pub fn ensure_compatible_with_shader(
pub(crate) fn ensure_compatible_with_shader(
&self,
binding_requirements: &DescriptorBindingRequirements,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
let &DescriptorBindingRequirements {
ref descriptor_types,
descriptor_count,
@ -579,38 +579,38 @@ impl DescriptorSetLayoutBinding {
} = binding_requirements;
if !descriptor_types.contains(&self.descriptor_type) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the descriptor type is not one of the types allowed by the \
descriptor binding requirements"
.into(),
..Default::default()
});
}));
}
if let Some(required) = descriptor_count {
if self.descriptor_count < required {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the descriptor count is less than the count required by the \
descriptor binding requirements"
.into(),
..Default::default()
});
}));
}
}
if !self.stages.contains(stages) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the stages are not a superset of the stages required by the \
descriptor binding requirements"
.into(),
..Default::default()
});
}));
}
Ok(())
}
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
binding_flags,
descriptor_type,
@ -640,24 +640,24 @@ impl DescriptorSetLayoutBinding {
if descriptor_type == DescriptorType::InlineUniformBlock {
if !device.enabled_features().inline_uniform_block {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "descriptor_type".into(),
problem: "`DescriptorType::InlineUniformBlock`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"inline_uniform_block",
)])]),
vuids: &["VUID-VkDescriptorSetLayoutBinding-descriptorType-04604"],
});
}));
}
if descriptor_count % 4 != 0 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`descriptor_type` is `DescriptorType::InlineUniformBlock`, and \
`descriptor_count` is not a multiple of 4"
.into(),
vuids: &["VUID-VkDescriptorSetLayoutBinding-descriptorType-02209"],
..Default::default()
});
}));
}
if descriptor_count
@ -667,14 +667,14 @@ impl DescriptorSetLayoutBinding {
.max_inline_uniform_block_size
.unwrap_or(0)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`descriptor_type` is `DescriptorType::InlineUniformBlock`, and \
`descriptor_count` is greater than the `max_inline_uniform_block_size` \
limit"
.into(),
vuids: &["VUID-VkDescriptorSetLayoutBinding-descriptorType-08004"],
..Default::default()
});
}));
}
}
@ -690,25 +690,25 @@ impl DescriptorSetLayoutBinding {
if descriptor_type == DescriptorType::InputAttachment
&& !(stages.is_empty() || stages == ShaderStages::FRAGMENT)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`descriptor_type` is `DescriptorType::InputAttachment`, but \
`stages` is not either empty or equal to `ShaderStages::FRAGMENT`"
.into(),
vuids: &["VUID-VkDescriptorSetLayoutBinding-descriptorType-01510"],
..Default::default()
});
}));
}
}
if !immutable_samplers.is_empty() {
if descriptor_count != immutable_samplers.len() as u32 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`immutable_samplers` is not empty, but its length does not equal \
`descriptor_count`"
.into(),
vuids: &["VUID-VkDescriptorSetLayoutBinding-descriptorType-00282"],
..Default::default()
});
}));
}
let mut has_sampler_ycbcr_conversion = false;
@ -721,27 +721,27 @@ impl DescriptorSetLayoutBinding {
if has_sampler_ycbcr_conversion {
if !matches!(descriptor_type, DescriptorType::CombinedImageSampler) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`immutable_samplers` contains a sampler with a \
sampler YCbCr conversion, but `descriptor_type` is not \
`DescriptorType::CombinedImageSampler`"
.into(),
vuids: &["VUID-VkDescriptorSetLayoutBinding-descriptorType-00282"],
..Default::default()
});
}));
}
} else {
if !matches!(
descriptor_type,
DescriptorType::Sampler | DescriptorType::CombinedImageSampler
) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`immutable_samplers` is not empty, but `descriptor_type` is not \
`DescriptorType::Sampler` or `DescriptorType::CombinedImageSampler`"
.into(),
vuids: &["VUID-VkDescriptorSetLayoutBinding-descriptorType-00282"],
..Default::default()
});
}));
}
}
}
@ -751,21 +751,21 @@ impl DescriptorSetLayoutBinding {
.enabled_features()
.descriptor_binding_variable_descriptor_count
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "binding_flags".into(),
problem: "contains `DescriptorBindingFlags::VARIABLE_DESCRIPTOR_COUNT`".into(),
requires_one_of: RequiresOneOf(&[
RequiresAllOf(&[Requires::Feature("descriptor_binding_variable_descriptor_count")])
]),
vuids: &["VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-descriptorBindingVariableDescriptorCount-03014"],
});
}));
}
if matches!(
descriptor_type,
DescriptorType::UniformBufferDynamic | DescriptorType::StorageBufferDynamic
) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`binding_flags` contains \
`DescriptorBindingFlags::VARIABLE_DESCRIPTOR_COUNT`, and \
`descriptor_type` is `DescriptorType::UniformBufferDynamic` or \
@ -775,7 +775,7 @@ impl DescriptorSetLayoutBinding {
"VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-pBindingFlags-03015",
],
..Default::default()
});
}));
}
}

View File

@ -169,7 +169,7 @@ impl DescriptorSetInner {
variable_descriptor_count: u32,
descriptor_writes: impl IntoIterator<Item = WriteDescriptorSet>,
descriptor_copies: impl IntoIterator<Item = CopyDescriptorSet>,
) -> Result<Self, ValidationError> {
) -> Result<Self, Box<ValidationError>> {
assert!(
!layout
.flags()

View File

@ -31,7 +31,7 @@ use crate::{
UnsafeDescriptorSet,
},
device::{Device, DeviceOwned},
VulkanError, VulkanObject,
Validated, VulkanError, VulkanObject,
};
use std::{
hash::{Hash, Hasher},
@ -54,7 +54,7 @@ impl PersistentDescriptorSet {
layout: Arc<DescriptorSetLayout>,
descriptor_writes: impl IntoIterator<Item = WriteDescriptorSet>,
descriptor_copies: impl IntoIterator<Item = CopyDescriptorSet>,
) -> Result<Arc<PersistentDescriptorSet<A::Alloc>>, VulkanError>
) -> Result<Arc<PersistentDescriptorSet<A::Alloc>>, Validated<VulkanError>>
where
A: DescriptorSetAllocator + ?Sized,
{
@ -74,7 +74,7 @@ impl PersistentDescriptorSet {
variable_descriptor_count: u32,
descriptor_writes: impl IntoIterator<Item = WriteDescriptorSet>,
descriptor_copies: impl IntoIterator<Item = CopyDescriptorSet>,
) -> Result<Arc<PersistentDescriptorSet<A::Alloc>>, VulkanError>
) -> Result<Arc<PersistentDescriptorSet<A::Alloc>>, Validated<VulkanError>>
where
A: DescriptorSetAllocator + ?Sized,
{

View File

@ -15,7 +15,7 @@ use crate::{
device::{Device, DeviceOwned},
instance::InstanceOwnedDebugWrapper,
macros::{impl_id_counter, vulkan_bitflags},
Requires, RequiresAllOf, RequiresOneOf, RuntimeError, ValidationError, Version, VulkanError,
Requires, RequiresAllOf, RequiresOneOf, Validated, ValidationError, Version, VulkanError,
VulkanObject,
};
use ahash::HashMap;
@ -47,7 +47,7 @@ impl DescriptorPool {
pub fn new(
device: Arc<Device>,
create_info: DescriptorPoolCreateInfo,
) -> Result<DescriptorPool, VulkanError> {
) -> Result<DescriptorPool, Validated<VulkanError>> {
Self::validate_new(&device, &create_info)?;
unsafe { Ok(Self::new_unchecked(device, create_info)?) }
@ -57,7 +57,7 @@ impl DescriptorPool {
pub unsafe fn new_unchecked(
device: Arc<Device>,
create_info: DescriptorPoolCreateInfo,
) -> Result<DescriptorPool, RuntimeError> {
) -> Result<DescriptorPool, VulkanError> {
let &DescriptorPoolCreateInfo {
flags,
max_sets,
@ -106,7 +106,7 @@ impl DescriptorPool {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -116,7 +116,7 @@ impl DescriptorPool {
fn validate_new(
device: &Device,
create_info: &DescriptorPoolCreateInfo,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
// VUID-vkCreateDescriptorPool-pCreateInfo-parameter
create_info
.validate(device)
@ -205,7 +205,7 @@ impl DescriptorPool {
pub unsafe fn allocate_descriptor_sets<'a>(
&self,
allocate_info: impl IntoIterator<Item = DescriptorSetAllocateInfo<'a>>,
) -> Result<impl ExactSizeIterator<Item = UnsafeDescriptorSet>, RuntimeError> {
) -> Result<impl ExactSizeIterator<Item = UnsafeDescriptorSet>, VulkanError> {
let (layouts, variable_descriptor_counts): (SmallVec<[_; 1]>, SmallVec<[_; 1]>) =
allocate_info
.into_iter()
@ -256,15 +256,15 @@ impl DescriptorPool {
let fns = self.device.fns();
(fns.v1_0.allocate_descriptor_sets)(self.device.handle(), &infos, output.as_mut_ptr())
.result()
.map_err(RuntimeError::from)
.map_err(VulkanError::from)
.map_err(|err| match err {
RuntimeError::OutOfHostMemory
| RuntimeError::OutOfDeviceMemory
| RuntimeError::OutOfPoolMemory => err,
VulkanError::OutOfHostMemory
| VulkanError::OutOfDeviceMemory
| VulkanError::OutOfPoolMemory => err,
// According to the specs, because `VK_ERROR_FRAGMENTED_POOL` was added after
// version 1.0 of Vulkan, any negative return value except out-of-memory errors
// must be considered as a fragmented pool error.
_ => RuntimeError::FragmentedPool,
_ => VulkanError::FragmentedPool,
})?;
output.set_len(layouts.len());
@ -288,7 +288,7 @@ impl DescriptorPool {
pub unsafe fn free_descriptor_sets(
&self,
descriptor_sets: impl IntoIterator<Item = UnsafeDescriptorSet>,
) -> Result<(), RuntimeError> {
) -> Result<(), VulkanError> {
let sets: SmallVec<[_; 8]> = descriptor_sets.into_iter().map(|s| s.handle()).collect();
if !sets.is_empty() {
let fns = self.device.fns();
@ -299,7 +299,7 @@ impl DescriptorPool {
sets.as_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
}
Ok(())
@ -309,7 +309,7 @@ impl DescriptorPool {
///
/// This destroys all descriptor sets and empties the pool.
#[inline]
pub unsafe fn reset(&self) -> Result<(), RuntimeError> {
pub unsafe fn reset(&self) -> Result<(), VulkanError> {
let fns = self.device.fns();
(fns.v1_0.reset_descriptor_pool)(
self.device.handle(),
@ -317,7 +317,7 @@ impl DescriptorPool {
ash::vk::DescriptorPoolResetFlags::empty(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
Ok(())
}
@ -399,7 +399,7 @@ impl Default for DescriptorPoolCreateInfo {
}
impl DescriptorPoolCreateInfo {
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
flags,
max_sets,
@ -417,21 +417,21 @@ impl DescriptorPoolCreateInfo {
})?;
if max_sets == 0 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "max_sets".into(),
problem: "is zero".into(),
vuids: &["VUID-VkDescriptorPoolCreateInfo-maxSets-00301"],
..Default::default()
});
}));
}
if pool_sizes.is_empty() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "pool_sizes".into(),
problem: "is empty".into(),
// vuids?
..Default::default()
});
}));
}
// VUID-VkDescriptorPoolCreateInfo-pPoolSizes-parameter
@ -445,21 +445,21 @@ impl DescriptorPoolCreateInfo {
})?;
if pool_size == 0 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("pool_sizes[DescriptorType::{:?}]", descriptor_type).into(),
problem: "is zero".into(),
vuids: &["VUID-VkDescriptorPoolSize-descriptorCount-00302"],
..Default::default()
});
}));
}
if descriptor_type == DescriptorType::InlineUniformBlock {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "pool_sizes[DescriptorType::InlineUniformBlock]".into(),
problem: "is not a multiple of 4".into(),
vuids: &["VUID-VkDescriptorPoolSize-type-02218"],
..Default::default()
});
}));
}
}
@ -467,7 +467,7 @@ impl DescriptorPoolCreateInfo {
&& !(device.api_version() >= Version::V1_3
|| device.enabled_extensions().ext_inline_uniform_block)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "max_inline_uniform_block_bindings".into(),
problem: "is not zero".into(),
requires_one_of: RequiresOneOf(&[
@ -476,7 +476,7 @@ impl DescriptorPoolCreateInfo {
]),
// vuids?
..Default::default()
});
}));
}
Ok(())

View File

@ -367,7 +367,7 @@ impl WriteDescriptorSet {
&self,
layout: &DescriptorSetLayout,
variable_descriptor_count: u32,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
fn provided_element_type(elements: &WriteDescriptorSetElements) -> &'static str {
match elements {
WriteDescriptorSetElements::None(_) => "none",
@ -392,12 +392,12 @@ impl WriteDescriptorSet {
let layout_binding = match layout.bindings().get(&binding) {
Some(layout_binding) => layout_binding,
None => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "binding".into(),
problem: "does not exist in the descriptor set layout".into(),
vuids: &["VUID-VkWriteDescriptorSet-dstBinding-00315"],
..Default::default()
});
}));
}
};
@ -415,34 +415,34 @@ impl WriteDescriptorSet {
// VUID-VkWriteDescriptorSet-dstArrayElement-00321
if first_array_element + array_element_count > max_descriptor_count {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`first_array_element` + the number of provided elements is greater than \
the number of descriptors in the descriptor set binding"
.into(),
vuids: &["VUID-VkWriteDescriptorSet-dstArrayElement-00321"],
..Default::default()
});
}));
}
let validate_image_view =
|image_view: &ImageView, index: usize| -> Result<(), ValidationError> {
|image_view: &ImageView, index: usize| -> Result<(), Box<ValidationError>> {
if image_view.image().image_type() == ImageType::Dim3d {
if image_view.view_type() == ImageViewType::Dim2dArray {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("elements[{}]", index).into(),
problem: "the image view's type is `ImageViewType::Dim2dArray`, and \
was created from a 3D image"
.into(),
vuids: &["VUID-VkDescriptorImageInfo-imageView-00343"],
..Default::default()
});
}));
} else if image_view.view_type() == ImageViewType::Dim2d {
if !image_view
.image()
.flags()
.intersects(ImageCreateFlags::DIM2D_VIEW_COMPATIBLE)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("elements[{}]", index).into(),
problem: "the image view's type is `ImageViewType::Dim2d`, and \
was created from a 3D image, but the image's flags do not \
@ -450,13 +450,13 @@ impl WriteDescriptorSet {
.into(),
vuids: &["VUID-VkDescriptorImageInfo-imageView-07796"],
..Default::default()
});
}));
}
match layout_binding.descriptor_type {
DescriptorType::StorageImage => {
if !device.enabled_features().image2_d_view_of3_d {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("elements[{}]", index).into(),
problem: format!(
"the descriptor type is `DescriptorType::{:?}`, and \
@ -469,12 +469,12 @@ impl WriteDescriptorSet {
Requires::Feature("image2_d_view_of3_d"),
])]),
vuids: &["VUID-VkDescriptorImageInfo-descriptorType-06713"],
});
}));
}
}
DescriptorType::SampledImage | DescriptorType::CombinedImageSampler => {
if !device.enabled_features().sampler2_d_view_of3_d {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("elements[{}]", index).into(),
problem: format!(
"the descriptor type is `DescriptorType::{:?}`, and \
@ -487,11 +487,11 @@ impl WriteDescriptorSet {
Requires::Feature("sampler2_d_view_of3_d"),
])]),
vuids: &["VUID-VkDescriptorImageInfo-descriptorType-06714"],
});
}));
}
}
_ => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("elements[{}]", index).into(),
problem: "the descriptor type is not \
`DescriptorType::StorageImage`, \
@ -502,7 +502,7 @@ impl WriteDescriptorSet {
.into(),
vuids: &["VUID-VkDescriptorImageInfo-imageView-07795"],
..Default::default()
});
}));
}
}
}
@ -513,14 +513,14 @@ impl WriteDescriptorSet {
.aspects
.contains(ImageAspects::DEPTH | ImageAspects::STENCIL)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("elements[{}]", index).into(),
problem: "the image view's aspects include both a depth and a \
stencil component"
.into(),
vuids: &["VUID-VkDescriptorImageInfo-imageView-01976"],
..Default::default()
});
}));
}
Ok(())
@ -539,7 +539,7 @@ impl WriteDescriptorSet {
if let WriteDescriptorSetElements::None(_) = elements {
// Do nothing
} else {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "elements".into(),
problem: format!(
"contains `{}` elements, but the descriptor set \
@ -549,25 +549,25 @@ impl WriteDescriptorSet {
.into(),
// vuids?
..Default::default()
});
}));
}
} else {
// For regular descriptors, no element must be written.
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "binding".into(),
problem: "no descriptors must be written to this \
descriptor set binding"
.into(),
// vuids?
..Default::default()
});
}));
}
}
let elements = if let WriteDescriptorSetElements::Sampler(elements) = elements {
elements
} else {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "elements".into(),
problem: format!(
"contains `{}` elements, but the descriptor set \
@ -577,14 +577,14 @@ impl WriteDescriptorSet {
.into(),
// vuids?
..Default::default()
});
}));
};
for (index, sampler) in elements.iter().enumerate() {
assert_eq!(device, sampler.device());
if sampler.sampler_ycbcr_conversion().is_some() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("elements[{}]", index).into(),
problem: "the descriptor type is not \
`DescriptorType::CombinedImageSampler`, and the sampler has a \
@ -592,14 +592,14 @@ impl WriteDescriptorSet {
.into(),
// vuids?
..Default::default()
});
}));
}
if device.enabled_extensions().khr_portability_subset
&& !device.enabled_features().mutable_comparison_samplers
&& sampler.compare().is_some()
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("elements[{}]", index).into(),
problem: "this device is a portability subset device, and \
the sampler has depth comparison enabled"
@ -608,7 +608,7 @@ impl WriteDescriptorSet {
"mutable_comparison_samplers",
)])]),
vuids: &["VUID-VkDescriptorImageInfo-mutableComparisonSamplers-04450"],
});
}));
}
}
}
@ -619,7 +619,7 @@ impl WriteDescriptorSet {
if let WriteDescriptorSetElements::ImageViewSampler(elements) = elements {
elements
} else {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "elements".into(),
problem: format!(
"contains `{}` elements, but the descriptor set \
@ -629,7 +629,7 @@ impl WriteDescriptorSet {
.into(),
// vuids?
..Default::default()
});
}));
};
for (index, (image_view_info, sampler)) in elements.iter().enumerate() {
@ -648,7 +648,7 @@ impl WriteDescriptorSet {
validate_image_view(image_view.as_ref(), index)?;
if !image_view.usage().intersects(ImageUsage::SAMPLED) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("elements[{}]", index).into(),
problem: "the descriptor type is \
`DescriptorType::SampledImage` or \
@ -657,7 +657,7 @@ impl WriteDescriptorSet {
.into(),
vuids: &["VUID-VkWriteDescriptorSet-descriptorType-00337"],
..Default::default()
});
}));
}
if !matches!(
@ -670,7 +670,7 @@ impl WriteDescriptorSet {
| ImageLayout::DepthReadOnlyOptimal
| ImageLayout::StencilReadOnlyOptimal,
) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("elements[{}]", index).into(),
problem: "the descriptor type is \
`DescriptorType::CombinedImageSampler`, and the image layout \
@ -678,14 +678,14 @@ impl WriteDescriptorSet {
.into(),
vuids: &["VUID-VkWriteDescriptorSet-descriptorType-04150"],
..Default::default()
});
}));
}
if device.enabled_extensions().khr_portability_subset
&& !device.enabled_features().mutable_comparison_samplers
&& sampler.compare().is_some()
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("elements[{}]", index).into(),
problem: "this device is a portability subset device, and \
the sampler has depth comparison enabled"
@ -696,27 +696,27 @@ impl WriteDescriptorSet {
vuids: &[
"VUID-VkDescriptorImageInfo-mutableComparisonSamplers-04450",
],
});
}));
}
if image_view.sampler_ycbcr_conversion().is_some() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("elements[{}]", index).into(),
problem: "the image view has a sampler YCbCr conversion, and the \
descriptor set layout was not created with immutable samplers"
.into(),
vuids: &["VUID-VkWriteDescriptorSet-descriptorType-02738"],
..Default::default()
});
}));
}
if sampler.sampler_ycbcr_conversion().is_some() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("elements[{}]", index).into(),
problem: "the sampler has a sampler YCbCr conversion".into(),
// vuids?
..Default::default()
});
}));
}
sampler
@ -728,7 +728,7 @@ impl WriteDescriptorSet {
{
elements
} else {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "elements".into(),
problem: format!(
"contains `{}` elements, but the descriptor set \
@ -737,7 +737,7 @@ impl WriteDescriptorSet {
)
.into(),
..Default::default()
});
}));
};
let immutable_samplers = &layout_binding.immutable_samplers
@ -760,7 +760,7 @@ impl WriteDescriptorSet {
validate_image_view(image_view.as_ref(), index)?;
if !image_view.usage().intersects(ImageUsage::SAMPLED) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("elements[{}]", index).into(),
problem: "the descriptor type is \
`DescriptorType::SampledImage` or \
@ -769,7 +769,7 @@ impl WriteDescriptorSet {
.into(),
vuids: &["VUID-VkWriteDescriptorSet-descriptorType-00337"],
..Default::default()
});
}));
}
if !matches!(
@ -782,7 +782,7 @@ impl WriteDescriptorSet {
| ImageLayout::DepthReadOnlyOptimal
| ImageLayout::StencilReadOnlyOptimal,
) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("elements[{}]", index).into(),
problem: "the descriptor type is \
`DescriptorType::CombinedImageSampler`, and the image layout \
@ -790,7 +790,7 @@ impl WriteDescriptorSet {
.into(),
vuids: &["VUID-VkWriteDescriptorSet-descriptorType-04150"],
..Default::default()
});
}));
}
sampler
@ -804,7 +804,7 @@ impl WriteDescriptorSet {
let elements = if let WriteDescriptorSetElements::ImageView(elements) = elements {
elements
} else {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "elements".into(),
problem: format!(
"contains `{}` elements, but the descriptor set \
@ -814,7 +814,7 @@ impl WriteDescriptorSet {
.into(),
// vuids?
..Default::default()
});
}));
};
for (index, image_view_info) in elements.iter().enumerate() {
@ -832,7 +832,7 @@ impl WriteDescriptorSet {
validate_image_view(image_view.as_ref(), index)?;
if !image_view.usage().intersects(ImageUsage::SAMPLED) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("elements[{}]", index).into(),
problem: "the descriptor type is \
`DescriptorType::SampledImage` or \
@ -841,7 +841,7 @@ impl WriteDescriptorSet {
.into(),
vuids: &["VUID-VkWriteDescriptorSet-descriptorType-00337"],
..Default::default()
});
}));
}
if !matches!(
@ -854,7 +854,7 @@ impl WriteDescriptorSet {
| ImageLayout::DepthReadOnlyOptimal
| ImageLayout::StencilReadOnlyOptimal,
) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("elements[{}]", index).into(),
problem: "the descriptor type is \
`DescriptorType::SampledImage`, and the image layout is \
@ -862,18 +862,18 @@ impl WriteDescriptorSet {
.into(),
vuids: &["VUID-VkWriteDescriptorSet-descriptorType-04149"],
..Default::default()
});
}));
}
if image_view.sampler_ycbcr_conversion().is_some() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("elements[{}]", index).into(),
problem: "the descriptor type is `DescriptorType::SampledImage`, and \
the image view has a sampler YCbCr conversion"
.into(),
vuids: &["VUID-VkWriteDescriptorSet-descriptorType-01946"],
..Default::default()
});
}));
}
}
}
@ -882,7 +882,7 @@ impl WriteDescriptorSet {
let elements = if let WriteDescriptorSetElements::ImageView(elements) = elements {
elements
} else {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "elements".into(),
problem: format!(
"contains `{}` elements, but the descriptor set \
@ -892,7 +892,7 @@ impl WriteDescriptorSet {
.into(),
// vuids?
..Default::default()
});
}));
};
for (index, image_view_info) in elements.iter().enumerate() {
@ -910,7 +910,7 @@ impl WriteDescriptorSet {
validate_image_view(image_view.as_ref(), index)?;
if !image_view.usage().intersects(ImageUsage::STORAGE) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("elements[{}]", index).into(),
problem: "the descriptor type is \
`DescriptorType::StorageImage`, and the image was not \
@ -918,11 +918,11 @@ impl WriteDescriptorSet {
.into(),
vuids: &["VUID-VkWriteDescriptorSet-descriptorType-00339"],
..Default::default()
});
}));
}
if !matches!(image_layout, ImageLayout::General) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("elements[{}]", index).into(),
problem: "the descriptor type is \
`DescriptorType::StorageImage`, and the image layout is \
@ -930,11 +930,11 @@ impl WriteDescriptorSet {
.into(),
vuids: &["VUID-VkWriteDescriptorSet-descriptorType-04152"],
..Default::default()
});
}));
}
if !image_view.component_mapping().is_identity() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("elements[{}]", index).into(),
problem: "the descriptor type is `DescriptorType::StorageImage` or \
`DescriptorType::InputAttachment`, and the image view is not \
@ -942,16 +942,16 @@ impl WriteDescriptorSet {
.into(),
vuids: &["VUID-VkWriteDescriptorSet-descriptorType-00336"],
..Default::default()
});
}));
}
if image_view.sampler_ycbcr_conversion().is_some() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("elements[{}]", index).into(),
problem: "the image view has a sampler YCbCr conversion".into(),
// vuids?
..Default::default()
});
}));
}
}
}
@ -960,7 +960,7 @@ impl WriteDescriptorSet {
let elements = if let WriteDescriptorSetElements::BufferView(elements) = elements {
elements
} else {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "elements".into(),
problem: format!(
"contains `{}` elements, but the descriptor set \
@ -970,7 +970,7 @@ impl WriteDescriptorSet {
.into(),
// vuids?
..Default::default()
});
}));
};
for (index, buffer_view) in elements.iter().enumerate() {
@ -982,7 +982,7 @@ impl WriteDescriptorSet {
.usage()
.intersects(BufferUsage::UNIFORM_TEXEL_BUFFER)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("elements[{}]", index).into(),
problem: "the descriptor type is \
`DescriptorType::UniformTexelBuffer`, and the buffer was not \
@ -990,7 +990,7 @@ impl WriteDescriptorSet {
.into(),
vuids: &["VUID-VkWriteDescriptorSet-descriptorType-00334"],
..Default::default()
});
}));
}
}
}
@ -999,7 +999,7 @@ impl WriteDescriptorSet {
let elements = if let WriteDescriptorSetElements::BufferView(elements) = elements {
elements
} else {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "elements".into(),
problem: format!(
"contains `{}` elements, but the descriptor set \
@ -1009,7 +1009,7 @@ impl WriteDescriptorSet {
.into(),
// vuids?
..Default::default()
});
}));
};
for (index, buffer_view) in elements.iter().enumerate() {
@ -1022,7 +1022,7 @@ impl WriteDescriptorSet {
.usage()
.intersects(BufferUsage::STORAGE_TEXEL_BUFFER)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("elements[{}]", index).into(),
problem: "the descriptor type is \
`DescriptorType::StorageTexelBuffer`, and the buffer was not \
@ -1030,7 +1030,7 @@ impl WriteDescriptorSet {
.into(),
vuids: &["VUID-VkWriteDescriptorSet-descriptorType-00335"],
..Default::default()
});
}));
}
}
}
@ -1039,7 +1039,7 @@ impl WriteDescriptorSet {
let elements = if let WriteDescriptorSetElements::Buffer(elements) = elements {
elements
} else {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "elements".into(),
problem: format!(
"contains `{}` elements, but the descriptor set \
@ -1049,7 +1049,7 @@ impl WriteDescriptorSet {
.into(),
// vuids?
..Default::default()
});
}));
};
for (index, buffer_info) in elements.iter().enumerate() {
@ -1062,7 +1062,7 @@ impl WriteDescriptorSet {
.usage()
.intersects(BufferUsage::UNIFORM_BUFFER)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("elements[{}]", index).into(),
problem: "the descriptor type is `DescriptorType::UniformBuffer` or \
`DescriptorType::UniformBufferDynamic`, and the buffer was not \
@ -1070,19 +1070,19 @@ impl WriteDescriptorSet {
.into(),
vuids: &["VUID-VkWriteDescriptorSet-descriptorType-00330"],
..Default::default()
});
}));
}
assert!(!range.is_empty());
if range.end > buffer.size() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("elements[{}]", index).into(),
problem: "the end of the range is greater than the size of the buffer"
.into(),
vuids: &["VUID-VkDescriptorBufferInfo-range-00342"],
..Default::default()
});
}));
}
}
}
@ -1091,7 +1091,7 @@ impl WriteDescriptorSet {
let elements = if let WriteDescriptorSetElements::Buffer(elements) = elements {
elements
} else {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "elements".into(),
problem: format!(
"contains `{}` elements, but the descriptor set \
@ -1101,7 +1101,7 @@ impl WriteDescriptorSet {
.into(),
// vuids?
..Default::default()
});
}));
};
for (index, buffer_info) in elements.iter().enumerate() {
@ -1114,7 +1114,7 @@ impl WriteDescriptorSet {
.usage()
.intersects(BufferUsage::STORAGE_BUFFER)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("elements[{}]", index).into(),
problem: "the descriptor type is `DescriptorType::StorageBuffer` or \
`DescriptorType::StorageBufferDynamic`, and the buffer was not \
@ -1122,19 +1122,19 @@ impl WriteDescriptorSet {
.into(),
vuids: &["VUID-VkWriteDescriptorSet-descriptorType-00331"],
..Default::default()
});
}));
}
assert!(!range.is_empty());
if range.end > buffer.size() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("elements[{}]", index).into(),
problem: "the end of the range is greater than the size of the buffer"
.into(),
vuids: &["VUID-VkDescriptorBufferInfo-range-00342"],
..Default::default()
});
}));
}
}
}
@ -1143,7 +1143,7 @@ impl WriteDescriptorSet {
let elements = if let WriteDescriptorSetElements::ImageView(elements) = elements {
elements
} else {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "elements".into(),
problem: format!(
"contains `{}` elements, but the descriptor set \
@ -1153,7 +1153,7 @@ impl WriteDescriptorSet {
.into(),
// vuids?
..Default::default()
});
}));
};
for (index, image_view_info) in elements.iter().enumerate() {
@ -1171,7 +1171,7 @@ impl WriteDescriptorSet {
validate_image_view(image_view.as_ref(), index)?;
if !image_view.usage().intersects(ImageUsage::INPUT_ATTACHMENT) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("elements[{}]", index).into(),
problem: "the descriptor type is \
`DescriptorType::InputAttachment`, and the image was not \
@ -1179,7 +1179,7 @@ impl WriteDescriptorSet {
.into(),
vuids: &["VUID-VkWriteDescriptorSet-descriptorType-00338"],
..Default::default()
});
}));
}
if !matches!(
@ -1192,7 +1192,7 @@ impl WriteDescriptorSet {
| ImageLayout::DepthReadOnlyOptimal
| ImageLayout::StencilReadOnlyOptimal,
) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("elements[{}]", index).into(),
problem: "the descriptor type is \
`DescriptorType::InputAttachment`, and the image layout is \
@ -1200,11 +1200,11 @@ impl WriteDescriptorSet {
.into(),
vuids: &["VUID-VkWriteDescriptorSet-descriptorType-04151"],
..Default::default()
});
}));
}
if !image_view.component_mapping().is_identity() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("elements[{}]", index).into(),
problem: "the descriptor type is `DescriptorType::StorageImage` or \
`DescriptorType::InputAttachment`, and the image view is not \
@ -1212,18 +1212,18 @@ impl WriteDescriptorSet {
.into(),
vuids: &["VUID-VkWriteDescriptorSet-descriptorType-00336"],
..Default::default()
});
}));
}
if image_view.sampler_ycbcr_conversion().is_some() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("elements[{}]", index).into(),
problem: "the descriptor type is `DescriptorType::InputAttachment`, \
and the image view has a sampler YCbCr conversion"
.into(),
// vuids?
..Default::default()
});
}));
}
}
}
@ -1232,7 +1232,7 @@ impl WriteDescriptorSet {
let data = if let WriteDescriptorSetElements::InlineUniformBlock(data) = elements {
data
} else {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "elements".into(),
problem: format!(
"contains `{}` elements, but the descriptor set \
@ -1241,11 +1241,11 @@ impl WriteDescriptorSet {
)
.into(),
..Default::default()
});
}));
};
if data.is_empty() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "data".into(),
problem: "is empty".into(),
vuids: &[
@ -1253,11 +1253,11 @@ impl WriteDescriptorSet {
"VUID-VkWriteDescriptorSet-descriptorCount-arraylength",
],
..Default::default()
});
}));
}
if data.len() % 4 != 0 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "data".into(),
problem: "the length is not a multiple of 4".into(),
vuids: &[
@ -1265,16 +1265,16 @@ impl WriteDescriptorSet {
"VUID-VkWriteDescriptorSet-descriptorType-02220",
],
..Default::default()
});
}));
}
if first_array_element % 4 != 0 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "offset".into(),
problem: "is not a multiple of 4".into(),
vuids: &["VUID-VkWriteDescriptorSet-descriptorType-02219"],
..Default::default()
});
}));
}
}
@ -1283,7 +1283,7 @@ impl WriteDescriptorSet {
if let WriteDescriptorSetElements::AccelerationStructure(elements) = elements {
elements
} else {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "elements".into(),
problem: format!(
"contains `{}` elements, but the descriptor set \
@ -1292,7 +1292,7 @@ impl WriteDescriptorSet {
)
.into(),
..Default::default()
});
}));
};
for (index, acceleration_structure) in elements.iter().enumerate() {
@ -1302,7 +1302,7 @@ impl WriteDescriptorSet {
acceleration_structure.ty(),
AccelerationStructureType::TopLevel | AccelerationStructureType::Generic
) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("elements[{}]", index).into(),
problem: "the acceleration structure's type is not \
`AccelerationStructureType::TopLevel` or \
@ -1310,7 +1310,7 @@ impl WriteDescriptorSet {
.into(),
vuids: &["VUID-VkWriteDescriptorSetAccelerationStructureKHR-pAccelerationStructures-03579"],
..Default::default()
});
}));
}
}
}
@ -1620,7 +1620,7 @@ impl CopyDescriptorSet {
&self,
dst_set_layout: &DescriptorSetLayout,
dst_set_variable_descriptor_count: u32,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
let &Self {
ref src_set,
src_binding,
@ -1637,13 +1637,13 @@ impl CopyDescriptorSet {
let src_layout_binding = match src_set.layout().bindings().get(&src_binding) {
Some(layout_binding) => layout_binding,
None => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`src_binding` does not exist in the descriptor set layout of \
`src_set`"
.into(),
vuids: &["VUID-VkCopyDescriptorSet-srcBinding-00345"],
..Default::default()
});
}));
}
};
@ -1657,25 +1657,25 @@ impl CopyDescriptorSet {
};
if src_first_array_element + descriptor_count > src_max_descriptor_count {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`src_first_array_element` + `descriptor_count` is greater than \
the number of descriptors in `src_set`'s descriptor set binding"
.into(),
vuids: &["VUID-VkCopyDescriptorSet-srcArrayElement-00346"],
..Default::default()
});
}));
}
let dst_layout_binding = match dst_set_layout.bindings().get(&dst_binding) {
Some(layout_binding) => layout_binding,
None => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`dst_binding` does not exist in the descriptor set layout of \
`dst_set`"
.into(),
vuids: &["VUID-VkCopyDescriptorSet-dstBinding-00347"],
..Default::default()
});
}));
}
};
@ -1689,70 +1689,70 @@ impl CopyDescriptorSet {
};
if dst_first_array_element + descriptor_count > dst_max_descriptor_count {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`dst_first_array_element` + `descriptor_count` is greater than \
the number of descriptors in `dst_set`'s descriptor set binding"
.into(),
vuids: &["VUID-VkCopyDescriptorSet-dstArrayElement-00348"],
..Default::default()
});
}));
}
if src_layout_binding.descriptor_type != dst_layout_binding.descriptor_type {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the descriptor type of `src_binding` within `src_set` does not equal \
the descriptor type of `dst_binding` within `dst_set`"
.into(),
vuids: &["VUID-VkCopyDescriptorSet-dstBinding-02632"],
..Default::default()
});
}));
}
if dst_layout_binding.descriptor_type == DescriptorType::Sampler
&& !dst_layout_binding.immutable_samplers.is_empty()
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the descriptor type of `dst_binding` within `dst_set` is \
`DescriptorType::Sampler`, and the layout was created with immutable samplers \
for `dst_binding`"
.into(),
vuids: &["VUID-VkCopyDescriptorSet-dstBinding-02753"],
..Default::default()
});
}));
}
if dst_layout_binding.descriptor_type == DescriptorType::InlineUniformBlock {
if src_first_array_element % 4 != 0 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the descriptor type of `src_binding` within `src_set` is \
`DescriptorType::InlineUniformBlock`, and `src_first_array_element` is \
not a multiple of 4"
.into(),
vuids: &["VUID-VkCopyDescriptorSet-srcBinding-02223"],
..Default::default()
});
}));
}
if dst_first_array_element % 4 != 0 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the descriptor type of `dst_binding` within `dst_set` is \
`DescriptorType::InlineUniformBlock`, and `dst_first_array_element` is \
not a multiple of 4"
.into(),
vuids: &["VUID-VkCopyDescriptorSet-dstBinding-02224"],
..Default::default()
});
}));
}
if descriptor_count % 4 != 0 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the descriptor type of `dst_binding` within `dst_set` is \
`DescriptorType::InlineUniformBlock`, and `descriptor_count` is \
not a multiple of 4"
.into(),
vuids: &["VUID-VkCopyDescriptorSet-srcBinding-02225"],
..Default::default()
});
}));
}
}

View File

@ -119,7 +119,7 @@ use crate::{
instance::{Instance, InstanceOwned, InstanceOwnedDebugWrapper},
macros::{impl_id_counter, vulkan_bitflags},
memory::ExternalMemoryHandleType,
OomError, Requires, RequiresAllOf, RequiresOneOf, RuntimeError, ValidationError, Version,
OomError, Requires, RequiresAllOf, RequiresOneOf, Validated, ValidationError, Version,
VulkanError, VulkanObject,
};
use ash::vk::Handle;
@ -178,7 +178,8 @@ impl Device {
pub fn new(
physical_device: Arc<PhysicalDevice>,
create_info: DeviceCreateInfo,
) -> Result<(Arc<Device>, impl ExactSizeIterator<Item = Arc<Queue>>), VulkanError> {
) -> Result<(Arc<Device>, impl ExactSizeIterator<Item = Arc<Queue>>), Validated<VulkanError>>
{
Self::validate_new(&physical_device, &create_info)?;
unsafe { Ok(Self::new_unchecked(physical_device, create_info)?) }
@ -187,7 +188,7 @@ impl Device {
fn validate_new(
physical_device: &PhysicalDevice,
create_info: &DeviceCreateInfo,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
create_info
.validate(physical_device)
.map_err(|err| err.add_context("create_info"))?;
@ -205,13 +206,13 @@ impl Device {
.iter()
.any(|p| p.as_ref() == physical_device)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`create_info.physical_devices` is not empty, but does not contain \
`physical_device`"
.into(),
vuids: &["VUID-VkDeviceGroupDeviceCreateInfo-physicalDeviceCount-00377"],
..Default::default()
});
}));
}
Ok(())
@ -221,7 +222,7 @@ impl Device {
pub unsafe fn new_unchecked(
physical_device: Arc<PhysicalDevice>,
mut create_info: DeviceCreateInfo,
) -> Result<(Arc<Device>, impl ExactSizeIterator<Item = Arc<Queue>>), RuntimeError> {
) -> Result<(Arc<Device>, impl ExactSizeIterator<Item = Arc<Queue>>), VulkanError> {
// VUID-vkCreateDevice-ppEnabledExtensionNames-01387
create_info.enabled_extensions.enable_dependencies(
physical_device.api_version(),
@ -377,7 +378,7 @@ impl Device {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -574,7 +575,7 @@ impl Device {
build_type: AccelerationStructureBuildType,
build_info: &AccelerationStructureBuildGeometryInfo,
max_primitive_counts: &[u32],
) -> Result<AccelerationStructureBuildSizesInfo, ValidationError> {
) -> Result<AccelerationStructureBuildSizesInfo, Box<ValidationError>> {
self.validate_acceleration_structure_build_sizes(
build_type,
build_info,
@ -595,18 +596,18 @@ impl Device {
build_type: AccelerationStructureBuildType,
build_info: &AccelerationStructureBuildGeometryInfo,
max_primitive_counts: &[u32],
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
if !self.enabled_extensions().khr_acceleration_structure {
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceExtension(
"khr_acceleration_structure",
)])]),
..Default::default()
});
}));
}
if !self.enabled_features().acceleration_structure {
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"acceleration_structure",
)])]),
@ -614,7 +615,7 @@ impl Device {
"VUID-vkGetAccelerationStructureBuildSizesKHR-accelerationStructure-08933",
],
..Default::default()
});
}));
}
build_type
@ -645,12 +646,12 @@ impl Device {
AccelerationStructureGeometries::Triangles(geometries) => {
for (index, &primitive_count) in max_primitive_counts.iter().enumerate() {
if primitive_count as u64 > max_primitive_count {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("max_primitive_counts[{}]", index).into(),
problem: "exceeds the `max_primitive_count` limit".into(),
vuids: &["VUID-VkAccelerationStructureBuildGeometryInfoKHR-type-03795"],
..Default::default()
});
}));
}
}
@ -659,12 +660,12 @@ impl Device {
AccelerationStructureGeometries::Aabbs(geometries) => {
for (index, &primitive_count) in max_primitive_counts.iter().enumerate() {
if primitive_count as u64 > max_primitive_count {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("max_primitive_counts[{}]", index).into(),
problem: "exceeds the `max_primitive_count` limit".into(),
vuids: &["VUID-VkAccelerationStructureBuildGeometryInfoKHR-type-03794"],
..Default::default()
});
}));
}
}
@ -673,14 +674,14 @@ impl Device {
AccelerationStructureGeometries::Instances(_) => {
for (index, &instance_count) in max_primitive_counts.iter().enumerate() {
if instance_count as u64 > max_instance_count {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("max_primitive_counts[{}]", index).into(),
problem: "exceeds the `max_instance_count` limit".into(),
vuids: &[
"VUID-vkGetAccelerationStructureBuildSizesKHR-pBuildInfo-03785",
],
..Default::default()
});
}));
}
}
@ -689,13 +690,13 @@ impl Device {
};
if max_primitive_counts.len() != geometry_count {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`build_info.geometries` and `max_primitive_counts` \
do not have the same length"
.into(),
vuids: &["VUID-vkGetAccelerationStructureBuildSizesKHR-pBuildInfo-03619"],
..Default::default()
});
}));
}
Ok(())
@ -741,7 +742,7 @@ impl Device {
pub fn acceleration_structure_is_compatible(
&self,
version_data: &[u8; 2 * ash::vk::UUID_SIZE],
) -> Result<bool, ValidationError> {
) -> Result<bool, Box<ValidationError>> {
self.validate_acceleration_structure_is_compatible(version_data)?;
unsafe { Ok(self.acceleration_structure_is_compatible_unchecked(version_data)) }
@ -750,24 +751,24 @@ impl Device {
fn validate_acceleration_structure_is_compatible(
&self,
_version_data: &[u8; 2 * ash::vk::UUID_SIZE],
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
if !self.enabled_extensions().khr_acceleration_structure {
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceExtension(
"khr_acceleration_structure",
)])]),
..Default::default()
});
}));
}
if !self.enabled_features().acceleration_structure {
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[
RequiresAllOf(&[Requires::Feature("acceleration_structure")]),
]),
vuids: &["VUID-vkGetDeviceAccelerationStructureCompatibilityKHR-accelerationStructure-08928"],
..Default::default()
});
}));
}
Ok(())
@ -812,7 +813,7 @@ impl Device {
pub fn descriptor_set_layout_support(
&self,
create_info: &DescriptorSetLayoutCreateInfo,
) -> Result<Option<DescriptorSetLayoutSupport>, ValidationError> {
) -> Result<Option<DescriptorSetLayoutSupport>, Box<ValidationError>> {
self.validate_descriptor_set_layout_support(create_info)?;
unsafe { Ok(self.descriptor_set_layout_support_unchecked(create_info)) }
@ -821,15 +822,15 @@ impl Device {
fn validate_descriptor_set_layout_support(
&self,
create_info: &DescriptorSetLayoutCreateInfo,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
if !(self.api_version() >= Version::V1_1 || self.enabled_extensions().khr_maintenance3) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[
RequiresAllOf(&[Requires::APIVersion(Version::V1_1)]),
RequiresAllOf(&[Requires::DeviceExtension("khr_maintenance3")]),
]),
..Default::default()
});
}));
}
// VUID-vkGetDescriptorSetLayoutSupport-pCreateInfo-parameter
@ -957,7 +958,7 @@ impl Device {
&self,
handle_type: ExternalMemoryHandleType,
file: File,
) -> Result<MemoryFdProperties, VulkanError> {
) -> Result<MemoryFdProperties, Validated<VulkanError>> {
self.validate_memory_fd_properties(handle_type, &file)?;
Ok(self.memory_fd_properties_unchecked(handle_type, file)?)
@ -967,14 +968,14 @@ impl Device {
&self,
handle_type: ExternalMemoryHandleType,
_file: &File,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
if !self.enabled_extensions().khr_external_memory_fd {
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceExtension(
"khr_external_memory_fd",
)])]),
..Default::default()
});
}));
}
handle_type
@ -986,12 +987,12 @@ impl Device {
})?;
if handle_type == ExternalMemoryHandleType::OpaqueFd {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "handle_type".into(),
problem: "is `ExternalMemoryHandleType::OpaqueFd`".into(),
vuids: &["VUID-vkGetMemoryFdPropertiesKHR-handleType-00674"],
..Default::default()
});
}));
}
Ok(())
@ -1003,7 +1004,7 @@ impl Device {
&self,
handle_type: ExternalMemoryHandleType,
file: File,
) -> Result<MemoryFdProperties, RuntimeError> {
) -> Result<MemoryFdProperties, VulkanError> {
#[cfg(not(unix))]
unreachable!("`khr_external_memory_fd` was somehow enabled on a non-Unix system");
@ -1021,7 +1022,7 @@ impl Device {
&mut memory_fd_properties,
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
Ok(MemoryFdProperties {
memory_type_bits: memory_fd_properties.memory_type_bits,
@ -1056,7 +1057,7 @@ impl Device {
let fns = self.instance().fns();
(fns.ext_debug_utils.set_debug_utils_object_name_ext)(self.handle, &info)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
}
Ok(())
@ -1077,7 +1078,7 @@ impl Device {
let fns = self.fns();
(fns.v1_0.device_wait_idle)(self.handle)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
Ok(())
}
@ -1230,7 +1231,10 @@ impl Default for DeviceCreateInfo {
}
impl DeviceCreateInfo {
pub(crate) fn validate(&self, physical_device: &PhysicalDevice) -> Result<(), ValidationError> {
pub(crate) fn validate(
&self,
physical_device: &PhysicalDevice,
) -> Result<(), Box<ValidationError>> {
let &Self {
ref queue_create_infos,
ref enabled_extensions,
@ -1240,12 +1244,12 @@ impl DeviceCreateInfo {
} = self;
if queue_create_infos.is_empty() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "queue_create_infos".into(),
problem: "is empty".into(),
vuids: &["VUID-VkDeviceCreateInfo-queueCreateInfoCount-arraylength"],
..Default::default()
});
}));
}
for (index, queue_create_info) in queue_create_infos.iter().enumerate() {
@ -1266,7 +1270,7 @@ impl DeviceCreateInfo {
.count()
!= 1
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: format!(
"`queue_create_infos[{}].queue_family_index` occurs more than once in \
`queue_create_infos`",
@ -1275,7 +1279,7 @@ impl DeviceCreateInfo {
.into(),
vuids: &["VUID-VkDeviceCreateInfo-queueFamilyIndex-02802"],
..Default::default()
});
}));
}
}
@ -1312,175 +1316,175 @@ impl DeviceCreateInfo {
if enabled_extensions.ext_buffer_device_address {
if enabled_extensions.khr_buffer_device_address {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "enabled_extensions".into(),
problem: "contains `khr_buffer_device_address`, \
but also contains `ext_buffer_device_address`"
.into(),
vuids: &["VUID-VkDeviceCreateInfo-ppEnabledExtensionNames-03328"],
..Default::default()
});
}));
} else if dependency_extensions.khr_buffer_device_address {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "enabled_extensions".into(),
problem: "contains an extension that requires `khr_buffer_device_address`, \
but also contains `ext_buffer_device_address`"
.into(),
vuids: &["VUID-VkDeviceCreateInfo-ppEnabledExtensionNames-03328"],
..Default::default()
});
}));
}
if physical_device.api_version() >= Version::V1_2
&& enabled_features.buffer_device_address
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the physical device API version is at least 1.2, \
`enabled_features` contains `buffer_device_address`, and \
`enabled_extensions` contains `ext_buffer_device_address`"
.into(),
vuids: &["VUID-VkDeviceCreateInfo-pNext-04748"],
..Default::default()
});
}));
}
}
if enabled_features.shading_rate_image {
if enabled_features.pipeline_fragment_shading_rate {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "enabled_features".into(),
problem: "contains both `shading_rate_image` and \
`pipeline_fragment_shading_rate`"
.into(),
vuids: &["VUID-VkDeviceCreateInfo-shadingRateImage-04478"],
..Default::default()
});
}));
}
if enabled_features.primitive_fragment_shading_rate {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "enabled_features".into(),
problem: "contains both `shading_rate_image` and \
`primitive_fragment_shading_rate`"
.into(),
vuids: &["VUID-VkDeviceCreateInfo-shadingRateImage-04479"],
..Default::default()
});
}));
}
if enabled_features.attachment_fragment_shading_rate {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "enabled_features".into(),
problem: "contains both `shading_rate_image` and \
`attachment_fragment_shading_rate`"
.into(),
vuids: &["VUID-VkDeviceCreateInfo-shadingRateImage-04480"],
..Default::default()
});
}));
}
}
if enabled_features.fragment_density_map {
if enabled_features.pipeline_fragment_shading_rate {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "enabled_features".into(),
problem: "contains both `fragment_density_map` and \
`pipeline_fragment_shading_rate`"
.into(),
vuids: &["VUID-VkDeviceCreateInfo-shadingRateImage-04481"],
..Default::default()
});
}));
}
if enabled_features.primitive_fragment_shading_rate {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "enabled_features".into(),
problem: "contains both `fragment_density_map` and \
`primitive_fragment_shading_rate`"
.into(),
vuids: &["VUID-VkDeviceCreateInfo-shadingRateImage-04482"],
..Default::default()
});
}));
}
if enabled_features.attachment_fragment_shading_rate {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "enabled_features".into(),
problem: "contains both `fragment_density_map` and \
`attachment_fragment_shading_rate`"
.into(),
vuids: &["VUID-VkDeviceCreateInfo-shadingRateImage-04483"],
..Default::default()
});
}));
}
}
if enabled_features.sparse_image_int64_atomics
&& !enabled_features.shader_image_int64_atomics
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "enabled_features".into(),
problem: "contains `sparse_image_int64_atomics`, but does not contain \
`shader_image_int64_atomics`"
.into(),
vuids: &["VUID-VkDeviceCreateInfo-None-04896"],
..Default::default()
});
}));
}
if enabled_features.sparse_image_float32_atomics
&& !enabled_features.shader_image_float32_atomics
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "enabled_features".into(),
problem: "contains `sparse_image_float32_atomics`, but does not contain \
`shader_image_float32_atomics`"
.into(),
vuids: &["VUID-VkDeviceCreateInfo-None-04897"],
..Default::default()
});
}));
}
if enabled_features.sparse_image_float32_atomic_add
&& !enabled_features.shader_image_float32_atomic_add
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "enabled_features".into(),
problem: "contains `sparse_image_float32_atomic_add`, but does not contain \
`shader_image_float32_atomic_add`"
.into(),
vuids: &["VUID-VkDeviceCreateInfo-None-04898"],
..Default::default()
});
}));
}
if enabled_features.sparse_image_float32_atomic_min_max
&& !enabled_features.shader_image_float32_atomic_min_max
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "enabled_features".into(),
problem: "contains `sparse_image_float32_atomic_min_max`, but does not contain \
`shader_image_float32_atomic_min_max`"
.into(),
vuids: &["VUID-VkDeviceCreateInfo-sparseImageFloat32AtomicMinMax-04975"],
..Default::default()
});
}));
}
if enabled_features.descriptor_buffer && enabled_extensions.amd_shader_fragment_mask {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`enabled_features` contains `descriptor_buffer`, and \
`enabled_extensions` contains `amd_shader_fragment_mask`"
.into(),
vuids: &["VUID-VkDeviceCreateInfo-None-08095"],
..Default::default()
});
}));
}
if physical_devices.len() > 1 {
for (index, group_physical_device) in physical_devices.iter().enumerate() {
if physical_devices[..index].contains(group_physical_device) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "physical_devices".into(),
problem: format!(
"the physical device at index {} is contained in the list more than \
@ -1490,7 +1494,7 @@ impl DeviceCreateInfo {
.into(),
vuids: &["VUID-VkDeviceGroupDeviceCreateInfo-pPhysicalDevices-00375"],
..Default::default()
});
}));
}
}
@ -1500,7 +1504,7 @@ impl DeviceCreateInfo {
.enabled_extensions()
.khr_device_group_creation)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "physical_devices".into(),
problem: "the length is greater than 1".into(),
requires_one_of: RequiresOneOf(&[
@ -1508,20 +1512,20 @@ impl DeviceCreateInfo {
RequiresAllOf(&[Requires::InstanceExtension("khr_device_group_creation")]),
]),
..Default::default()
});
}));
}
if !physical_device
.instance()
.is_same_device_group(physical_devices.iter().map(AsRef::as_ref))
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "physical_devices".into(),
problem: "the physical devices do not all belong to the same device group"
.into(),
vuids: &["VUID-VkDeviceGroupDeviceCreateInfo-pPhysicalDevices-00376"],
..Default::default()
});
}));
}
}
@ -1573,7 +1577,7 @@ impl QueueCreateInfo {
physical_device: &PhysicalDevice,
device_extensions: &DeviceExtensions,
device_features: &Features,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
let &Self {
flags,
queue_family_index,
@ -1606,32 +1610,32 @@ impl QueueCreateInfo {
})?;
if queues.is_empty() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "queues".into(),
problem: "is empty".into(),
vuids: &["VUID-VkDeviceQueueCreateInfo-queueCount-arraylength"],
..Default::default()
});
}));
}
if queues.len() > queue_family_properties.queue_count as usize {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the length of `queues` is greater than the number of queues in the
queue family indicated by `queue_family_index`"
.into(),
vuids: &["VUID-VkDeviceQueueCreateInfo-queueCount-00382"],
..Default::default()
});
}));
}
for (index, &priority) in queues.iter().enumerate() {
if !(0.0..=1.0).contains(&priority) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("queues[{}]", index).into(),
problem: "is not between 0.0 and 1.0 inclusive".into(),
vuids: &["VUID-VkDeviceQueueCreateInfo-pQueuePriorities-00383"],
..Default::default()
});
}));
}
}

View File

@ -29,7 +29,7 @@ use crate::{
semaphore::{ExternalSemaphoreInfo, ExternalSemaphoreProperties},
Sharing,
},
DebugWrapper, ExtensionProperties, Requires, RequiresAllOf, RequiresOneOf, RuntimeError,
DebugWrapper, ExtensionProperties, Requires, RequiresAllOf, RequiresOneOf, Validated,
ValidationError, Version, VulkanError, VulkanObject,
};
use bytemuck::cast_slice;
@ -95,7 +95,7 @@ impl PhysicalDevice {
pub unsafe fn from_handle(
instance: Arc<Instance>,
handle: ash::vk::PhysicalDevice,
) -> Result<Arc<Self>, RuntimeError> {
) -> Result<Arc<Self>, VulkanError> {
let api_version = Self::get_api_version(handle, &instance);
let extension_properties = Self::get_extension_properties(handle, &instance)?;
let supported_extensions: DeviceExtensions = extension_properties
@ -160,7 +160,7 @@ impl PhysicalDevice {
unsafe fn get_extension_properties(
handle: ash::vk::PhysicalDevice,
instance: &Instance,
) -> Result<Vec<ExtensionProperties>, RuntimeError> {
) -> Result<Vec<ExtensionProperties>, VulkanError> {
let fns = instance.fns();
loop {
@ -172,7 +172,7 @@ impl PhysicalDevice {
ptr::null_mut(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
let mut output = Vec::with_capacity(count as usize);
let result = (fns.v1_0.enumerate_device_extension_properties)(
@ -188,7 +188,7 @@ impl PhysicalDevice {
return Ok(output.into_iter().map(Into::into).collect());
}
ash::vk::Result::INCOMPLETE => (),
err => return Err(RuntimeError::from(err)),
err => return Err(VulkanError::from(err)),
}
}
}
@ -429,7 +429,7 @@ impl PhysicalDevice {
&self,
queue_family_index: u32,
dfb: *const D,
) -> Result<bool, ValidationError> {
) -> Result<bool, Box<ValidationError>> {
self.validate_directfb_presentation_support(queue_family_index, dfb)?;
Ok(self.directfb_presentation_support_unchecked(queue_family_index, dfb))
@ -439,18 +439,18 @@ impl PhysicalDevice {
&self,
queue_family_index: u32,
_dfb: *const D,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
if !self.instance.enabled_extensions().ext_directfb_surface {
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"ext_directfb_surface",
)])]),
..Default::default()
});
}));
}
if queue_family_index >= self.queue_family_properties.len() as u32 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "queue_family_index".into(),
problem: "is not less than the number of queue families in the physical device"
.into(),
@ -458,7 +458,7 @@ impl PhysicalDevice {
"VUID-vkGetPhysicalDeviceDirectFBPresentationSupportEXT-queueFamilyIndex-04119",
],
..Default::default()
});
}));
}
// VUID-vkGetPhysicalDeviceDirectFBPresentationSupportEXT-dfb-parameter
@ -496,7 +496,7 @@ impl PhysicalDevice {
pub fn external_buffer_properties(
&self,
info: ExternalBufferInfo,
) -> Result<ExternalBufferProperties, ValidationError> {
) -> Result<ExternalBufferProperties, Box<ValidationError>> {
self.validate_external_buffer_properties(&info)?;
unsafe { Ok(self.external_buffer_properties_unchecked(info)) }
@ -505,14 +505,14 @@ impl PhysicalDevice {
fn validate_external_buffer_properties(
&self,
info: &ExternalBufferInfo,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
if !(self.instance.api_version() >= Version::V1_1
|| self
.instance
.enabled_extensions()
.khr_external_memory_capabilities)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[
RequiresAllOf(&[Requires::APIVersion(Version::V1_1)]),
RequiresAllOf(&[Requires::InstanceExtension(
@ -520,7 +520,7 @@ impl PhysicalDevice {
)]),
]),
..Default::default()
});
}));
}
info.validate(self).map_err(|err| err.add_context("info"))?;
@ -596,7 +596,7 @@ impl PhysicalDevice {
pub fn external_fence_properties(
&self,
info: ExternalFenceInfo,
) -> Result<ExternalFenceProperties, ValidationError> {
) -> Result<ExternalFenceProperties, Box<ValidationError>> {
self.validate_external_fence_properties(&info)?;
unsafe { Ok(self.external_fence_properties_unchecked(info)) }
@ -605,14 +605,14 @@ impl PhysicalDevice {
fn validate_external_fence_properties(
&self,
info: &ExternalFenceInfo,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
if !(self.instance.api_version() >= Version::V1_1
|| self
.instance
.enabled_extensions()
.khr_external_fence_capabilities)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[
RequiresAllOf(&[Requires::APIVersion(Version::V1_1)]),
RequiresAllOf(&[Requires::InstanceExtension(
@ -620,7 +620,7 @@ impl PhysicalDevice {
)]),
]),
..Default::default()
});
}));
}
info.validate(self).map_err(|err| err.add_context("info"))?;
@ -699,7 +699,7 @@ impl PhysicalDevice {
pub fn external_semaphore_properties(
&self,
info: ExternalSemaphoreInfo,
) -> Result<ExternalSemaphoreProperties, ValidationError> {
) -> Result<ExternalSemaphoreProperties, Box<ValidationError>> {
self.validate_external_semaphore_properties(&info)?;
unsafe { Ok(self.external_semaphore_properties_unchecked(info)) }
@ -708,14 +708,14 @@ impl PhysicalDevice {
fn validate_external_semaphore_properties(
&self,
info: &ExternalSemaphoreInfo,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
if !(self.instance.api_version() >= Version::V1_1
|| self
.instance
.enabled_extensions()
.khr_external_semaphore_capabilities)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[
RequiresAllOf(&[Requires::APIVersion(Version::V1_1)]),
RequiresAllOf(&[Requires::InstanceExtension(
@ -723,7 +723,7 @@ impl PhysicalDevice {
)]),
]),
..Default::default()
});
}));
}
info.validate(self).map_err(|err| err.add_context("info"))?;
@ -797,13 +797,16 @@ impl PhysicalDevice {
/// The results of this function are cached, so that future calls with the same arguments
/// do not need to make a call to the Vulkan API again.
#[inline]
pub fn format_properties(&self, format: Format) -> Result<FormatProperties, ValidationError> {
pub fn format_properties(
&self,
format: Format,
) -> Result<FormatProperties, Box<ValidationError>> {
self.validate_format_properties(format)?;
unsafe { Ok(self.format_properties_unchecked(format)) }
}
fn validate_format_properties(&self, format: Format) -> Result<(), ValidationError> {
fn validate_format_properties(&self, format: Format) -> Result<(), Box<ValidationError>> {
format
.validate_physical_device(self)
.map_err(|err| ValidationError {
@ -993,7 +996,7 @@ impl PhysicalDevice {
pub fn image_format_properties(
&self,
image_format_info: ImageFormatInfo,
) -> Result<Option<ImageFormatProperties>, VulkanError> {
) -> Result<Option<ImageFormatProperties>, Validated<VulkanError>> {
self.validate_image_format_properties(&image_format_info)?;
unsafe { Ok(self.image_format_properties_unchecked(image_format_info)?) }
@ -1002,7 +1005,7 @@ impl PhysicalDevice {
fn validate_image_format_properties(
&self,
image_format_info: &ImageFormatInfo,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
image_format_info
.validate(self)
.map_err(|err| err.add_context("image_format_info"))?;
@ -1015,7 +1018,7 @@ impl PhysicalDevice {
pub unsafe fn image_format_properties_unchecked(
&self,
mut image_format_info: ImageFormatInfo,
) -> Result<Option<ImageFormatProperties>, RuntimeError> {
) -> Result<Option<ImageFormatProperties>, VulkanError> {
{
let ImageFormatInfo {
format,
@ -1193,7 +1196,7 @@ impl PhysicalDevice {
)
}
.result()
.map_err(RuntimeError::from)
.map_err(VulkanError::from)
};
Ok(match result {
@ -1211,7 +1214,7 @@ impl PhysicalDevice {
}),
..properties2_vk.image_format_properties.into()
}),
Err(RuntimeError::FormatNotSupported) => None,
Err(VulkanError::FormatNotSupported) => None,
Err(err) => return Err(err),
})
})
@ -1227,7 +1230,7 @@ impl PhysicalDevice {
&self,
queue_family_index: u32,
window: *const W,
) -> Result<bool, ValidationError> {
) -> Result<bool, Box<ValidationError>> {
self.validate_qnx_screen_presentation_support(queue_family_index, window)?;
Ok(self.qnx_screen_presentation_support_unchecked(queue_family_index, window))
@ -1237,18 +1240,18 @@ impl PhysicalDevice {
&self,
queue_family_index: u32,
_window: *const W,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
if !self.instance.enabled_extensions().qnx_screen_surface {
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"qnx_screen_surface",
)])]),
..Default::default()
});
}));
}
if queue_family_index >= self.queue_family_properties.len() as u32 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "queue_family_index".into(),
problem: "is not less than the number of queue families in the physical device"
.into(),
@ -1256,7 +1259,7 @@ impl PhysicalDevice {
"VUID-vkGetPhysicalDeviceScreenPresentationSupportQNX-queueFamilyIndex-04743",
],
..Default::default()
});
}));
}
// VUID-vkGetPhysicalDeviceScreenPresentationSupportQNX-window-parameter
@ -1292,7 +1295,7 @@ impl PhysicalDevice {
pub fn sparse_image_format_properties(
&self,
format_info: SparseImageFormatInfo,
) -> Result<Vec<SparseImageFormatProperties>, ValidationError> {
) -> Result<Vec<SparseImageFormatProperties>, Box<ValidationError>> {
self.validate_sparse_image_format_properties(&format_info)?;
unsafe { Ok(self.sparse_image_format_properties_unchecked(format_info)) }
@ -1301,7 +1304,7 @@ impl PhysicalDevice {
fn validate_sparse_image_format_properties(
&self,
format_info: &SparseImageFormatInfo,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
format_info
.validate(self)
.map_err(|err| err.add_context("format_info"))?;
@ -1470,7 +1473,7 @@ impl PhysicalDevice {
&self,
surface: &Surface,
surface_info: SurfaceInfo,
) -> Result<SurfaceCapabilities, VulkanError> {
) -> Result<SurfaceCapabilities, Validated<VulkanError>> {
self.validate_surface_capabilities(surface, &surface_info)?;
unsafe { Ok(self.surface_capabilities_unchecked(surface, surface_info)?) }
@ -1480,20 +1483,20 @@ impl PhysicalDevice {
&self,
surface: &Surface,
surface_info: &SurfaceInfo,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
if !(self
.instance
.enabled_extensions()
.khr_get_surface_capabilities2
|| self.instance.enabled_extensions().khr_surface)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[
RequiresAllOf(&[Requires::InstanceExtension("khr_get_surface_capabilities2")]),
RequiresAllOf(&[Requires::InstanceExtension("khr_surface")]),
]),
..Default::default()
});
}));
}
// VUID-vkGetPhysicalDeviceSurfaceCapabilities2KHR-commonparent
@ -1503,12 +1506,12 @@ impl PhysicalDevice {
self.surface_support_unchecked(index, surface)
.unwrap_or_default()
}) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "surface".into(),
problem: "is not supported by the physical device".into(),
vuids: &["VUID-vkGetPhysicalDeviceSurfaceCapabilities2KHR-pSurfaceInfo-06210"],
..Default::default()
});
}));
}
surface_info
@ -1533,11 +1536,11 @@ impl PhysicalDevice {
};
if !present_modes.any(|mode| mode == present_mode) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`surface_info.present_mode` is not supported for `surface`".into(),
vuids: &["VUID-VkSurfacePresentModeEXT-presentMode-07780"],
..Default::default()
});
}));
}
}
@ -1547,7 +1550,7 @@ impl PhysicalDevice {
win32_monitor.is_some(),
) {
(true, false) => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`surface` is a Win32 surface, and \
`surface_info.full_screen_exclusive` is \
`FullScreenExclusive::ApplicationControlled`, but \
@ -1555,17 +1558,17 @@ impl PhysicalDevice {
.into(),
vuids: &["VUID-VkPhysicalDeviceSurfaceInfo2KHR-pNext-02672"],
..Default::default()
});
}));
}
(false, true) => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`surface` is not a Win32 surface, or \
`surface_info.full_screen_exclusive` is not \
`FullScreenExclusive::ApplicationControlled`, but \
`surface_info.win32_monitor` is `Some`"
.into(),
..Default::default()
});
}));
}
(true, true) | (false, false) => (),
}
@ -1578,7 +1581,7 @@ impl PhysicalDevice {
&self,
surface: &Surface,
surface_info: SurfaceInfo,
) -> Result<SurfaceCapabilities, RuntimeError> {
) -> Result<SurfaceCapabilities, VulkanError> {
/* Input */
let SurfaceInfo {
@ -1696,7 +1699,7 @@ impl PhysicalDevice {
&mut capabilities_vk,
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
} else {
(fns.khr_surface.get_physical_device_surface_capabilities_khr)(
self.handle(),
@ -1704,7 +1707,7 @@ impl PhysicalDevice {
&mut capabilities_vk.surface_capabilities,
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
};
Ok(SurfaceCapabilities {
@ -1835,7 +1838,7 @@ impl PhysicalDevice {
&self,
surface: &Surface,
surface_info: SurfaceInfo,
) -> Result<Vec<(Format, ColorSpace)>, VulkanError> {
) -> Result<Vec<(Format, ColorSpace)>, Validated<VulkanError>> {
self.validate_surface_formats(surface, &surface_info)?;
unsafe { Ok(self.surface_formats_unchecked(surface, surface_info)?) }
@ -1845,20 +1848,20 @@ impl PhysicalDevice {
&self,
surface: &Surface,
surface_info: &SurfaceInfo,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
if !(self
.instance
.enabled_extensions()
.khr_get_surface_capabilities2
|| self.instance.enabled_extensions().khr_surface)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[
RequiresAllOf(&[Requires::InstanceExtension("khr_get_surface_capabilities2")]),
RequiresAllOf(&[Requires::InstanceExtension("khr_surface")]),
]),
..Default::default()
});
}));
}
// VUID-vkGetPhysicalDeviceSurfaceFormats2KHR-commonparent
@ -1868,12 +1871,12 @@ impl PhysicalDevice {
self.surface_support_unchecked(index, surface)
.unwrap_or_default()
}) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "surface".into(),
problem: "is not supported by the physical device".into(),
vuids: &["VUID-vkGetPhysicalDeviceSurfaceFormats2KHR-pSurfaceInfo-06522"],
..Default::default()
});
}));
}
surface_info
@ -1898,11 +1901,11 @@ impl PhysicalDevice {
};
if !present_modes.any(|mode| mode == present_mode) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`surface_info.present_mode` is not supported for `surface`".into(),
vuids: &["VUID-VkSurfacePresentModeEXT-presentMode-07780"],
..Default::default()
});
}));
}
}
@ -1912,25 +1915,25 @@ impl PhysicalDevice {
.khr_get_surface_capabilities2
{
if full_screen_exclusive != FullScreenExclusive::Default {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "surface_info.full_screen_exclusive".into(),
problem: "is not `FullScreenExclusive::Default`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[
Requires::InstanceExtension("khr_get_surface_capabilities2"),
])]),
..Default::default()
});
}));
}
if win32_monitor.is_some() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "surface_info.win32_monitor".into(),
problem: "is `Some`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[
Requires::InstanceExtension("khr_get_surface_capabilities2"),
])]),
..Default::default()
});
}));
}
}
@ -1940,7 +1943,7 @@ impl PhysicalDevice {
win32_monitor.is_some(),
) {
(true, false) => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`surface` is a Win32 surface, and \
`surface_info.full_screen_exclusive` is \
`FullScreenExclusive::ApplicationControlled`, but \
@ -1948,17 +1951,17 @@ impl PhysicalDevice {
.into(),
vuids: &["VUID-VkPhysicalDeviceSurfaceInfo2KHR-pNext-02672"],
..Default::default()
});
}));
}
(false, true) => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`surface` is not a Win32 surface, or \
`surface_info.full_screen_exclusive` is not \
`FullScreenExclusive::ApplicationControlled`, but \
`surface_info.win32_monitor` is `Some`"
.into(),
..Default::default()
});
}));
}
(true, true) | (false, false) => (),
}
@ -1971,7 +1974,7 @@ impl PhysicalDevice {
&self,
surface: &Surface,
surface_info: SurfaceInfo,
) -> Result<Vec<(Format, ColorSpace)>, RuntimeError> {
) -> Result<Vec<(Format, ColorSpace)>, VulkanError> {
surface.surface_formats.get_or_try_insert(
(self.handle, surface_info),
|(_, surface_info)| {
@ -2041,7 +2044,7 @@ impl PhysicalDevice {
ptr::null_mut(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
let mut surface_format2s_vk =
vec![ash::vk::SurfaceFormat2KHR::default(); count as usize];
@ -2060,7 +2063,7 @@ impl PhysicalDevice {
break surface_format2s_vk;
}
ash::vk::Result::INCOMPLETE => (),
err => return Err(RuntimeError::from(err)),
err => return Err(VulkanError::from(err)),
}
};
@ -2081,7 +2084,7 @@ impl PhysicalDevice {
ptr::null_mut(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
let mut surface_formats = Vec::with_capacity(count as usize);
let result = (fns.khr_surface.get_physical_device_surface_formats_khr)(
@ -2097,7 +2100,7 @@ impl PhysicalDevice {
break surface_formats;
}
ash::vk::Result::INCOMPLETE => (),
err => return Err(RuntimeError::from(err)),
err => return Err(VulkanError::from(err)),
}
};
@ -2124,20 +2127,23 @@ impl PhysicalDevice {
pub fn surface_present_modes(
&self,
surface: &Surface,
) -> Result<impl Iterator<Item = PresentMode>, VulkanError> {
) -> Result<impl Iterator<Item = PresentMode>, Validated<VulkanError>> {
self.validate_surface_present_modes(surface)?;
unsafe { Ok(self.surface_present_modes_unchecked(surface)?) }
}
fn validate_surface_present_modes(&self, surface: &Surface) -> Result<(), ValidationError> {
fn validate_surface_present_modes(
&self,
surface: &Surface,
) -> Result<(), Box<ValidationError>> {
if !self.instance.enabled_extensions().khr_surface {
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"khr_surface",
)])]),
..Default::default()
});
}));
}
// VUID-vkGetPhysicalDeviceSurfacePresentModesKHR-commonparent
@ -2147,12 +2153,12 @@ impl PhysicalDevice {
self.surface_support_unchecked(index, surface)
.unwrap_or_default()
}) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "surface".into(),
problem: "is not supported by the physical device".into(),
vuids: &["VUID-vkGetPhysicalDeviceSurfacePresentModesKHR-surface-06525"],
..Default::default()
});
}));
}
Ok(())
@ -2162,7 +2168,7 @@ impl PhysicalDevice {
pub unsafe fn surface_present_modes_unchecked(
&self,
surface: &Surface,
) -> Result<impl Iterator<Item = PresentMode>, RuntimeError> {
) -> Result<impl Iterator<Item = PresentMode>, VulkanError> {
surface
.surface_present_modes
.get_or_try_insert(self.handle, |_| {
@ -2178,7 +2184,7 @@ impl PhysicalDevice {
ptr::null_mut(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
let mut modes = Vec::with_capacity(count as usize);
let result = (fns
@ -2196,7 +2202,7 @@ impl PhysicalDevice {
break modes;
}
ash::vk::Result::INCOMPLETE => (),
err => return Err(RuntimeError::from(err)),
err => return Err(VulkanError::from(err)),
}
};
@ -2217,7 +2223,7 @@ impl PhysicalDevice {
&self,
queue_family_index: u32,
surface: &Surface,
) -> Result<bool, VulkanError> {
) -> Result<bool, Validated<VulkanError>> {
self.validate_surface_support(queue_family_index, surface)?;
unsafe { Ok(self.surface_support_unchecked(queue_family_index, surface)?) }
@ -2227,24 +2233,24 @@ impl PhysicalDevice {
&self,
queue_family_index: u32,
_surface: &Surface,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
if !self.instance.enabled_extensions().khr_surface {
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"khr_surface",
)])]),
..Default::default()
});
}));
}
if queue_family_index >= self.queue_family_properties.len() as u32 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "queue_family_index".into(),
problem: "is not less than the number of queue families in the physical device"
.into(),
vuids: &["VUID-vkGetPhysicalDeviceSurfaceSupportKHR-queueFamilyIndex-01269"],
..Default::default()
});
}));
}
Ok(())
@ -2255,7 +2261,7 @@ impl PhysicalDevice {
&self,
queue_family_index: u32,
surface: &Surface,
) -> Result<bool, RuntimeError> {
) -> Result<bool, VulkanError> {
surface
.surface_support
.get_or_try_insert((self.handle, queue_family_index), |_| {
@ -2269,7 +2275,7 @@ impl PhysicalDevice {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
Ok(output.assume_init() != 0)
})
@ -2284,21 +2290,21 @@ impl PhysicalDevice {
/// [`ext_tooling_info`](crate::device::DeviceExtensions::ext_tooling_info)
/// extension must be supported by the physical device.
#[inline]
pub fn tool_properties(&self) -> Result<Vec<ToolProperties>, VulkanError> {
pub fn tool_properties(&self) -> Result<Vec<ToolProperties>, Validated<VulkanError>> {
self.validate_tool_properties()?;
unsafe { Ok(self.tool_properties_unchecked()?) }
}
fn validate_tool_properties(&self) -> Result<(), ValidationError> {
fn validate_tool_properties(&self) -> Result<(), Box<ValidationError>> {
if !(self.api_version() >= Version::V1_3 || self.supported_extensions().ext_tooling_info) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[
RequiresAllOf(&[Requires::APIVersion(Version::V1_3)]),
RequiresAllOf(&[Requires::DeviceExtension("ext_tooling_info")]),
]),
..Default::default()
});
}));
}
Ok(())
@ -2306,7 +2312,7 @@ impl PhysicalDevice {
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
#[inline]
pub unsafe fn tool_properties_unchecked(&self) -> Result<Vec<ToolProperties>, RuntimeError> {
pub unsafe fn tool_properties_unchecked(&self) -> Result<Vec<ToolProperties>, VulkanError> {
let fns = self.instance.fns();
loop {
@ -2326,7 +2332,7 @@ impl PhysicalDevice {
)
}
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
let mut tool_properties = Vec::with_capacity(count as usize);
let result = if self.api_version() >= Version::V1_3 {
@ -2375,7 +2381,7 @@ impl PhysicalDevice {
})
.collect());
}
err => return Err(RuntimeError::from(err)),
err => return Err(VulkanError::from(err)),
}
}
}
@ -2390,7 +2396,7 @@ impl PhysicalDevice {
&self,
queue_family_index: u32,
display: *const D,
) -> Result<bool, ValidationError> {
) -> Result<bool, Box<ValidationError>> {
self.validate_wayland_presentation_support(queue_family_index, display)?;
Ok(self.wayland_presentation_support_unchecked(queue_family_index, display))
@ -2400,18 +2406,18 @@ impl PhysicalDevice {
&self,
queue_family_index: u32,
_display: *const D,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
if !self.instance.enabled_extensions().khr_wayland_surface {
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"khr_wayland_surface",
)])]),
..Default::default()
});
}));
}
if queue_family_index >= self.queue_family_properties.len() as u32 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "queue_family_index".into(),
problem: "is not less than the number of queue families in the physical device"
.into(),
@ -2419,7 +2425,7 @@ impl PhysicalDevice {
"VUID-vkGetPhysicalDeviceWaylandPresentationSupportKHR-queueFamilyIndex-01306",
],
..Default::default()
});
}));
}
// VUID-vkGetPhysicalDeviceWaylandPresentationSupportKHR-display-parameter
@ -2449,7 +2455,7 @@ impl PhysicalDevice {
pub fn win32_presentation_support(
&self,
queue_family_index: u32,
) -> Result<bool, ValidationError> {
) -> Result<bool, Box<ValidationError>> {
self.validate_win32_presentation_support(queue_family_index)?;
unsafe { Ok(self.win32_presentation_support_unchecked(queue_family_index)) }
@ -2458,18 +2464,18 @@ impl PhysicalDevice {
fn validate_win32_presentation_support(
&self,
queue_family_index: u32,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
if !self.instance.enabled_extensions().khr_win32_surface {
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"khr_win32_surface",
)])]),
..Default::default()
});
}));
}
if queue_family_index >= self.queue_family_properties.len() as u32 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "queue_family_index".into(),
problem: "is not less than the number of queue families in the physical device"
.into(),
@ -2477,7 +2483,7 @@ impl PhysicalDevice {
"VUID-vkGetPhysicalDeviceWin32PresentationSupportKHR-queueFamilyIndex-01309",
],
..Default::default()
});
}));
}
Ok(())
@ -2504,7 +2510,7 @@ impl PhysicalDevice {
queue_family_index: u32,
connection: *const C,
visual_id: ash::vk::xcb_visualid_t,
) -> Result<bool, ValidationError> {
) -> Result<bool, Box<ValidationError>> {
self.validate_xcb_presentation_support(queue_family_index, connection, visual_id)?;
Ok(self.xcb_presentation_support_unchecked(queue_family_index, connection, visual_id))
@ -2515,18 +2521,18 @@ impl PhysicalDevice {
queue_family_index: u32,
_connection: *const C,
_visual_id: ash::vk::xcb_visualid_t,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
if !self.instance.enabled_extensions().khr_xcb_surface {
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"khr_xcb_surface",
)])]),
..Default::default()
});
}));
}
if queue_family_index >= self.queue_family_properties.len() as u32 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "queue_family_index".into(),
problem: "is not less than the number of queue families in the physical device"
.into(),
@ -2534,7 +2540,7 @@ impl PhysicalDevice {
"VUID-vkGetPhysicalDeviceXcbPresentationSupportKHR-queueFamilyIndex-01312",
],
..Default::default()
});
}));
}
// VUID-vkGetPhysicalDeviceXcbPresentationSupportKHR-connection-parameter
@ -2571,7 +2577,7 @@ impl PhysicalDevice {
queue_family_index: u32,
display: *const D,
visual_id: ash::vk::VisualID,
) -> Result<bool, ValidationError> {
) -> Result<bool, Box<ValidationError>> {
self.validate_xlib_presentation_support(queue_family_index, display, visual_id)?;
Ok(self.xlib_presentation_support_unchecked(queue_family_index, display, visual_id))
@ -2582,18 +2588,18 @@ impl PhysicalDevice {
queue_family_index: u32,
_display: *const D,
_visual_id: ash::vk::VisualID,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
if !self.instance.enabled_extensions().khr_xlib_surface {
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"khr_xlib_surface",
)])]),
..Default::default()
});
}));
}
if queue_family_index >= self.queue_family_properties.len() as u32 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "queue_family_index".into(),
problem: "is not less than the number of queue families in the physical device"
.into(),
@ -2601,7 +2607,7 @@ impl PhysicalDevice {
"VUID-vkGetPhysicalDeviceXlibPresentationSupportKHR-queueFamilyIndex-01315",
],
..Default::default()
});
}));
}
// VUID-vkGetPhysicalDeviceXlibPresentationSupportKHR-dpy-parameter

View File

@ -26,7 +26,7 @@ use crate::{
future::{AccessCheckError, FlushError, GpuFuture},
semaphore::SemaphoreState,
},
OomError, Requires, RequiresAllOf, RequiresOneOf, RuntimeError, ValidationError, Version,
OomError, Requires, RequiresAllOf, RequiresOneOf, ValidationError, Version, VulkanError,
VulkanObject,
};
use ahash::HashMap;
@ -202,7 +202,7 @@ impl<'a> QueueGuard<'a> {
&mut self,
bind_infos: impl IntoIterator<Item = BindSparseInfo>,
fence: Option<Arc<Fence>>,
) -> Result<(), RuntimeError> {
) -> Result<(), VulkanError> {
let bind_infos: SmallVec<[_; 4]> = bind_infos.into_iter().collect();
let mut states = States::from_bind_infos(&bind_infos);
@ -221,7 +221,7 @@ impl<'a> QueueGuard<'a> {
bind_infos: &SmallVec<[BindSparseInfo; 4]>,
fence: Option<(&Arc<Fence>, MutexGuard<'_, FenceState>)>,
states: &mut States<'_>,
) -> Result<(), RuntimeError> {
) -> Result<(), VulkanError> {
struct PerBindSparseInfo {
wait_semaphores_vk: SmallVec<[ash::vk::Semaphore; 4]>,
buffer_bind_infos_vk: SmallVec<[ash::vk::SparseBufferMemoryBindInfo; 4]>,
@ -478,7 +478,7 @@ impl<'a> QueueGuard<'a> {
.map_or_else(Default::default, |(fence, _)| fence.handle()),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
for bind_info in bind_infos {
let BindSparseInfo {
@ -518,7 +518,7 @@ impl<'a> QueueGuard<'a> {
pub unsafe fn present_unchecked(
&mut self,
present_info: PresentInfo,
) -> Result<impl ExactSizeIterator<Item = Result<bool, RuntimeError>>, RuntimeError> {
) -> Result<impl ExactSizeIterator<Item = Result<bool, VulkanError>>, VulkanError> {
let mut states = States::from_present_info(&present_info);
self.present_unchecked_locked(&present_info, &mut states)
}
@ -527,7 +527,7 @@ impl<'a> QueueGuard<'a> {
&mut self,
present_info: &PresentInfo,
states: &mut States<'_>,
) -> Result<impl ExactSizeIterator<Item = Result<bool, RuntimeError>>, RuntimeError> {
) -> Result<impl ExactSizeIterator<Item = Result<bool, VulkanError>>, VulkanError> {
let PresentInfo {
wait_semaphores,
swapchain_infos,
@ -657,7 +657,7 @@ impl<'a> QueueGuard<'a> {
| ash::vk::Result::ERROR_SURFACE_LOST_KHR
| ash::vk::Result::ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT,
) {
return Err(RuntimeError::from(result));
return Err(VulkanError::from(result));
}
for semaphore in wait_semaphores {
@ -683,7 +683,7 @@ impl<'a> QueueGuard<'a> {
Ok(results.into_iter().map(|result| match result {
ash::vk::Result::SUCCESS => Ok(false),
ash::vk::Result::SUBOPTIMAL_KHR => Ok(true),
err => Err(RuntimeError::from(err)),
err => Err(VulkanError::from(err)),
}))
}
@ -817,7 +817,7 @@ impl<'a> QueueGuard<'a> {
&mut self,
submit_infos: impl IntoIterator<Item = SubmitInfo>,
fence: Option<Arc<Fence>>,
) -> Result<(), RuntimeError> {
) -> Result<(), VulkanError> {
let submit_infos: SmallVec<[_; 4]> = submit_infos.into_iter().collect();
let mut states = States::from_submit_infos(&submit_infos);
@ -836,7 +836,7 @@ impl<'a> QueueGuard<'a> {
submit_infos: &SmallVec<[SubmitInfo; 4]>,
fence: Option<(&Arc<Fence>, MutexGuard<'_, FenceState>)>,
states: &mut States<'_>,
) -> Result<(), RuntimeError> {
) -> Result<(), VulkanError> {
if self.queue.device.enabled_features().synchronization2 {
struct PerSubmitInfo {
wait_semaphore_infos_vk: SmallVec<[ash::vk::SemaphoreSubmitInfo; 4]>,
@ -965,7 +965,7 @@ impl<'a> QueueGuard<'a> {
)
}
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
} else {
struct PerSubmitInfo {
wait_semaphores_vk: SmallVec<[ash::vk::Semaphore; 4]>,
@ -1067,7 +1067,7 @@ impl<'a> QueueGuard<'a> {
.map_or_else(Default::default, |(fence, _)| fence.handle()),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
}
for submit_info in submit_infos {
@ -1155,7 +1155,7 @@ impl<'a> QueueGuard<'a> {
pub fn begin_debug_utils_label(
&mut self,
label_info: DebugUtilsLabel,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
self.validate_begin_debug_utils_label(&label_info)?;
unsafe {
@ -1167,7 +1167,7 @@ impl<'a> QueueGuard<'a> {
fn validate_begin_debug_utils_label(
&self,
_label_info: &DebugUtilsLabel,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
if !self
.queue
.device
@ -1175,12 +1175,12 @@ impl<'a> QueueGuard<'a> {
.enabled_extensions()
.ext_debug_utils
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"ext_debug_utils",
)])]),
..Default::default()
});
}));
}
Ok(())
@ -1216,14 +1216,14 @@ impl<'a> QueueGuard<'a> {
/// - There must be an outstanding queue label region begun with `begin_debug_utils_label` in
/// the queue.
#[inline]
pub unsafe fn end_debug_utils_label(&mut self) -> Result<(), ValidationError> {
pub unsafe fn end_debug_utils_label(&mut self) -> Result<(), Box<ValidationError>> {
self.validate_end_debug_utils_label()?;
self.end_debug_utils_label_unchecked();
Ok(())
}
fn validate_end_debug_utils_label(&self) -> Result<(), ValidationError> {
fn validate_end_debug_utils_label(&self) -> Result<(), Box<ValidationError>> {
if !self
.queue
.device
@ -1231,12 +1231,12 @@ impl<'a> QueueGuard<'a> {
.enabled_extensions()
.ext_debug_utils
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"ext_debug_utils",
)])]),
..Default::default()
});
}));
}
// VUID-vkQueueEndDebugUtilsLabelEXT-None-01911
@ -1260,7 +1260,7 @@ impl<'a> QueueGuard<'a> {
pub fn insert_debug_utils_label(
&mut self,
label_info: DebugUtilsLabel,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
self.validate_insert_debug_utils_label(&label_info)?;
unsafe {
@ -1272,7 +1272,7 @@ impl<'a> QueueGuard<'a> {
fn validate_insert_debug_utils_label(
&self,
_label_info: &DebugUtilsLabel,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
if !self
.queue
.device
@ -1280,12 +1280,12 @@ impl<'a> QueueGuard<'a> {
.enabled_extensions()
.ext_debug_utils
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"ext_debug_utils",
)])]),
..Default::default()
});
}));
}
Ok(())
@ -1323,7 +1323,7 @@ impl QueueState {
let fns = device.fns();
(fns.v1_0.queue_wait_idle)(handle)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
// Since we now know that the queue is finished with all work,
// we can safely release all resources.

View File

@ -75,7 +75,7 @@ use crate::{
range_map::RangeMap,
swapchain::Swapchain,
sync::{future::AccessError, AccessConflict, CurrentAccess, Sharing},
DeviceSize, Requires, RequiresAllOf, RequiresOneOf, RuntimeError, ValidationError, Version,
DeviceSize, Requires, RequiresAllOf, RequiresOneOf, Validated, ValidationError, Version,
VulkanError, VulkanObject,
};
use parking_lot::{Mutex, MutexGuard};
@ -146,15 +146,18 @@ impl Image {
/// Creates a new uninitialized `Image`.
pub fn new(
allocator: &(impl MemoryAllocator + ?Sized),
image_info: ImageCreateInfo,
create_info: ImageCreateInfo,
allocation_info: AllocationCreateInfo,
) -> Result<Arc<Self>, ImageAllocateError> {
) -> Result<Arc<Self>, Validated<ImageAllocateError>> {
// TODO: adjust the code below to make this safe
assert!(!image_info.flags.intersects(ImageCreateFlags::DISJOINT));
assert!(!create_info.flags.intersects(ImageCreateFlags::DISJOINT));
let allocation_type = image_info.tiling.into();
let raw_image = RawImage::new(allocator.device().clone(), image_info)
.map_err(ImageAllocateError::CreateImage)?;
let allocation_type = create_info.tiling.into();
let raw_image =
RawImage::new(allocator.device().clone(), create_info).map_err(|err| match err {
Validated::Error(err) => Validated::Error(ImageAllocateError::CreateImage(err)),
Validated::ValidationError(err) => err.into(),
})?;
let requirements = raw_image.memory_requirements()[0];
let allocation = unsafe {
@ -207,7 +210,7 @@ impl Image {
handle: ash::vk::Image,
swapchain: Arc<Swapchain>,
image_index: u32,
) -> Result<Self, RuntimeError> {
) -> Result<Self, VulkanError> {
let create_info = ImageCreateInfo {
flags: ImageCreateFlags::empty(),
image_type: ImageType::Dim2d,
@ -381,7 +384,7 @@ impl Image {
aspect: ImageAspect,
mip_level: u32,
array_layer: u32,
) -> Result<SubresourceLayout, ValidationError> {
) -> Result<SubresourceLayout, Box<ValidationError>> {
self.inner
.subresource_layout(aspect, mip_level, array_layer)
}
@ -570,7 +573,7 @@ impl Hash for Image {
pub enum ImageAllocateError {
CreateImage(VulkanError),
AllocateMemory(MemoryAllocatorError),
BindMemory(RuntimeError),
BindMemory(VulkanError),
}
impl Error for ImageAllocateError {
@ -593,6 +596,12 @@ impl Display for ImageAllocateError {
}
}
impl From<ImageAllocateError> for Validated<ImageAllocateError> {
fn from(err: ImageAllocateError) -> Self {
Self::Error(err)
}
}
/// The current state of an image.
#[derive(Debug)]
pub(crate) struct ImageState {
@ -1378,7 +1387,7 @@ impl ImageSubresourceLayers {
}
impl ImageSubresourceLayers {
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
aspects,
mip_level: _,
@ -1394,34 +1403,34 @@ impl ImageSubresourceLayers {
})?;
if aspects.is_empty() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "aspects".into(),
problem: "is empty".into(),
vuids: &["VUID-VkImageSubresourceLayers-aspectMask-requiredbitmask"],
..Default::default()
});
}));
}
if aspects.intersects(ImageAspects::COLOR)
&& aspects.intersects(ImageAspects::DEPTH | ImageAspects::STENCIL)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "aspects".into(),
problem: "contains both `ImageAspects::COLOR`, and either `ImageAspects::DEPTH` \
or `ImageAspects::STENCIL`"
.into(),
vuids: &["VUID-VkImageSubresourceLayers-aspectMask-00167"],
..Default::default()
});
}));
}
if aspects.intersects(ImageAspects::METADATA) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "aspects".into(),
problem: "contains `ImageAspects::METADATA`".into(),
vuids: &["VUID-VkImageSubresourceLayers-aspectMask-00168"],
..Default::default()
});
}));
}
if aspects.intersects(
@ -1430,7 +1439,7 @@ impl ImageSubresourceLayers {
| ImageAspects::MEMORY_PLANE_2
| ImageAspects::MEMORY_PLANE_3,
) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "aspects".into(),
problem: "contains `ImageAspects::MEMORY_PLANE_0`, \
`ImageAspects::MEMORY_PLANE_1`, `ImageAspects::MEMORY_PLANE_2` or \
@ -1438,16 +1447,16 @@ impl ImageSubresourceLayers {
.into(),
vuids: &["VUID-VkImageSubresourceLayers-aspectMask-02247"],
..Default::default()
});
}));
}
if array_layers.is_empty() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "array_layers".into(),
problem: "is empty".into(),
vuids: &["VUID-VkImageSubresourceLayers-layerCount-01700"],
..Default::default()
});
}));
}
Ok(())
@ -1511,7 +1520,7 @@ impl ImageSubresourceRange {
}
}
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
aspects,
ref mip_levels,
@ -1527,44 +1536,44 @@ impl ImageSubresourceRange {
})?;
if aspects.is_empty() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "aspects".into(),
problem: "is empty".into(),
vuids: &["VUID-VkImageSubresourceRange-aspectMask-requiredbitmask"],
..Default::default()
});
}));
}
if mip_levels.is_empty() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "mip_levels".into(),
problem: "is empty".into(),
vuids: &["VUID-VkImageSubresourceRange-levelCount-01720"],
..Default::default()
});
}));
}
if array_layers.is_empty() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "array_layers".into(),
problem: "is empty".into(),
vuids: &["VUID-VkImageSubresourceRange-layerCount-01721"],
..Default::default()
});
}));
}
if aspects.intersects(ImageAspects::COLOR)
&& aspects
.intersects(ImageAspects::PLANE_0 | ImageAspects::PLANE_1 | ImageAspects::PLANE_2)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "aspects".into(),
problem: "contains both `ImageAspects::COLOR`, and one of \
`ImageAspects::PLANE_0`, `ImageAspects::PLANE_1` or `ImageAspects::PLANE_2`"
.into(),
vuids: &["VUID-VkImageSubresourceRange-aspectMask-01670"],
..Default::default()
});
}));
}
if aspects.intersects(
@ -1573,7 +1582,7 @@ impl ImageSubresourceRange {
| ImageAspects::MEMORY_PLANE_2
| ImageAspects::MEMORY_PLANE_3,
) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "aspects".into(),
problem: "contains `ImageAspects::MEMORY_PLANE_0`, \
`ImageAspects::MEMORY_PLANE_1`, `ImageAspects::MEMORY_PLANE_2` or \
@ -1581,7 +1590,7 @@ impl ImageSubresourceRange {
.into(),
vuids: &["VUID-VkImageSubresourceLayers-aspectMask-02247"],
..Default::default()
});
}));
}
Ok(())
@ -1733,7 +1742,10 @@ impl Default for ImageFormatInfo {
}
impl ImageFormatInfo {
pub(crate) fn validate(&self, physical_device: &PhysicalDevice) -> Result<(), ValidationError> {
pub(crate) fn validate(
&self,
physical_device: &PhysicalDevice,
) -> Result<(), Box<ValidationError>> {
let &Self {
flags,
format,
@ -1796,12 +1808,12 @@ impl ImageFormatInfo {
})?;
if usage.is_empty() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "usage".into(),
problem: "is empty".into(),
vuids: &["VUID-VkPhysicalDeviceImageFormatInfo2-usage-requiredbitmask"],
..Default::default()
});
}));
}
let has_separate_stencil_usage = if aspects
@ -1820,7 +1832,7 @@ impl ImageFormatInfo {
.supported_extensions()
.ext_separate_stencil_usage)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`stencil_usage` is `Some`, and `format` has both a depth and a \
stencil aspect"
.into(),
@ -1829,7 +1841,7 @@ impl ImageFormatInfo {
RequiresAllOf(&[Requires::DeviceExtension("ext_separate_stencil_usage")]),
]),
..Default::default()
});
}));
}
stencil_usage
@ -1841,12 +1853,12 @@ impl ImageFormatInfo {
})?;
if stencil_usage.is_empty() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "stencil_usage".into(),
problem: "is empty".into(),
vuids: &["VUID-VkImageStencilUsageCreateInfo-usage-requiredbitmask"],
..Default::default()
});
}));
}
}
@ -1857,7 +1869,7 @@ impl ImageFormatInfo {
.enabled_extensions()
.khr_external_memory_capabilities)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`external_memory_handle_type` is `Some`".into(),
requires_one_of: RequiresOneOf(&[
RequiresAllOf(&[Requires::APIVersion(Version::V1_1)]),
@ -1866,7 +1878,7 @@ impl ImageFormatInfo {
)]),
]),
..Default::default()
});
}));
}
handle_type
@ -1880,13 +1892,13 @@ impl ImageFormatInfo {
if let Some(image_view_type) = image_view_type {
if !physical_device.supported_extensions().ext_filter_cubic {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`image_view_type` is `Some`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceExtension(
"ext_filter_cubic",
)])]),
..Default::default()
});
}));
}
image_view_type
@ -1905,14 +1917,14 @@ impl ImageFormatInfo {
.supported_extensions()
.ext_image_drm_format_modifier
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "drm_format_modifier_info".into(),
problem: "is `Some`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceExtension(
"ext_image_drm_format_modifier",
)])]),
..Default::default()
});
}));
}
drm_format_modifier_info
@ -1920,32 +1932,32 @@ impl ImageFormatInfo {
.map_err(|err| err.add_context("drm_format_modifier_info"))?;
if tiling != ImageTiling::DrmFormatModifier {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`drm_format_modifier_info` is `Some` but \
`tiling` is not `ImageTiling::DrmFormatModifier`"
.into(),
vuids: &[" VUID-VkPhysicalDeviceImageFormatInfo2-tiling-02249"],
..Default::default()
});
}));
}
if flags.intersects(ImageCreateFlags::MUTABLE_FORMAT) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`tiling` is `ImageTiling::DrmFormatModifier`, but \
`flags` contains `ImageCreateFlags::MUTABLE_FORMAT`"
.into(),
vuids: &["VUID-VkPhysicalDeviceImageFormatInfo2-tiling-02313"],
..Default::default()
});
}));
}
} else if tiling == ImageTiling::DrmFormatModifier {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`tiling` is `ImageTiling::DrmFormatModifier`, but \
`drm_format_modifier_info` is `None`"
.into(),
vuids: &[" VUID-VkPhysicalDeviceImageFormatInfo2-tiling-02249"],
..Default::default()
});
}));
}
Ok(())
@ -1981,7 +1993,10 @@ impl Default for ImageDrmFormatModifierInfo {
}
impl ImageDrmFormatModifierInfo {
pub(crate) fn validate(&self, physical_device: &PhysicalDevice) -> Result<(), ValidationError> {
pub(crate) fn validate(
&self,
physical_device: &PhysicalDevice,
) -> Result<(), Box<ValidationError>> {
let &Self {
drm_format_modifier: _,
ref sharing,
@ -1992,7 +2007,7 @@ impl ImageDrmFormatModifierInfo {
Sharing::Exclusive => (),
Sharing::Concurrent(queue_family_indices) => {
if queue_family_indices.len() < 2 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "sharing".into(),
problem: "is `Sharing::Concurrent`, but contains less than 2 elements"
.into(),
@ -2000,14 +2015,14 @@ impl ImageDrmFormatModifierInfo {
"VUID-VkPhysicalDeviceImageDrmFormatModifierInfoEXT-sharingMode-02315",
],
..Default::default()
});
}));
}
let queue_family_count = physical_device.queue_family_properties().len() as u32;
for (index, &queue_family_index) in queue_family_indices.iter().enumerate() {
if queue_family_indices[..index].contains(&queue_family_index) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "queue_family_indices".into(),
problem: format!(
"the queue family index in the list at index {} is contained in \
@ -2017,17 +2032,17 @@ impl ImageDrmFormatModifierInfo {
.into(),
vuids: &[" VUID-VkPhysicalDeviceImageDrmFormatModifierInfoEXT-sharingMode-02316"],
..Default::default()
});
}));
}
if queue_family_index >= queue_family_count {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("sharing[{}]", index).into(),
problem: "is not less than the number of queue families in the device"
.into(),
vuids: &[" VUID-VkPhysicalDeviceImageDrmFormatModifierInfoEXT-sharingMode-02316"],
..Default::default()
});
}));
}
}
}
@ -2139,7 +2154,10 @@ impl Default for SparseImageFormatInfo {
}
impl SparseImageFormatInfo {
pub(crate) fn validate(&self, physical_device: &PhysicalDevice) -> Result<(), ValidationError> {
pub(crate) fn validate(
&self,
physical_device: &PhysicalDevice,
) -> Result<(), Box<ValidationError>> {
let &Self {
format,
image_type,
@ -2189,12 +2207,12 @@ impl SparseImageFormatInfo {
})?;
if usage.is_empty() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "usage".into(),
problem: "is empty".into(),
vuids: &["VUID-VkPhysicalDeviceSparseImageFormatInfo2-usage-requiredbitmask"],
..Default::default()
});
}));
}
tiling

View File

@ -58,8 +58,7 @@ use crate::{
macros::{impl_id_counter, vulkan_enum},
pipeline::graphics::depth_stencil::CompareOp,
shader::ShaderScalarType,
Requires, RequiresAllOf, RequiresOneOf, RuntimeError, ValidationError, VulkanError,
VulkanObject,
Requires, RequiresAllOf, RequiresOneOf, Validated, ValidationError, VulkanError, VulkanObject,
};
use std::{mem::MaybeUninit, num::NonZeroU64, ops::RangeInclusive, ptr, sync::Arc};
@ -118,7 +117,7 @@ impl Sampler {
pub fn new(
device: Arc<Device>,
create_info: SamplerCreateInfo,
) -> Result<Arc<Sampler>, VulkanError> {
) -> Result<Arc<Sampler>, Validated<VulkanError>> {
Self::validate_new(&device, &create_info)?;
unsafe { Ok(Self::new_unchecked(device, create_info)?) }
@ -127,7 +126,7 @@ impl Sampler {
fn validate_new(
device: &Device,
create_info: &SamplerCreateInfo,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
create_info
.validate(device)
.map_err(|err| err.add_context("create_info"))?;
@ -139,7 +138,7 @@ impl Sampler {
pub unsafe fn new_unchecked(
device: Arc<Device>,
create_info: SamplerCreateInfo,
) -> Result<Arc<Sampler>, RuntimeError> {
) -> Result<Arc<Sampler>, VulkanError> {
let &SamplerCreateInfo {
mag_filter,
min_filter,
@ -223,7 +222,7 @@ impl Sampler {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -281,7 +280,10 @@ impl Sampler {
}
/// Checks whether this sampler is compatible with `image_view`.
pub fn check_can_sample(&self, image_view: &ImageView) -> Result<(), ValidationError> {
pub(crate) fn check_can_sample(
&self,
image_view: &ImageView,
) -> Result<(), Box<ValidationError>> {
/*
NOTE: Most of these checks come from the Instruction/Sampler/Image View Validation
section, and are not strictly VUIDs.
@ -294,13 +296,13 @@ impl Sampler {
.format_features()
.intersects(FormatFeatures::SAMPLED_IMAGE_DEPTH_COMPARISON)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the sampler has depth comparison enabled, and \
the image view's format features do not include \
`FormatFeatures::SAMPLED_IMAGE_DEPTH_COMPARISON`"
.into(),
..Default::default()
});
}));
}
// The SPIR-V instruction is one of the OpImage*Dref* instructions, the image
@ -311,12 +313,12 @@ impl Sampler {
.aspects
.intersects(ImageAspects::DEPTH)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the sampler has depth comparison enabled, and \
the image view's aspects do not include `ImageAspects::DEPTH`"
.into(),
..Default::default()
});
}));
}
} else {
if !image_view
@ -325,24 +327,24 @@ impl Sampler {
{
// VUID-vkCmdDispatch-magFilter-04553
if self.mag_filter == Filter::Linear || self.min_filter == Filter::Linear {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the sampler's `mag_filter` or `min_filter` is `Filter::Linear`, \
and the image view's format features do not include \
`FormatFeatures::SAMPLED_IMAGE_FILTER_LINEAR`"
.into(),
..Default::default()
});
}));
}
// VUID-vkCmdDispatch-mipmapMode-04770
if self.mipmap_mode == SamplerMipmapMode::Linear {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the sampler's `mipmap_mode` is `SamplerMipmapMpde::Linear`, and \
the image view's format features do not include \
`FormatFeatures::SAMPLED_IMAGE_FILTER_LINEAR`"
.into(),
..Default::default()
});
}));
}
}
}
@ -353,24 +355,24 @@ impl Sampler {
.format_features()
.intersects(FormatFeatures::SAMPLED_IMAGE_FILTER_CUBIC)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the sampler's `mag_filter` or `min_filter` is `Filter::Cubic`, and \
the image view's format features do not include \
`FormatFeatures::SAMPLED_IMAGE_FILTER_CUBIC`"
.into(),
..Default::default()
});
}));
}
// VUID-vkCmdDispatch-filterCubic-02694
if !image_view.filter_cubic() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the sampler's `mag_filter` or `min_filter` is Filter::Cubic, and \
the image view does not support this, as returned by \
`PhysicalDevice::image_format_properties`"
.into(),
..Default::default()
});
}));
}
// VUID-vkCmdDispatch-filterCubicMinmax-02695
@ -379,7 +381,7 @@ impl Sampler {
SamplerReductionMode::Min | SamplerReductionMode::Max
) && !image_view.filter_cubic_minmax()
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the sampler's `mag_filter` or `min_filter` is `Filter::Cubic`, and \
the its `reduction_mode` is `SamplerReductionMode::Min` or \
`SamplerReductionMode::Max`, and \
@ -387,7 +389,7 @@ impl Sampler {
`PhysicalDevice::image_format_properties`"
.into(),
..Default::default()
});
}));
}
}
@ -423,12 +425,12 @@ impl Sampler {
view_scalar_type,
ShaderScalarType::Sint | ShaderScalarType::Uint
) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the sampler has an integer border color, and \
the image view does not have an integer format"
.into(),
..Default::default()
});
}));
}
}
BorderColor::FloatTransparentBlack
@ -438,12 +440,12 @@ impl Sampler {
// format is not one of the VkFormat float types or a depth
// component of a depth/stencil format.
if !matches!(view_scalar_type, ShaderScalarType::Float) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the sampler has an floating-point border color, and \
the image view does not have a floating-point format"
.into(),
..Default::default()
});
}));
}
}
}
@ -460,12 +462,12 @@ impl Sampler {
BorderColor::FloatOpaqueBlack | BorderColor::IntOpaqueBlack
) && !image_view.component_mapping().is_identity()
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the sampler has an opaque black border color, and \
the image view is not identity swizzled"
.into(),
..Default::default()
});
}));
}
}
@ -480,13 +482,13 @@ impl Sampler {
image_view.view_type(),
ImageViewType::Dim1d | ImageViewType::Dim2d
) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the sampler uses unnormalized coordinates, and \
the image view's type is not `ImageViewtype::Dim1d` or \
`ImageViewType::Dim2d`"
.into(),
..Default::default()
});
}));
}
// The image view must have a single layer and a single mip level.
@ -494,12 +496,12 @@ impl Sampler {
- image_view.subresource_range().mip_levels.start
!= 1
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the sampler uses unnormalized coordinates, and \
the image view has more than one mip level"
.into(),
..Default::default()
});
}));
}
}
@ -797,7 +799,7 @@ impl SamplerCreateInfo {
}
}
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
mag_filter,
min_filter,
@ -875,7 +877,7 @@ impl SamplerCreateInfo {
if !(device.enabled_features().sampler_mirror_clamp_to_edge
|| device.enabled_extensions().khr_sampler_mirror_clamp_to_edge)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "address_mode".into(),
problem: "contains `SamplerAddressMode::MirrorClampToEdge`".into(),
requires_one_of: RequiresOneOf(&[
@ -885,34 +887,34 @@ impl SamplerCreateInfo {
)]),
]),
..Default::default()
});
}));
}
}
if lod.is_empty() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "lod".into(),
problem: "is empty".into(),
vuids: &["VUID-VkSamplerCreateInfo-maxLod-01973"],
..Default::default()
});
}));
}
if mip_lod_bias.abs() > properties.max_sampler_lod_bias {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "lod".into(),
problem: "the absolute value is greater than the `max_sampler_lod_bias` limit"
.into(),
vuids: &["VUID-VkSamplerCreateInfo-mipLodBias-01069"],
..Default::default()
});
}));
}
if device.enabled_extensions().khr_portability_subset
&& !device.enabled_features().sampler_mip_lod_bias
&& mip_lod_bias != 0.0
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "this device is a portability subset device, and \
`mip_lod_bias` is not zero"
.into(),
@ -921,47 +923,47 @@ impl SamplerCreateInfo {
)])]),
vuids: &["VUID-VkSamplerCreateInfo-samplerMipLodBias-04467"],
..Default::default()
});
}));
}
if let Some(max_anisotropy) = anisotropy {
if !device.enabled_features().sampler_anisotropy {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "anisotropy".into(),
problem: "is `Some`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"sampler_anisotropy",
)])]),
vuids: &["VUID-VkSamplerCreateInfo-anisotropyEnable-01070"],
});
}));
}
if max_anisotropy < 1.0 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "anisotropy".into(),
problem: "is less than 1.0".into(),
vuids: &["VUID-VkSamplerCreateInfo-anisotropyEnable-01071"],
..Default::default()
});
}));
}
if max_anisotropy > properties.max_sampler_anisotropy {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "anisotropy".into(),
problem: "is greater than the `max_sampler_anisotropy` limit".into(),
vuids: &["VUID-VkSamplerCreateInfo-anisotropyEnable-01071"],
..Default::default()
});
}));
}
if [mag_filter, min_filter].contains(&Filter::Cubic) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`anisotropy` is `Some`, but `mag_filter` or `min_filter` is \
`Filter::Cubic`"
.into(),
vuids: &["VUID-VkSamplerCreateInfo-magFilter-01081"],
..Default::default()
});
}));
}
}
@ -975,45 +977,45 @@ impl SamplerCreateInfo {
})?;
if reduction_mode != SamplerReductionMode::WeightedAverage {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`compare` is `Some`, but `reduction_mode` is not \
`SamplerReductionMode::WeightedAverage`"
.into(),
vuids: &["VUID-VkSamplerCreateInfo-compareEnable-01423"],
..Default::default()
});
}));
}
}
if unnormalized_coordinates {
if min_filter != mag_filter {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`unnormalized_coordinates` is `true`, but \
`min_filter` and `mag_filter` are not equal"
.into(),
vuids: &["VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01072"],
..Default::default()
});
}));
}
if mipmap_mode != SamplerMipmapMode::Nearest {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`unnormalized_coordinates` is `true`, but \
`mipmap_mode` is not `SamplerMipmapMode::Nearest`"
.into(),
vuids: &["VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01073"],
..Default::default()
});
}));
}
if *lod != (0.0..=0.0) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`unnormalized_coordinates` is `true`, but \
`lod` is not `0.0..=1.0`"
.into(),
vuids: &["VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01074"],
..Default::default()
});
}));
}
if address_mode[0..2].iter().any(|mode| {
@ -1022,31 +1024,31 @@ impl SamplerCreateInfo {
SamplerAddressMode::ClampToEdge | SamplerAddressMode::ClampToBorder
)
}) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`unnormalized_coordinates` is `true`, but \
`address_mode[0]` or `address_mode[1]` are not \
`SamplerAddressMode::ClampToEdge` or `SamplerAddressMode::ClampToBorder`"
.into(),
vuids: &["VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01075"],
..Default::default()
});
}));
}
if anisotropy.is_some() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`unnormalized_coordinates` is `true`, but `anisotropy` is `Some`"
.into(),
vuids: &["VUID-VkSamplerCreateInfo-unnormalizedCoordinates-01076"],
..Default::default()
});
}));
}
if compare.is_some() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`unnormalized_coordinates` is `true`, but `compare` is `Some`".into(),
vuids: &["VUID-VkSamplerCreateInfo-unnormalizedCoordinates-0107"],
..Default::default()
});
}));
}
}
@ -1054,7 +1056,7 @@ impl SamplerCreateInfo {
if !(device.enabled_features().sampler_filter_minmax
|| device.enabled_extensions().ext_sampler_filter_minmax)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "reduction_mode".into(),
problem: "is not `SamplerReductionMode::WeightedAverage`".into(),
requires_one_of: RequiresOneOf(&[
@ -1062,7 +1064,7 @@ impl SamplerCreateInfo {
RequiresAllOf(&[Requires::DeviceExtension("ext_sampler_filter_minmax")]),
]),
..Default::default()
});
}));
}
}
@ -1084,7 +1086,7 @@ impl SamplerCreateInfo {
) && !(mag_filter == sampler_ycbcr_conversion.chroma_filter()
&& min_filter == sampler_ycbcr_conversion.chroma_filter())
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`sampler_ycbcr_conversion` is `Some`, and \
the potential format features of `sampler_ycbcr_conversion.format()` \
do not include `FormatFeatures::\
@ -1094,51 +1096,51 @@ impl SamplerCreateInfo {
.into(),
vuids: &["VUID-VkSamplerCreateInfo-minFilter-01645"],
..Default::default()
});
}));
}
if address_mode
.into_iter()
.any(|mode| !matches!(mode, SamplerAddressMode::ClampToEdge))
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`sampler_ycbcr_conversion` is `Some`, but \
not all elements of `address_mode` are \
`SamplerAddressMode::ClampToEdge`"
.into(),
vuids: &["VUID-VkSamplerCreateInfo-addressModeU-01646"],
..Default::default()
});
}));
}
if anisotropy.is_some() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`sampler_ycbcr_conversion` is `Some`, but \
`anisotropy` is `Some`"
.into(),
vuids: &["VUID-VkSamplerCreateInfo-addressModeU-01646"],
..Default::default()
});
}));
}
if unnormalized_coordinates {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`sampler_ycbcr_conversion` is `Some`, but \
`unnormalized_coordinates` is `true`"
.into(),
vuids: &["VUID-VkSamplerCreateInfo-addressModeU-01646"],
..Default::default()
});
}));
}
if reduction_mode != SamplerReductionMode::WeightedAverage {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`sampler_ycbcr_conversion` is `Some`, but \
`reduction_mode` is not `SamplerReductionMode::WeightedAverage`"
.into(),
vuids: &["VUID-VkSamplerCreateInfo-None-01647"],
..Default::default()
});
}));
}
}
@ -1248,7 +1250,7 @@ impl ComponentMapping {
]
}
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self { r, g, b, a } = self;
r.validate_device(device).map_err(|err| ValidationError {
@ -1493,7 +1495,7 @@ mod tests {
Filter, Sampler, SamplerAddressMode, SamplerCreateInfo, SamplerReductionMode,
},
pipeline::graphics::depth_stencil::CompareOp,
Requires, RequiresAllOf, RequiresOneOf, ValidationError, VulkanError,
Requires, RequiresAllOf, RequiresOneOf, Validated, ValidationError,
};
#[test]
@ -1628,7 +1630,7 @@ mod tests {
);
match r {
Err(VulkanError::ValidationError(_)) => (),
Err(Validated::ValidationError(_)) => (),
_ => panic!(),
}
}
@ -1651,7 +1653,7 @@ mod tests {
);
match r {
Err(VulkanError::ValidationError(_)) => (),
Err(Validated::ValidationError(_)) => (),
_ => panic!(),
}
}
@ -1673,7 +1675,7 @@ mod tests {
);
match r {
Err(VulkanError::ValidationError(_)) => (),
Err(Validated::ValidationError(_)) => (),
_ => panic!(),
}
}
@ -1695,15 +1697,19 @@ mod tests {
);
match r {
Err(VulkanError::ValidationError(ValidationError {
requires_one_of:
RequiresOneOf(
[RequiresAllOf([Requires::Feature("sampler_mirror_clamp_to_edge")]), RequiresAllOf(
[Requires::DeviceExtension("khr_sampler_mirror_clamp_to_edge")],
)],
),
..
})) => {}
Err(Validated::ValidationError(err))
if matches!(
*err,
ValidationError {
requires_one_of: RequiresOneOf([
RequiresAllOf([Requires::Feature("sampler_mirror_clamp_to_edge")]),
RequiresAllOf([Requires::DeviceExtension(
"khr_sampler_mirror_clamp_to_edge"
)],)
],),
..
}
) => {}
_ => panic!(),
}
}
@ -1723,13 +1729,17 @@ mod tests {
);
match r {
Err(VulkanError::ValidationError(ValidationError {
requires_one_of:
RequiresOneOf(
[RequiresAllOf([Requires::Feature("sampler_filter_minmax")]), RequiresAllOf([Requires::DeviceExtension("ext_sampler_filter_minmax")])],
),
..
})) => {}
Err(Validated::ValidationError(err))
if matches!(
*err,
ValidationError {
requires_one_of: RequiresOneOf([
RequiresAllOf([Requires::Feature("sampler_filter_minmax")]),
RequiresAllOf([Requires::DeviceExtension("ext_sampler_filter_minmax")])
],),
..
}
) => {}
_ => panic!(),
}
}

View File

@ -115,7 +115,7 @@ use crate::{
image::sampler::{ComponentMapping, ComponentSwizzle, Filter},
instance::InstanceOwnedDebugWrapper,
macros::{impl_id_counter, vulkan_enum},
Requires, RequiresAllOf, RequiresOneOf, RuntimeError, ValidationError, Version, VulkanError,
Requires, RequiresAllOf, RequiresOneOf, Validated, ValidationError, Version, VulkanError,
VulkanObject,
};
use std::{mem::MaybeUninit, num::NonZeroU64, ptr, sync::Arc};
@ -145,7 +145,7 @@ impl SamplerYcbcrConversion {
pub fn new(
device: Arc<Device>,
create_info: SamplerYcbcrConversionCreateInfo,
) -> Result<Arc<SamplerYcbcrConversion>, VulkanError> {
) -> Result<Arc<SamplerYcbcrConversion>, Validated<VulkanError>> {
Self::validate_new(&device, &create_info)?;
unsafe { Ok(Self::new_unchecked(device, create_info)?) }
@ -154,15 +154,15 @@ impl SamplerYcbcrConversion {
fn validate_new(
device: &Device,
create_info: &SamplerYcbcrConversionCreateInfo,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
if !device.enabled_features().sampler_ycbcr_conversion {
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"sampler_ycbcr_conversion",
)])]),
vuids: &["VUID-vkCreateSamplerYcbcrConversion-None-01648"],
..Default::default()
});
}));
}
create_info
@ -176,7 +176,7 @@ impl SamplerYcbcrConversion {
pub unsafe fn new_unchecked(
device: Arc<Device>,
create_info: SamplerYcbcrConversionCreateInfo,
) -> Result<Arc<SamplerYcbcrConversion>, RuntimeError> {
) -> Result<Arc<SamplerYcbcrConversion>, VulkanError> {
let &SamplerYcbcrConversionCreateInfo {
format,
ycbcr_model,
@ -217,7 +217,7 @@ impl SamplerYcbcrConversion {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -456,7 +456,7 @@ impl Default for SamplerYcbcrConversionCreateInfo {
}
impl SamplerYcbcrConversionCreateInfo {
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
format,
ycbcr_model,
@ -527,12 +527,12 @@ impl SamplerYcbcrConversionCreateInfo {
.type_color()
.map_or(false, |ty| ty == NumericType::UNORM)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "format".into(),
problem: "the numeric type is not `UNORM`".into(),
vuids: &["VUID-VkSamplerYcbcrConversionCreateInfo-format-04061"],
..Default::default()
});
}));
}
// Use unchecked, because all validation has been done above.
@ -546,7 +546,7 @@ impl SamplerYcbcrConversionCreateInfo {
if !potential_format_features.intersects(
FormatFeatures::MIDPOINT_CHROMA_SAMPLES | FormatFeatures::COSITED_CHROMA_SAMPLES,
) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "format".into(),
problem: "the potential format features do not contain \
`FormatFeatures::MIDPOINT_CHROMA_SAMPLES` or \
@ -554,7 +554,7 @@ impl SamplerYcbcrConversionCreateInfo {
.into(),
vuids: &["VUID-VkSamplerYcbcrConversionCreateInfo-format-01650"],
..Default::default()
});
}));
}
if let Some(chroma_sampling @ (ChromaSampling::Mode422 | ChromaSampling::Mode420)) =
@ -566,7 +566,7 @@ impl SamplerYcbcrConversionCreateInfo {
&& !potential_format_features
.intersects(FormatFeatures::COSITED_CHROMA_SAMPLES)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`format` has both horizontal and vertical chroma \
subsampling, and \
its potential format features do not \
@ -576,14 +576,14 @@ impl SamplerYcbcrConversionCreateInfo {
.into(),
vuids: &["VUID-VkSamplerYcbcrConversionCreateInfo-xChromaOffset-01651"],
..Default::default()
});
}));
}
if chroma_offset.contains(&ChromaLocation::Midpoint)
&& !potential_format_features
.intersects(FormatFeatures::MIDPOINT_CHROMA_SAMPLES)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`format` has both horizontal and vertical chroma \
subsampling, and \
its potential format features do not \
@ -593,7 +593,7 @@ impl SamplerYcbcrConversionCreateInfo {
.into(),
vuids: &["VUID-VkSamplerYcbcrConversionCreateInfo-xChromaOffset-01652"],
..Default::default()
});
}));
}
}
ChromaSampling::Mode422 => {
@ -601,7 +601,7 @@ impl SamplerYcbcrConversionCreateInfo {
&& !potential_format_features
.intersects(FormatFeatures::COSITED_CHROMA_SAMPLES)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`format` has horizontal chroma subsampling, and \
its potential format features do not \
contain `FormatFeatures::COSITED_CHROMA_SAMPLES`, but \
@ -610,14 +610,14 @@ impl SamplerYcbcrConversionCreateInfo {
.into(),
vuids: &["VUID-VkSamplerYcbcrConversionCreateInfo-xChromaOffset-01651"],
..Default::default()
});
}));
}
if chroma_offset[0] == ChromaLocation::Midpoint
&& !potential_format_features
.intersects(FormatFeatures::MIDPOINT_CHROMA_SAMPLES)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`format` has horizontal chroma subsampling, and \
its potential format features do not \
contain `FormatFeatures::MIDPOINT_CHROMA_SAMPLES`, but \
@ -626,20 +626,20 @@ impl SamplerYcbcrConversionCreateInfo {
.into(),
vuids: &["VUID-VkSamplerYcbcrConversionCreateInfo-xChromaOffset-01652"],
..Default::default()
});
}));
}
}
_ => unreachable!(),
}
if !component_mapping.g_is_identity() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`format` has chroma subsampling, but \
`component_mapping.g` is not identity swizzled"
.into(),
vuids: &["VUID-VkSamplerYcbcrConversionCreateInfo-components-02581"],
..Default::default()
});
}));
}
if !(component_mapping.a_is_identity()
@ -648,7 +648,7 @@ impl SamplerYcbcrConversionCreateInfo {
ComponentSwizzle::One | ComponentSwizzle::Zero
))
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "component_mapping.a".into(),
problem: "`format` has chroma subsampling, but \
`component_mapping.a` is not identity swizzled, or \
@ -656,33 +656,33 @@ impl SamplerYcbcrConversionCreateInfo {
.into(),
vuids: &["VUID-VkSamplerYcbcrConversionCreateInfo-components-02582"],
..Default::default()
});
}));
}
if !(component_mapping.r_is_identity()
|| matches!(component_mapping.r, ComponentSwizzle::Blue))
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`format` has chroma subsampling, but \
`component_mapping.r` is not identity swizzled, or \
`ComponentSwizzle::Blue`"
.into(),
vuids: &["VUID-VkSamplerYcbcrConversionCreateInfo-components-02583"],
..Default::default()
});
}));
}
if !(component_mapping.b_is_identity()
|| matches!(component_mapping.b, ComponentSwizzle::Red))
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`format` has chroma subsampling, but \
`component_mapping.b` is not identity swizzled, or \
`ComponentSwizzle::Red`"
.into(),
vuids: &["VUID-VkSamplerYcbcrConversionCreateInfo-components-02584"],
..Default::default()
});
}));
}
match (
@ -690,24 +690,24 @@ impl SamplerYcbcrConversionCreateInfo {
component_mapping.b_is_identity(),
) {
(true, false) => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`format` has chroma subsampling, and \
`component_mapping.r` is identity swizzled, but \
`component_mapping.b` is not identity swizzled"
.into(),
vuids: &["VUID-VkSamplerYcbcrConversionCreateInfo-components-02585"],
..Default::default()
});
}));
}
(false, true) => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`format` has chroma subsampling, and \
`component_mapping.b` is identity swizzled, but \
`component_mapping.r` is not identity swizzled"
.into(),
vuids: &["VUID-VkSamplerYcbcrConversionCreateInfo-components-02585"],
..Default::default()
});
}));
}
_ => (),
}
@ -723,47 +723,47 @@ impl SamplerYcbcrConversionCreateInfo {
// VUID-VkSamplerYcbcrConversionCreateInfo-ycbcrModel-01655
if ycbcr_model != SamplerYcbcrModelConversion::RgbIdentity {
if components_bits[0].map_or(true, |bits| bits == 0) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`ycbcr_model` is not `SamplerYcbcrModelConversion::RgbIdentity`, \
and `component_mapping.r` does not map to a component that exists in \
`format`"
.into(),
vuids: &["VUID-VkSamplerYcbcrConversionCreateInfo-components-02585"],
..Default::default()
});
}));
}
if components_bits[1].map_or(true, |bits| bits == 0) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`ycbcr_model` is not `SamplerYcbcrModelConversion::RgbIdentity`, \
and `component_mapping.g` does not map to a component that exists in \
`format`"
.into(),
vuids: &["VUID-VkSamplerYcbcrConversionCreateInfo-components-02585"],
..Default::default()
});
}));
}
if components_bits[2].map_or(true, |bits| bits == 0) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`ycbcr_model` is not `SamplerYcbcrModelConversion::RgbIdentity`, \
and `component_mapping.b` does not map to a component that exists in \
`format`"
.into(),
vuids: &["VUID-VkSamplerYcbcrConversionCreateInfo-components-02585"],
..Default::default()
});
}));
}
if components_bits[3].map_or(true, |bits| bits == 0) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`ycbcr_model` is not `SamplerYcbcrModelConversion::RgbIdentity`, \
and `component_mapping.a` does not map to a component that exists in \
`format`"
.into(),
vuids: &["VUID-VkSamplerYcbcrConversionCreateInfo-components-02585"],
..Default::default()
});
}));
}
}
@ -772,47 +772,47 @@ impl SamplerYcbcrConversionCreateInfo {
// just skip them for now.
if components_bits[0].map_or(false, |bits| bits < 8) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`ycbcr_range` is `SamplerYcbcrRange::ItuNarrow`, and \
`component_mapping.r` maps to a component in `format` with less than \
8 bits"
.into(),
vuids: &["VUID-VkSamplerYcbcrConversionCreateInfo-ycbcrRange-02748"],
..Default::default()
});
}));
}
if components_bits[1].map_or(false, |bits| bits < 8) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`ycbcr_range` is `SamplerYcbcrRange::ItuNarrow`, and \
`component_mapping.g` maps to a component in `format` with less than \
8 bits"
.into(),
vuids: &["VUID-VkSamplerYcbcrConversionCreateInfo-ycbcrRange-02748"],
..Default::default()
});
}));
}
if components_bits[2].map_or(false, |bits| bits < 8) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`ycbcr_range` is `SamplerYcbcrRange::ItuNarrow`, and \
`component_mapping.b` maps to a component in `format` with less than \
8 bits"
.into(),
vuids: &["VUID-VkSamplerYcbcrConversionCreateInfo-ycbcrRange-02748"],
..Default::default()
});
}));
}
if components_bits[3].map_or(false, |bits| bits < 8) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`ycbcr_range` is `SamplerYcbcrRange::ItuNarrow`, and \
`component_mapping.a` maps to a component in `format` with less than \
8 bits"
.into(),
vuids: &["VUID-VkSamplerYcbcrConversionCreateInfo-ycbcrRange-02748"],
..Default::default()
});
}));
}
}
@ -820,14 +820,14 @@ impl SamplerYcbcrConversionCreateInfo {
&& !potential_format_features.intersects(FormatFeatures::
SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`force_explicit_reconstruction` is `true`, but the \
potential format features of `format` do not include `FormatFeatures::\
SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE`"
.into(),
vuids: &["VUID-VkSamplerYcbcrConversionCreateInfo-forceExplicitReconstruction-01656"],
..Default::default()
});
}));
}
match chroma_filter {
@ -836,23 +836,23 @@ impl SamplerYcbcrConversionCreateInfo {
if !potential_format_features
.intersects(FormatFeatures::SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`chroma_filter` is `Filter::Linear`, but the \
potential format features of `format` do not include `FormatFeatures::\
SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER`"
.into(),
vuids: &["VUID-VkSamplerYcbcrConversionCreateInfo-chromaFilter-01657"],
..Default::default()
});
}));
}
}
Filter::Cubic => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "chroma_filter".into(),
problem: "is `Filter::Cubic`".into(),
// vuids?
..Default::default()
});
}));
}
}
@ -918,7 +918,7 @@ vulkan_enum! {
#[cfg(test)]
mod tests {
use super::SamplerYcbcrConversion;
use crate::{Requires, RequiresAllOf, RequiresOneOf, ValidationError, VulkanError};
use crate::{Requires, RequiresAllOf, RequiresOneOf, Validated, ValidationError};
#[test]
fn feature_not_enabled() {
@ -927,11 +927,16 @@ mod tests {
let r = SamplerYcbcrConversion::new(device, Default::default());
match r {
Err(VulkanError::ValidationError(ValidationError {
requires_one_of:
RequiresOneOf([RequiresAllOf([Requires::Feature("sampler_ycbcr_conversion")])]),
..
})) => (),
Err(Validated::ValidationError(err))
if matches!(
*err,
ValidationError {
requires_one_of: RequiresOneOf([RequiresAllOf([Requires::Feature(
"sampler_ycbcr_conversion"
)])]),
..
}
) => {}
_ => panic!(),
}
}

File diff suppressed because it is too large Load Diff

View File

@ -26,7 +26,7 @@ use crate::{
ImageAspects, ImageCreateFlags, ImageTiling, ImageType, SampleCount,
},
macros::{impl_id_counter, vulkan_enum},
Requires, RequiresAllOf, RequiresOneOf, RuntimeError, ValidationError, Version, VulkanError,
Requires, RequiresAllOf, RequiresOneOf, Validated, ValidationError, Version, VulkanError,
VulkanObject,
};
use smallvec::{smallvec, SmallVec};
@ -61,7 +61,7 @@ impl ImageView {
pub fn new(
image: Arc<Image>,
create_info: ImageViewCreateInfo,
) -> Result<Arc<ImageView>, VulkanError> {
) -> Result<Arc<ImageView>, Validated<VulkanError>> {
Self::validate_new(&image, &create_info)?;
unsafe { Ok(Self::new_unchecked(image, create_info)?) }
@ -70,7 +70,7 @@ impl ImageView {
fn validate_new(
image: &Image,
create_info: &ImageViewCreateInfo,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
let device = image.device();
create_info
@ -91,47 +91,47 @@ impl ImageView {
let format_features = unsafe { get_format_features(format, image) };
if format_features.is_empty() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "create_info.format".into(),
problem: "the format features are empty".into(),
vuids: &["VUID-VkImageViewCreateInfo-None-02273"],
..Default::default()
});
}));
}
let image_type = image.image_type();
if !view_type.is_compatible_with(image_type) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`create_info.view_type` is not compatible with \
`image.image_type()`"
.into(),
vuids: &["VUID-VkImageViewCreateInfo-subResourceRange-01021"],
..Default::default()
});
}));
}
if subresource_range.mip_levels.end > image.mip_levels() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`create_info.subresource_range.mip_levels.end` is greater than \
`image.mip_levels()`"
.into(),
vuids: &["VUID-VkImageViewCreateInfo-subresourceRange-01718"],
..Default::default()
});
}));
}
if matches!(view_type, ImageViewType::Cube | ImageViewType::CubeArray)
&& !image.flags().intersects(ImageCreateFlags::CUBE_COMPATIBLE)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`create_info.view_type` is `ImageViewType::Cube` or \
`ImageViewType::CubeArray`, but \
`image.flags()` does not contain `ImageCreateFlags::CUBE_COMPATIBLE`"
.into(),
vuids: &["VUID-VkImageViewCreateInfo-image-01003"],
..Default::default()
});
}));
}
if matches!(view_type, ImageViewType::Dim2d | ImageViewType::Dim2dArray)
@ -143,7 +143,7 @@ impl ImageView {
.flags()
.intersects(ImageCreateFlags::DIM2D_ARRAY_COMPATIBLE)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`create_info.view_type` is `ImageViewType::Dim2d`, and \
`image.image_type()` is `ImageType::Dim3d`, but \
`image.flags()` does not contain \
@ -152,7 +152,7 @@ impl ImageView {
.into(),
vuids: &["VUID-VkImageViewCreateInfo-image-06728"],
..Default::default()
});
}));
}
}
ImageViewType::Dim2dArray => {
@ -160,7 +160,7 @@ impl ImageView {
.flags()
.intersects(ImageCreateFlags::DIM2D_ARRAY_COMPATIBLE)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`create_info.view_type` is `ImageViewType::Dim2dArray`, and \
`image.image_type()` is `ImageType::Dim3d`, but \
`image.flags()` does not contain \
@ -168,14 +168,14 @@ impl ImageView {
.into(),
vuids: &["VUID-VkImageViewCreateInfo-image-06723"],
..Default::default()
});
}));
}
}
_ => unreachable!(),
}
if subresource_range.mip_levels.len() != 1 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`create_info.view_type` is `ImageViewType::Dim2d` or \
`ImageViewType::Dim2dArray`, and \
`image.image_type()` is `ImageType::Dim3d`, but \
@ -183,7 +183,7 @@ impl ImageView {
.into(),
vuids: &["VUID-VkImageViewCreateInfo-image-04970"],
..Default::default()
});
}));
}
// We're using the depth dimension as array layers, but because of mip scaling, the
@ -193,7 +193,7 @@ impl ImageView {
mip_level_extent(image.extent(), subresource_range.mip_levels.start).unwrap();
if subresource_range.array_layers.end > mip_level_extent[2] {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`create_info.view_type` is `ImageViewType::Dim2d` or \
`ImageViewType::Dim2dArray`, and \
`image.image_type()` is `ImageType::Dim3d`, but \
@ -206,11 +206,11 @@ impl ImageView {
"VUID-VkImageViewCreateInfo-subresourceRange-02725",
],
..Default::default()
});
}));
}
} else {
if subresource_range.array_layers.end > image.array_layers() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`create_info.subresource_range.array_layers.end` is greater than \
`image.array_layers()`"
.into(),
@ -219,21 +219,21 @@ impl ImageView {
"VUID-VkImageViewCreateInfo-subresourceRange-06725",
],
..Default::default()
});
}));
}
}
if image.samples() != SampleCount::Sample1
&& !matches!(view_type, ImageViewType::Dim2d | ImageViewType::Dim2dArray)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`image.samples()` is not `SampleCount::Sample1`, but \
`create_info.view_type` is not `ImageViewType::Dim2d` or \
`ImageViewType::Dim2dArray`"
.into(),
vuids: &["VUID-VkImageViewCreateInfo-image-04972"],
..Default::default()
});
}));
}
/* Check usage requirements */
@ -251,7 +251,7 @@ impl ImageView {
if !(device.api_version() >= Version::V1_1
|| device.enabled_extensions().khr_maintenance2)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`create_info.usage` is not the implicit default usage \
(calculated from `image` and `create_info.subresource_range.aspects`)"
.into(),
@ -260,7 +260,7 @@ impl ImageView {
RequiresAllOf(&[Requires::DeviceExtension("khr_maintenance2")]),
]),
..Default::default()
});
}));
}
// VUID-VkImageViewUsageCreateInfo-usage-requiredbitmask
@ -268,7 +268,7 @@ impl ImageView {
// (which is already validated to not be empty).
if !implicit_default_usage.contains(usage) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`create_info.usage` is not a subset of the implicit default usage \
(calculated from `image` and `create_info.subresource_range.aspects`)"
.into(),
@ -278,7 +278,7 @@ impl ImageView {
"VUID-VkImageViewCreateInfo-pNext-02664",
],
..Default::default()
});
}));
}
}
@ -290,7 +290,7 @@ impl ImageView {
| ImageUsage::INPUT_ATTACHMENT
| ImageUsage::TRANSIENT_ATTACHMENT,
) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "image.usage()".into(),
problem: "does not contain one of `ImageUsage::SAMPLED`, `ImageUsage::STORAGE`, \
`ImageUsage::COLOR_ATTACHMENT`, `ImageUsage::DEPTH_STENCIL_ATTACHMENT`, \
@ -298,13 +298,13 @@ impl ImageView {
.into(),
vuids: &["VUID-VkImageViewCreateInfo-image-04441"],
..Default::default()
});
}));
}
if usage.intersects(ImageUsage::SAMPLED)
&& !format_features.intersects(FormatFeatures::SAMPLED_IMAGE)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`create_info.usage` or the implicit default usage \
(calculated from `image` and `create_info.subresource_range.aspects`) \
contains `ImageUsage::SAMPLED`, but \
@ -313,13 +313,13 @@ impl ImageView {
.into(),
vuids: &["VUID-VkImageViewCreateInfo-usage-02274"],
..Default::default()
});
}));
}
if usage.intersects(ImageUsage::STORAGE)
&& !format_features.intersects(FormatFeatures::STORAGE_IMAGE)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`create_info.usage` or the implicit default usage \
(calculated from `image` and `create_info.subresource_range.aspects`) \
contains `ImageUsage::STORAGE`, but \
@ -328,13 +328,13 @@ impl ImageView {
.into(),
vuids: &["VUID-VkImageViewCreateInfo-usage-02275"],
..Default::default()
});
}));
}
if usage.intersects(ImageUsage::COLOR_ATTACHMENT)
&& !format_features.intersects(FormatFeatures::COLOR_ATTACHMENT)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`create_info.usage` or the implicit default usage \
(calculated from `image` and `create_info.subresource_range.aspects`) \
contains `ImageUsage::COLOR_ATTACHMENT`, but \
@ -343,13 +343,13 @@ impl ImageView {
.into(),
vuids: &["VUID-VkImageViewCreateInfo-usage-02276"],
..Default::default()
});
}));
}
if usage.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
&& !format_features.intersects(FormatFeatures::DEPTH_STENCIL_ATTACHMENT)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`create_info.usage` or the implicit default usage \
(calculated from `image` and `create_info.subresource_range.aspects`) \
contains `ImageUsage::DEPTH_STENCIL_ATTACHMENT`, but \
@ -358,7 +358,7 @@ impl ImageView {
.into(),
vuids: &["VUID-VkImageViewCreateInfo-usage-02277"],
..Default::default()
});
}));
}
if usage.intersects(ImageUsage::INPUT_ATTACHMENT)
@ -366,7 +366,7 @@ impl ImageView {
FormatFeatures::COLOR_ATTACHMENT | FormatFeatures::DEPTH_STENCIL_ATTACHMENT,
)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`create_info.usage` or the implicit default usage \
(calculated from `image` and `create_info.subresource_range.aspects`) \
contains `ImageUsage::INPUT_ATTACHMENT`, but \
@ -376,7 +376,7 @@ impl ImageView {
.into(),
vuids: &["VUID-VkImageViewCreateInfo-usage-02652"],
..Default::default()
});
}));
}
/* Check flags requirements */
@ -385,24 +385,24 @@ impl ImageView {
if !image.format().unwrap().planes().is_empty()
&& subresource_range.aspects.intersects(ImageAspects::COLOR)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`image.format()` is a multi-planar format, and \
`create_info.subresource_range.aspects` contains `ImageAspects::COLOR`, \
but `create_info.format` does not equal `image.format()`"
.into(),
vuids: &["VUID-VkImageViewCreateInfo-image-01762"],
..Default::default()
});
}));
}
if !image.flags().intersects(ImageCreateFlags::MUTABLE_FORMAT) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`create_info.format` does not equal `image.format()`, but \
`image.flags()` does not contain `ImageCreateFlags::MUTABLE_FORMAT`"
.into(),
vuids: &["VUID-VkImageViewCreateInfo-image-01762"],
..Default::default()
});
}));
}
// TODO: it is unclear what the number of bits is for compressed formats.
@ -411,7 +411,7 @@ impl ImageView {
&& !device.enabled_features().image_view_format_reinterpretation
&& format.components() != image.format().unwrap().components()
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "this device is a portability subset device, and \
`create_info.format` does not have the same components and \
number of bits per component as `image.format()`"
@ -421,7 +421,7 @@ impl ImageView {
)])]),
vuids: &["VUID-VkImageViewCreateInfo-imageViewFormatReinterpretation-04466"],
..Default::default()
});
}));
}
if image
@ -431,7 +431,7 @@ impl ImageView {
if !(format.compatibility() == image.format().unwrap().compatibility()
|| format.block_size() == image.format().unwrap().block_size())
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`image.flags()` contains \
`ImageCreateFlags::BLOCK_TEXEL_VIEW_COMPATIBLE`, but \
`create_info.format` is not compatible with `image.format()`, or \
@ -439,12 +439,12 @@ impl ImageView {
.into(),
vuids: &["VUID-VkImageViewCreateInfo-image-01583"],
..Default::default()
});
}));
}
if format.compression().is_none() {
if subresource_range.array_layers.len() != 1 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`image.flags()` contains \
`ImageCreateFlags::BLOCK_TEXEL_VIEW_COMPATIBLE`, and \
`create_info.format` is not a compressed format, but \
@ -453,11 +453,11 @@ impl ImageView {
.into(),
vuids: &["VUID-VkImageViewCreateInfo-image-07072"],
..Default::default()
});
}));
}
if subresource_range.mip_levels.len() != 1 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`image.flags()` contains \
`ImageCreateFlags::BLOCK_TEXEL_VIEW_COMPATIBLE`, and \
`create_info.format` is not a compressed format, but \
@ -466,13 +466,13 @@ impl ImageView {
.into(),
vuids: &["VUID-VkImageViewCreateInfo-image-07072"],
..Default::default()
});
}));
}
}
} else {
if image.format().unwrap().planes().is_empty() {
if format.compatibility() != image.format().unwrap().compatibility() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`image.flags()` does not contain \
`ImageCreateFlags::BLOCK_TEXEL_VIEW_COMPATIBLE`, and \
`image.format()` is not a multi-planar format, but \
@ -480,7 +480,7 @@ impl ImageView {
.into(),
vuids: &["VUID-VkImageViewCreateInfo-image-01761"],
..Default::default()
});
}));
}
} else if subresource_range.aspects.intersects(
ImageAspects::PLANE_0 | ImageAspects::PLANE_1 | ImageAspects::PLANE_2,
@ -497,7 +497,7 @@ impl ImageView {
let plane_format = image.format().unwrap().planes()[plane];
if format.compatibility() != plane_format.compatibility() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`image.flags()` does not contain \
`ImageCreateFlags::BLOCK_TEXEL_VIEW_COMPATIBLE`, and \
`image.format()` is a multi-planar format, but \
@ -506,7 +506,7 @@ impl ImageView {
.into(),
vuids: &["VUID-VkImageViewCreateInfo-image-01586"],
..Default::default()
});
}));
}
}
}
@ -517,7 +517,7 @@ impl ImageView {
ChromaSampling::Mode444 => (),
ChromaSampling::Mode422 => {
if image.extent()[0] % 2 != 0 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`create_info.format` is a YCbCr format with horizontal \
chroma subsampling, but \
`image.extent()[0]` is not \
@ -525,12 +525,12 @@ impl ImageView {
.into(),
vuids: &["VUID-VkImageViewCreateInfo-format-04714"],
..Default::default()
});
}));
}
}
ChromaSampling::Mode420 => {
if !(image.extent()[0] % 2 == 0 && image.extent()[1] % 2 == 0) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`create_info.format` is a YCbCr format with horizontal \
and vertical chroma subsampling, but \
`image.extent()[0]` and `image.extent()[1]` \
@ -541,7 +541,7 @@ impl ImageView {
"VUID-VkImageViewCreateInfo-format-04715",
],
..Default::default()
});
}));
}
}
}
@ -554,7 +554,7 @@ impl ImageView {
pub unsafe fn new_unchecked(
image: Arc<Image>,
create_info: ImageViewCreateInfo,
) -> Result<Arc<Self>, RuntimeError> {
) -> Result<Arc<Self>, VulkanError> {
let &ImageViewCreateInfo {
view_type,
format,
@ -618,7 +618,7 @@ impl ImageView {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -627,7 +627,7 @@ impl ImageView {
/// Creates a default `ImageView`. Equivalent to
/// `ImageView::new(image, ImageViewCreateInfo::from_image(image))`.
pub fn new_default(image: Arc<Image>) -> Result<Arc<ImageView>, VulkanError> {
pub fn new_default(image: Arc<Image>) -> Result<Arc<ImageView>, Validated<VulkanError>> {
let create_info = ImageViewCreateInfo::from_image(&image);
Self::new(image, create_info)
@ -643,7 +643,7 @@ impl ImageView {
image: Arc<Image>,
handle: ash::vk::ImageView,
create_info: ImageViewCreateInfo,
) -> Result<Arc<Self>, RuntimeError> {
) -> Result<Arc<Self>, VulkanError> {
let ImageViewCreateInfo {
view_type,
format,
@ -921,7 +921,7 @@ impl ImageViewCreateInfo {
}
}
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
view_type,
format,
@ -973,48 +973,48 @@ impl ImageViewCreateInfo {
match view_type {
ImageViewType::Dim1d | ImageViewType::Dim2d | ImageViewType::Dim3d => {
if subresource_range.array_layers.len() != 1 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`view_type` is `ImageViewType::Dim1d`, \
`ImageViewType::Dim2d` or `ImageViewType::Dim3d`, but \
the length of `subresource_range.array_layers` is not 1"
.into(),
vuids: &["VUID-VkImageViewCreateInfo-imageViewType-04973"],
..Default::default()
});
}));
}
}
ImageViewType::Cube => {
if subresource_range.array_layers.len() != 6 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`view_type` is `ImageViewType::Cube`, but \
the length of `subresource_range.array_layers` is not 6"
.into(),
vuids: &["VUID-VkImageViewCreateInfo-viewType-02960"],
..Default::default()
});
}));
}
}
ImageViewType::CubeArray => {
if !device.enabled_features().image_cube_array {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "view_type".into(),
problem: "is `ImageViewType::CubeArray`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"image_cube_array",
)])]),
vuids: &["VUID-VkImageViewCreateInfo-viewType-01004"],
});
}));
}
if subresource_range.array_layers.len() % 6 != 0 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`view_type` is `ImageViewType::CubeArray`, but \
the length of `subresource_range.array_layers` is not \
a multiple of 6"
.into(),
vuids: &["VUID-VkImageViewCreateInfo-viewType-02961"],
..Default::default()
});
}));
}
}
_ => (),
@ -1026,21 +1026,21 @@ impl ImageViewCreateInfo {
.count()
> 1
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "subresource_range.aspects".into(),
problem: "contains more than one of `ImageAspects::PLANE_0`, \
`ImageAspects::PLANE_1` and `ImageAspects::PLANE_2`"
.into(),
vuids: &["VUID-VkImageViewCreateInfo-subresourceRange-07818"],
..Default::default()
});
}));
}
if device.enabled_extensions().khr_portability_subset
&& !device.enabled_features().image_view_format_swizzle
&& !component_mapping.is_identity()
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "this device is a portability subset device, and \
`component_mapping` is not the identity mapping"
.into(),
@ -1049,7 +1049,7 @@ impl ImageViewCreateInfo {
)])]),
vuids: &["VUID-VkImageViewCreateInfo-imageViewFormatSwizzle-04465"],
..Default::default()
});
}));
}
// Don't need to check features because you can't create a conversion object without the
@ -1058,23 +1058,23 @@ impl ImageViewCreateInfo {
assert_eq!(device, conversion.device().as_ref());
if !component_mapping.is_identity() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`sampler_ycbcr_conversion` is `Some`, but \
`component_mapping` is not the identity mapping"
.into(),
vuids: &["VUID-VkImageViewCreateInfo-pNext-01970"],
..Default::default()
});
}));
}
} else {
if format.ycbcr_chroma_sampling().is_some() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`sampler_ycbcr_conversion` is `None`, but \
`format.ycbcr_chroma_sampling()` is `Some`"
.into(),
vuids: &["VUID-VkImageViewCreateInfo-format-06415"],
..Default::default()
});
}));
}
}

View File

@ -44,7 +44,7 @@
use super::{Instance, InstanceExtensions};
use crate::{
macros::{vulkan_bitflags, vulkan_enum},
DebugWrapper, Requires, RequiresAllOf, RequiresOneOf, RuntimeError, ValidationError, Version,
DebugWrapper, Requires, RequiresAllOf, RequiresOneOf, Validated, ValidationError, Version,
VulkanError, VulkanObject,
};
use std::{
@ -81,7 +81,7 @@ impl DebugUtilsMessenger {
pub unsafe fn new(
instance: Arc<Instance>,
create_info: DebugUtilsMessengerCreateInfo,
) -> Result<Self, VulkanError> {
) -> Result<Self, Validated<VulkanError>> {
Self::validate_new(&instance, &create_info)?;
Ok(Self::new_unchecked(instance, create_info)?)
@ -90,14 +90,14 @@ impl DebugUtilsMessenger {
fn validate_new(
instance: &Instance,
create_info: &DebugUtilsMessengerCreateInfo,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
if !instance.enabled_extensions().ext_debug_utils {
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"ext_debug_utils",
)])]),
..Default::default()
});
}));
}
create_info
@ -111,7 +111,7 @@ impl DebugUtilsMessenger {
pub unsafe fn new_unchecked(
instance: Arc<Instance>,
create_info: DebugUtilsMessengerCreateInfo,
) -> Result<Self, RuntimeError> {
) -> Result<Self, VulkanError> {
let DebugUtilsMessengerCreateInfo {
message_severity,
message_type,
@ -142,7 +142,7 @@ impl DebugUtilsMessenger {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -263,7 +263,7 @@ impl DebugUtilsMessengerCreateInfo {
}
#[inline]
pub(crate) fn validate(&self, instance: &Instance) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, instance: &Instance) -> Result<(), Box<ValidationError>> {
self.validate_raw(instance.api_version(), instance.enabled_extensions())
}
@ -271,7 +271,7 @@ impl DebugUtilsMessengerCreateInfo {
&self,
instance_api_version: Version,
instance_extensions: &InstanceExtensions,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
let &DebugUtilsMessengerCreateInfo {
message_severity,
message_type,
@ -288,12 +288,12 @@ impl DebugUtilsMessengerCreateInfo {
})?;
if message_severity.is_empty() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "message_severity".into(),
problem: "is empty".into(),
vuids: &["VUID-VkDebugUtilsMessengerCreateInfoEXT-messageSeverity-requiredbitmask"],
..Default::default()
});
}));
}
message_type
@ -305,12 +305,12 @@ impl DebugUtilsMessengerCreateInfo {
})?;
if message_type.is_empty() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "message_type".into(),
problem: "is empty".into(),
vuids: &["VUID-VkDebugUtilsMessengerCreateInfoEXT-messageType-requiredbitmask"],
..Default::default()
});
}));
}
// VUID-PFN_vkDebugUtilsMessengerCallbackEXT-None-04769

View File

@ -90,8 +90,8 @@ use crate::{
},
instance::debug::trampoline,
macros::{impl_id_counter, vulkan_bitflags},
Requires, RequiresAllOf, RequiresOneOf, RuntimeError, ValidationError, VulkanError,
VulkanLibrary, VulkanObject,
Requires, RequiresAllOf, RequiresOneOf, Validated, ValidationError, VulkanError, VulkanLibrary,
VulkanObject,
};
pub use crate::{fns::InstanceFunctions, version::Version};
use ash::vk::Handle;
@ -291,7 +291,7 @@ impl Instance {
pub fn new(
library: Arc<VulkanLibrary>,
create_info: InstanceCreateInfo,
) -> Result<Arc<Instance>, VulkanError> {
) -> Result<Arc<Instance>, Validated<VulkanError>> {
unsafe { Self::with_debug_utils_messengers(library, create_info, []) }
}
@ -313,7 +313,7 @@ impl Instance {
library: Arc<VulkanLibrary>,
mut create_info: InstanceCreateInfo,
debug_utils_messengers: impl IntoIterator<Item = DebugUtilsMessengerCreateInfo>,
) -> Result<Arc<Instance>, VulkanError> {
) -> Result<Arc<Instance>, Validated<VulkanError>> {
create_info.max_api_version.get_or_insert_with(|| {
let api_version = library.api_version();
if api_version < Version::V1_1 {
@ -337,7 +337,7 @@ impl Instance {
library: &VulkanLibrary,
create_info: &InstanceCreateInfo,
debug_utils_messengers: &[DebugUtilsMessengerCreateInfo],
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
// VUID-vkCreateInstance-pCreateInfo-parameter
create_info
.validate(library)
@ -373,14 +373,14 @@ impl Instance {
if !debug_utils_messengers.is_empty() {
if !create_info.enabled_extensions.ext_debug_utils {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "debug_utils_messengers".into(),
problem: "is not empty".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[
Requires::InstanceExtension("ext_debug_utils"),
])]),
vuids: &["VUID-VkInstanceCreateInfo-pNext-04926"],
});
}));
}
for (index, messenger_create_info) in debug_utils_messengers.iter().enumerate() {
@ -397,7 +397,7 @@ impl Instance {
pub unsafe fn new_unchecked(
library: Arc<VulkanLibrary>,
create_info: InstanceCreateInfo,
) -> Result<Arc<Instance>, RuntimeError> {
) -> Result<Arc<Instance>, VulkanError> {
Self::with_debug_utils_messengers_unchecked(library, create_info, [])
}
@ -406,7 +406,7 @@ impl Instance {
library: Arc<VulkanLibrary>,
mut create_info: InstanceCreateInfo,
debug_utils_messengers: impl IntoIterator<Item = DebugUtilsMessengerCreateInfo>,
) -> Result<Arc<Instance>, RuntimeError> {
) -> Result<Arc<Instance>, VulkanError> {
create_info.max_api_version.get_or_insert_with(|| {
let api_version = library.api_version();
if api_version < Version::V1_1 {
@ -572,7 +572,7 @@ impl Instance {
let fns = library.fns();
(fns.v1_0.create_instance)(&create_info_vk, ptr::null(), output.as_mut_ptr())
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -711,7 +711,7 @@ impl Instance {
/// ```
pub fn enumerate_physical_devices(
self: &Arc<Self>,
) -> Result<impl ExactSizeIterator<Item = Arc<PhysicalDevice>>, RuntimeError> {
) -> Result<impl ExactSizeIterator<Item = Arc<PhysicalDevice>>, VulkanError> {
let fns = self.fns();
unsafe {
@ -719,7 +719,7 @@ impl Instance {
let mut count = 0;
(fns.v1_0.enumerate_physical_devices)(self.handle, &mut count, ptr::null_mut())
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
let mut handles = Vec::with_capacity(count as usize);
let result = (fns.v1_0.enumerate_physical_devices)(
@ -734,7 +734,7 @@ impl Instance {
break handles;
}
ash::vk::Result::INCOMPLETE => (),
err => return Err(RuntimeError::from(err)),
err => return Err(VulkanError::from(err)),
}
};
@ -769,23 +769,24 @@ impl Instance {
#[inline]
pub fn enumerate_physical_device_groups(
self: &Arc<Self>,
) -> Result<impl ExactSizeIterator<Item = PhysicalDeviceGroupProperties>, VulkanError> {
) -> Result<impl ExactSizeIterator<Item = PhysicalDeviceGroupProperties>, Validated<VulkanError>>
{
self.validate_enumerate_physical_device_groups()?;
unsafe { Ok(self.enumerate_physical_device_groups_unchecked()?) }
}
fn validate_enumerate_physical_device_groups(&self) -> Result<(), ValidationError> {
fn validate_enumerate_physical_device_groups(&self) -> Result<(), Box<ValidationError>> {
if !(self.api_version() >= Version::V1_1
|| self.enabled_extensions().khr_device_group_creation)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[
RequiresAllOf(&[Requires::APIVersion(Version::V1_1)]),
RequiresAllOf(&[Requires::InstanceExtension("khr_device_group_creation")]),
]),
..Default::default()
});
}));
}
Ok(())
@ -794,7 +795,7 @@ impl Instance {
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
pub unsafe fn enumerate_physical_device_groups_unchecked(
self: &Arc<Self>,
) -> Result<impl ExactSizeIterator<Item = PhysicalDeviceGroupProperties>, RuntimeError> {
) -> Result<impl ExactSizeIterator<Item = PhysicalDeviceGroupProperties>, VulkanError> {
let fns = self.fns();
let enumerate_physical_device_groups = if self.api_version() >= Version::V1_1 {
fns.v1_1.enumerate_physical_device_groups
@ -808,7 +809,7 @@ impl Instance {
enumerate_physical_device_groups(self.handle, &mut count, ptr::null_mut())
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
let mut properties = Vec::with_capacity(count as usize);
let result =
@ -820,7 +821,7 @@ impl Instance {
break properties;
}
ash::vk::Result::INCOMPLETE => (),
err => return Err(RuntimeError::from(err)),
err => return Err(VulkanError::from(err)),
}
};
@ -1068,7 +1069,7 @@ impl InstanceCreateInfo {
}
}
pub(crate) fn validate(&self, library: &VulkanLibrary) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, library: &VulkanLibrary) -> Result<(), Box<ValidationError>> {
let &Self {
flags,
application_name: _,
@ -1087,12 +1088,12 @@ impl InstanceCreateInfo {
let api_version = std::cmp::min(max_api_version, library.api_version());
if max_api_version < Version::V1_0 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "max_api_version".into(),
problem: "is less than 1.0".into(),
vuids: &["VUID-VkApplicationInfo-apiVersion-04010"],
..Default::default()
});
}));
}
flags
@ -1105,14 +1106,14 @@ impl InstanceCreateInfo {
if !enabled_validation_features.is_empty() {
if !enabled_extensions.ext_validation_features {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "enabled_validation_features".into(),
problem: "is not empty".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[
Requires::InstanceExtension("ext_validation_features"),
])]),
..Default::default()
});
}));
}
for (index, enabled) in enabled_validation_features.iter().enumerate() {
@ -1131,7 +1132,7 @@ impl InstanceCreateInfo {
.contains(&ValidationFeatureEnable::GpuAssistedReserveBindingSlot)
&& !enabled_validation_features.contains(&ValidationFeatureEnable::GpuAssisted)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "enabled_validation_features".into(),
problem: "contains `ValidationFeatureEnable::GpuAssistedReserveBindingSlot`, \
but does not also contain \
@ -1139,33 +1140,33 @@ impl InstanceCreateInfo {
.into(),
vuids: &["VUID-VkValidationFeaturesEXT-pEnabledValidationFeatures-02967"],
..Default::default()
});
}));
}
if enabled_validation_features.contains(&ValidationFeatureEnable::DebugPrintf)
&& enabled_validation_features.contains(&ValidationFeatureEnable::GpuAssisted)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "enabled_validation_features".into(),
problem: "contains both `ValidationFeatureEnable::DebugPrintf` and \
`ValidationFeatureEnable::GpuAssisted`"
.into(),
vuids: &["VUID-VkValidationFeaturesEXT-pEnabledValidationFeatures-02968"],
..Default::default()
});
}));
}
}
if !disabled_validation_features.is_empty() {
if !enabled_extensions.ext_validation_features {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "disabled_validation_features".into(),
problem: "is not empty".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[
Requires::InstanceExtension("ext_validation_features"),
])]),
..Default::default()
});
}));
}
for (index, disabled) in disabled_validation_features.iter().enumerate() {

View File

@ -290,72 +290,179 @@ impl<T> Deref for DebugWrapper<T> {
}
}
/// An error that can happen when calling a safe (validated) function that makes a call to the
/// Vulkan API.
#[derive(Clone)]
pub enum VulkanError {
/// The function call was invalid in some way.
ValidationError(ValidationError),
// Generated by build.rs
include!(concat!(env!("OUT_DIR"), "/errors.rs"));
/// The Vulkan driver returned an error and was unable to complete the operation.
RuntimeError(RuntimeError),
}
impl VulkanError {
/// Returns the contained `RuntimeError` value, or panics if it contains `ValidationError`.
#[track_caller]
#[inline]
pub fn unwrap_runtime(self) -> RuntimeError {
match self {
VulkanError::ValidationError(err) => {
panic!(
"called `VulkanError::unwrap_runtime` on a `ValidationError` value: {:?}",
err
)
}
VulkanError::RuntimeError(err) => err,
}
}
}
impl Debug for VulkanError {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
match self {
Self::ValidationError(err) => {
write!(f, "a validation error occurred\n\nCaused by:\n {err:?}")
}
Self::RuntimeError(err) => write!(f, "a runtime error occurred: {err}"),
}
}
}
impl Error for VulkanError {}
impl Display for VulkanError {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
let msg = match self {
VulkanError::OutOfHostMemory => "a host memory allocation has failed",
VulkanError::OutOfDeviceMemory => "a device memory allocation has failed",
VulkanError::InitializationFailed => {
"initialization of an object could not be completed for implementation-specific \
reasons"
}
VulkanError::DeviceLost => "the logical or physical device has been lost",
VulkanError::MemoryMapFailed => "mapping of a memory object has failed",
VulkanError::LayerNotPresent => {
"a requested layer is not present or could not be loaded"
}
VulkanError::ExtensionNotPresent => "a requested extension is not supported",
VulkanError::FeatureNotPresent => "a requested feature is not supported",
VulkanError::IncompatibleDriver => {
"the requested version of Vulkan is not supported by the driver or is otherwise \
incompatible for implementation-specific reasons"
}
VulkanError::TooManyObjects => "too many objects of the type have already been created",
VulkanError::FormatNotSupported => "a requested format is not supported on this device",
VulkanError::FragmentedPool => {
"a pool allocation has failed due to fragmentation of the pool's memory"
}
VulkanError::Unknown => {
"an unknown error has occurred; either the application has provided invalid input, \
or an implementation failure has occurred"
}
VulkanError::OutOfPoolMemory => "a pool memory allocation has failed",
VulkanError::InvalidExternalHandle => {
"an external handle is not a valid handle of the specified type"
}
VulkanError::Fragmentation => {
"a descriptor pool creation has failed due to fragmentation"
}
VulkanError::InvalidOpaqueCaptureAddress => {
"a buffer creation or memory allocation failed because the requested address is \
not available. A shader group handle assignment failed because the requested \
shader group handle information is no longer valid"
}
VulkanError::IncompatibleDisplay => {
"the display used by a swapchain does not use the same presentable image layout, \
or is incompatible in a way that prevents sharing an image"
}
VulkanError::NotPermitted => "a requested operation was not permitted",
VulkanError::SurfaceLost => "a surface is no longer available",
VulkanError::NativeWindowInUse => {
"the requested window is already in use by Vulkan or another API in a manner which \
prevents it from being used again"
}
VulkanError::OutOfDate => {
"a surface has changed in such a way that it is no longer compatible with the \
swapchain, and further presentation requests using the swapchain will fail"
}
VulkanError::InvalidVideoStdParameters => {
"the provided Video Std parameters do not adhere to the requirements of the used \
video compression standard"
}
VulkanError::ValidationFailed => "validation failed",
VulkanError::FullScreenExclusiveModeLost => {
"an operation on a swapchain created with application controlled full-screen \
access failed as it did not have exclusive full-screen access"
}
VulkanError::InvalidDrmFormatModifierPlaneLayout => {
"the requested DRM format modifier plane layout is invalid"
}
VulkanError::InvalidShader => "one or more shaders failed to compile or link",
VulkanError::ImageUsageNotSupported => "the requested `ImageUsage` are not supported",
VulkanError::VideoPictureLayoutNotSupported => {
"the requested video picture layout is not supported"
}
VulkanError::VideoProfileOperationNotSupported => {
"a video profile operation specified via `VideoProfileInfo::video_codec_operation` \
is not supported"
}
VulkanError::VideoProfileFormatNotSupported => {
"format parameters in a requested `VideoProfileInfo` chain are not supported"
}
VulkanError::VideoProfileCodecNotSupported => {
"codec-specific parameters in a requested `VideoProfileInfo` chain are not \
supported"
}
VulkanError::VideoStdVersionNotSupported => {
"the specified video Std header version is not supported"
}
VulkanError::CompressionExhausted => {
"an image creation failed because internal resources required for compression are \
exhausted"
}
VulkanError::Unnamed(result) => {
return write!(f, "unnamed error, VkResult value {}", result.as_raw());
}
};
write!(f, "{msg}")
}
}
impl From<VulkanError> for Validated<VulkanError> {
fn from(err: VulkanError) -> Self {
Self::Error(err)
}
}
/// A wrapper for error types of functions that can return validation errors.
#[derive(Clone)]
pub enum Validated<E> {
/// A non-validation error occurred.
Error(E),
/// A validation error occurred.
ValidationError(Box<ValidationError>),
}
impl<E> Validated<E> {
/// Returns the inner `Error` value, or panics if it contains `ValidationError`.
pub fn unwrap(self) -> E {
match self {
Self::ValidationError(_) => write!(f, "a validation error occurred"),
Self::RuntimeError(_) => write!(f, "a runtime error occurred"),
Self::Error(err) => err,
Self::ValidationError(err) => {
panic!(
"called `Validated::unwrap` on a `ValidationError` value: {:?}",
err
)
}
}
}
}
impl Error for VulkanError {
impl<E> Error for Validated<E>
where
E: Error + 'static,
{
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
Self::Error(err) => Some(err),
Self::ValidationError(err) => Some(err),
Self::RuntimeError(err) => Some(err),
}
}
}
impl From<ValidationError> for VulkanError {
fn from(err: ValidationError) -> Self {
Self::ValidationError(err)
impl<E> Display for Validated<E> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
match self {
Self::Error(_) => write!(f, "a non-validation error occurred"),
Self::ValidationError(_) => write!(f, "a validation error occurred"),
}
}
}
impl From<RuntimeError> for VulkanError {
fn from(err: RuntimeError) -> Self {
Self::RuntimeError(err)
impl<E> Debug for Validated<E>
where
E: Display,
{
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
match self {
Self::Error(err) => write!(f, "a non-validation error occurred: {err}"),
Self::ValidationError(err) => {
write!(f, "a validation error occurred\n\nCaused by:\n {err:?}")
}
}
}
}
impl<E> From<Box<ValidationError>> for Validated<E> {
fn from(err: Box<ValidationError>) -> Self {
Self::ValidationError(err)
}
}
@ -394,18 +501,14 @@ impl ValidationError {
}
}
fn add_context(self, context: impl Into<Cow<'static, str>>) -> Self {
fn add_context(mut self: Box<Self>, context: impl Into<Cow<'static, str>>) -> Box<Self> {
if self.context.is_empty() {
Self {
context: context.into(),
..self
}
self.context = context.into();
} else {
Self {
context: format!("{}.{}", context.into(), self.context).into(),
..self
}
self.context = format!("{}.{}", context.into(), self.context).into();
}
self
}
}
@ -595,124 +698,16 @@ impl Display for OomError {
}
}
impl From<RuntimeError> for OomError {
fn from(err: RuntimeError) -> OomError {
impl From<VulkanError> for OomError {
fn from(err: VulkanError) -> OomError {
match err {
RuntimeError::OutOfHostMemory => OomError::OutOfHostMemory,
RuntimeError::OutOfDeviceMemory => OomError::OutOfDeviceMemory,
VulkanError::OutOfHostMemory => OomError::OutOfHostMemory,
VulkanError::OutOfDeviceMemory => OomError::OutOfDeviceMemory,
_ => panic!("unexpected error: {:?}", err),
}
}
}
// Generated by build.rs
include!(concat!(env!("OUT_DIR"), "/errors.rs"));
impl Error for RuntimeError {}
impl Display for RuntimeError {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
let msg = match self {
RuntimeError::OutOfHostMemory => "a host memory allocation has failed",
RuntimeError::OutOfDeviceMemory => "a device memory allocation has failed",
RuntimeError::InitializationFailed => {
"initialization of an object could not be completed for implementation-specific \
reasons"
}
RuntimeError::DeviceLost => "the logical or physical device has been lost",
RuntimeError::MemoryMapFailed => "mapping of a memory object has failed",
RuntimeError::LayerNotPresent => {
"a requested layer is not present or could not be loaded"
}
RuntimeError::ExtensionNotPresent => "a requested extension is not supported",
RuntimeError::FeatureNotPresent => "a requested feature is not supported",
RuntimeError::IncompatibleDriver => {
"the requested version of Vulkan is not supported by the driver or is otherwise \
incompatible for implementation-specific reasons"
}
RuntimeError::TooManyObjects => {
"too many objects of the type have already been created"
}
RuntimeError::FormatNotSupported => {
"a requested format is not supported on this device"
}
RuntimeError::FragmentedPool => {
"a pool allocation has failed due to fragmentation of the pool's memory"
}
RuntimeError::Unknown => {
"an unknown error has occurred; either the application has provided invalid input, \
or an implementation failure has occurred"
}
RuntimeError::OutOfPoolMemory => "a pool memory allocation has failed",
RuntimeError::InvalidExternalHandle => {
"an external handle is not a valid handle of the specified type"
}
RuntimeError::Fragmentation => {
"a descriptor pool creation has failed due to fragmentation"
}
RuntimeError::InvalidOpaqueCaptureAddress => {
"a buffer creation or memory allocation failed because the requested address is \
not available. A shader group handle assignment failed because the requested \
shader group handle information is no longer valid"
}
RuntimeError::IncompatibleDisplay => {
"the display used by a swapchain does not use the same presentable image layout, \
or is incompatible in a way that prevents sharing an image"
}
RuntimeError::NotPermitted => "a requested operation was not permitted",
RuntimeError::SurfaceLost => "a surface is no longer available",
RuntimeError::NativeWindowInUse => {
"the requested window is already in use by Vulkan or another API in a manner which \
prevents it from being used again"
}
RuntimeError::OutOfDate => {
"a surface has changed in such a way that it is no longer compatible with the \
swapchain, and further presentation requests using the swapchain will fail"
}
RuntimeError::InvalidVideoStdParameters => {
"the provided Video Std parameters do not adhere to the requirements of the used \
video compression standard"
}
RuntimeError::ValidationFailed => "validation failed",
RuntimeError::FullScreenExclusiveModeLost => {
"an operation on a swapchain created with application controlled full-screen \
access failed as it did not have exclusive full-screen access"
}
RuntimeError::InvalidDrmFormatModifierPlaneLayout => {
"the requested DRM format modifier plane layout is invalid"
}
RuntimeError::InvalidShader => "one or more shaders failed to compile or link",
RuntimeError::ImageUsageNotSupported => "the requested `ImageUsage` are not supported",
RuntimeError::VideoPictureLayoutNotSupported => {
"the requested video picture layout is not supported"
}
RuntimeError::VideoProfileOperationNotSupported => {
"a video profile operation specified via `VideoProfileInfo::video_codec_operation` \
is not supported"
}
RuntimeError::VideoProfileFormatNotSupported => {
"format parameters in a requested `VideoProfileInfo` chain are not supported"
}
RuntimeError::VideoProfileCodecNotSupported => {
"codec-specific parameters in a requested `VideoProfileInfo` chain are not \
supported"
}
RuntimeError::VideoStdVersionNotSupported => {
"the specified video Std header version is not supported"
}
RuntimeError::CompressionExhausted => {
"an image creation failed because internal resources required for compression are \
exhausted"
}
RuntimeError::Unnamed(result) => {
return write!(f, "unnamed error, VkResult value {}", result.as_raw());
}
};
write!(f, "{msg}")
}
}
/// A helper type for non-exhaustive structs.
///
/// This type cannot be constructed outside Vulkano. Structures with a field of this type can only

View File

@ -21,7 +21,7 @@
pub use crate::fns::EntryFunctions;
use crate::{
instance::{InstanceExtensions, LayerProperties},
ExtensionProperties, OomError, RuntimeError, SafeDeref, Version,
ExtensionProperties, OomError, SafeDeref, Version, VulkanError,
};
use libloading::{Error as LibloadingError, Library};
use std::{
@ -121,7 +121,7 @@ impl VulkanLibrary {
}))
}
unsafe fn get_api_version(loader: &impl Loader) -> Result<Version, RuntimeError> {
unsafe fn get_api_version(loader: &impl Loader) -> Result<Version, VulkanError> {
// Per the Vulkan spec:
// If the vkGetInstanceProcAddr returns NULL for vkEnumerateInstanceVersion, it is a
// Vulkan 1.0 implementation. Otherwise, the application can call vkEnumerateInstanceVersion
@ -133,9 +133,7 @@ impl VulkanLibrary {
let version = if let Some(func) = func {
let func: ash::vk::PFN_vkEnumerateInstanceVersion = transmute(func);
let mut api_version = 0;
func(&mut api_version)
.result()
.map_err(RuntimeError::from)?;
func(&mut api_version).result().map_err(VulkanError::from)?;
Version::from(api_version)
} else {
Version {
@ -151,7 +149,7 @@ impl VulkanLibrary {
unsafe fn get_extension_properties(
fns: &EntryFunctions,
layer: Option<&str>,
) -> Result<Vec<ExtensionProperties>, RuntimeError> {
) -> Result<Vec<ExtensionProperties>, VulkanError> {
let layer_vk = layer.map(|layer| CString::new(layer).unwrap());
loop {
@ -164,7 +162,7 @@ impl VulkanLibrary {
ptr::null_mut(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
let mut output = Vec::with_capacity(count as usize);
let result = (fns.v1_0.enumerate_instance_extension_properties)(
@ -181,7 +179,7 @@ impl VulkanLibrary {
return Ok(output.into_iter().map(Into::into).collect());
}
ash::vk::Result::INCOMPLETE => (),
err => return Err(RuntimeError::from(err)),
err => return Err(VulkanError::from(err)),
}
}
}
@ -243,7 +241,7 @@ impl VulkanLibrary {
let mut count = 0;
(fns.v1_0.enumerate_instance_layer_properties)(&mut count, ptr::null_mut())
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
let mut properties = Vec::with_capacity(count as usize);
let result = (fns.v1_0.enumerate_instance_layer_properties)(
@ -257,7 +255,7 @@ impl VulkanLibrary {
break properties;
}
ash::vk::Result::INCOMPLETE => (),
err => return Err(RuntimeError::from(err).into()),
err => return Err(VulkanError::from(err).into()),
}
}
};
@ -272,7 +270,7 @@ impl VulkanLibrary {
pub fn layer_extension_properties(
&self,
layer: &str,
) -> Result<Vec<ExtensionProperties>, RuntimeError> {
) -> Result<Vec<ExtensionProperties>, VulkanError> {
unsafe { Self::get_extension_properties(&self.fns, Some(layer)) }
}
@ -281,7 +279,7 @@ impl VulkanLibrary {
pub fn supported_layer_extensions(
&self,
layer: &str,
) -> Result<InstanceExtensions, RuntimeError> {
) -> Result<InstanceExtensions, VulkanError> {
Ok(self
.layer_extension_properties(layer)?
.iter()
@ -295,7 +293,7 @@ impl VulkanLibrary {
pub fn supported_extensions_with_layers<'a>(
&self,
layers: impl IntoIterator<Item = &'a str>,
) -> Result<InstanceExtensions, RuntimeError> {
) -> Result<InstanceExtensions, VulkanError> {
layers
.into_iter()
.try_fold(self.supported_extensions, |extensions, layer| {
@ -427,14 +425,14 @@ pub enum LoadingError {
LibraryLoadFailure(LibloadingError),
/// The Vulkan driver returned an error and was unable to complete the operation.
RuntimeError(RuntimeError),
VulkanError(VulkanError),
}
impl Error for LoadingError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
//Self::LibraryLoadFailure(err) => Some(err),
Self::RuntimeError(err) => Some(err),
Self::VulkanError(err) => Some(err),
_ => None,
}
}
@ -444,14 +442,14 @@ impl Display for LoadingError {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
match self {
Self::LibraryLoadFailure(_) => write!(f, "failed to load the Vulkan shared library"),
Self::RuntimeError(err) => write!(f, "a runtime error occurred: {err}"),
Self::VulkanError(err) => write!(f, "a runtime error occurred: {err}"),
}
}
}
impl From<RuntimeError> for LoadingError {
fn from(err: RuntimeError) -> Self {
Self::RuntimeError(err)
impl From<VulkanError> for LoadingError {
fn from(err: VulkanError) -> Self {
Self::VulkanError(err)
}
}

View File

@ -235,7 +235,7 @@ use super::{
use crate::{
device::{Device, DeviceOwned},
instance::InstanceOwnedDebugWrapper,
DeviceSize, Requires, RequiresAllOf, RequiresOneOf, RuntimeError, ValidationError, Version,
DeviceSize, Requires, RequiresAllOf, RequiresOneOf, ValidationError, Version, VulkanError,
};
use ash::vk::{MAX_MEMORY_HEAPS, MAX_MEMORY_TYPES};
use parking_lot::RwLock;
@ -525,7 +525,7 @@ pub enum MemoryAllocatePreference {
/// [memory allocator]: MemoryAllocator
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum MemoryAllocatorError {
RuntimeError(RuntimeError),
VulkanError(VulkanError),
/// There is not enough memory in the pool.
///
@ -555,7 +555,7 @@ pub enum MemoryAllocatorError {
impl Error for MemoryAllocatorError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
Self::RuntimeError(err) => Some(err),
Self::VulkanError(err) => Some(err),
_ => None,
}
}
@ -564,7 +564,7 @@ impl Error for MemoryAllocatorError {
impl Display for MemoryAllocatorError {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
match self {
Self::RuntimeError(_) => write!(f, "a runtime error occurred"),
Self::VulkanError(_) => write!(f, "a runtime error occurred"),
Self::OutOfPoolMemory => write!(f, "the pool doesn't have enough free space"),
Self::DedicatedAllocationRequired => write!(
f,
@ -583,9 +583,9 @@ impl Display for MemoryAllocatorError {
}
}
impl From<RuntimeError> for MemoryAllocatorError {
fn from(err: RuntimeError) -> Self {
MemoryAllocatorError::RuntimeError(err)
impl From<VulkanError> for MemoryAllocatorError {
fn from(err: VulkanError) -> Self {
MemoryAllocatorError::VulkanError(err)
}
}
@ -695,7 +695,7 @@ impl<S: Suballocator> GenericMemoryAllocator<S> {
pub fn new(
device: Arc<Device>,
create_info: GenericMemoryAllocatorCreateInfo<'_, '_>,
) -> Result<Self, ValidationError> {
) -> Result<Self, Box<ValidationError>> {
Self::validate_new(&device, &create_info)?;
Ok(unsafe { Self::new_unchecked(device, create_info) })
@ -704,7 +704,7 @@ impl<S: Suballocator> GenericMemoryAllocator<S> {
fn validate_new(
device: &Device,
create_info: &GenericMemoryAllocatorCreateInfo<'_, '_>,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
let &GenericMemoryAllocatorCreateInfo {
block_sizes,
allocation_type: _,
@ -727,7 +727,7 @@ impl<S: Suballocator> GenericMemoryAllocator<S> {
if !(device.api_version() >= Version::V1_1
&& device.enabled_extensions().khr_external_memory)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "create_info.export_handle_types".into(),
problem: "is not empty".into(),
requires_one_of: RequiresOneOf(&[
@ -735,7 +735,7 @@ impl<S: Suballocator> GenericMemoryAllocator<S> {
RequiresAllOf(&[Requires::DeviceExtension("khr_external_memory")]),
]),
..Default::default()
});
}));
}
assert!(
@ -977,7 +977,7 @@ unsafe impl<S: Suballocator> MemoryAllocator for GenericMemoryAllocator<S> {
/// [`protected_memory`]: crate::device::Features::protected_memory
/// [`DEVICE_COHERENT`]: MemoryPropertyFlags::DEVICE_COHERENT
/// [`device_coherent_memory`]: crate::device::Features::device_coherent_memory
/// [`TooManyObjects`]: RuntimeError::TooManyObjects
/// [`TooManyObjects`]: VulkanError::TooManyObjects
/// [`BlockSizeExceeded`]: MemoryAllocatorError::BlockSizeExceeded
/// [`SuballocatorBlockSizeExceeded`]: MemoryAllocatorError::SuballocatorBlockSizeExceeded
fn allocate_from_type(
@ -1134,9 +1134,7 @@ unsafe impl<S: Suballocator> MemoryAllocator for GenericMemoryAllocator<S> {
break S::new(MemoryAlloc::new(device_memory)?);
}
// Retry up to 3 times, halving the allocation size each time.
Err(RuntimeError::OutOfHostMemory | RuntimeError::OutOfDeviceMemory)
if i < 3 =>
{
Err(VulkanError::OutOfHostMemory | VulkanError::OutOfDeviceMemory) if i < 3 => {
i += 1;
}
Err(err) => return Err(err.into()),
@ -1151,8 +1149,8 @@ unsafe impl<S: Suballocator> MemoryAllocator for GenericMemoryAllocator<S> {
Ok(allocation) => Ok(allocation),
// This can happen if the block ended up smaller than advertised because there wasn't
// enough memory.
Err(SuballocatorError::OutOfRegionMemory) => Err(MemoryAllocatorError::RuntimeError(
RuntimeError::OutOfDeviceMemory,
Err(SuballocatorError::OutOfRegionMemory) => Err(MemoryAllocatorError::VulkanError(
VulkanError::OutOfDeviceMemory,
)),
// This can not happen as the block is fresher than Febreze and we're still holding an
// exclusive lock.
@ -1195,7 +1193,7 @@ unsafe impl<S: Suballocator> MemoryAllocator for GenericMemoryAllocator<S> {
/// `create_info.size` is greater than `BLOCK_SIZE` and a dedicated allocation was not
/// created.
///
/// [`TooManyObjects`]: RuntimeError::TooManyObjects
/// [`TooManyObjects`]: VulkanError::TooManyObjects
/// [`OutOfPoolMemory`]: MemoryAllocatorError::OutOfPoolMemory
/// [`DedicatedAllocationRequired`]: MemoryAllocatorError::DedicatedAllocationRequired
/// [`BlockSizeExceeded`]: MemoryAllocatorError::BlockSizeExceeded

View File

@ -21,7 +21,7 @@ use crate::{
device::{Device, DeviceOwned},
image::ImageTiling,
memory::{is_aligned, DeviceMemory, MemoryPropertyFlags},
DeviceSize, NonZeroDeviceSize, RuntimeError, VulkanObject,
DeviceSize, NonZeroDeviceSize, VulkanError, VulkanObject,
};
use crossbeam_queue::ArrayQueue;
use parking_lot::Mutex;
@ -124,7 +124,7 @@ impl MemoryAlloc {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
Some(NonNull::new(output.assume_init()).unwrap())
}
@ -229,7 +229,7 @@ impl MemoryAlloc {
/// [host-coherent]: crate::memory::MemoryPropertyFlags::HOST_COHERENT
/// [`non_coherent_atom_size`]: crate::device::Properties::non_coherent_atom_size
#[inline]
pub unsafe fn invalidate_range(&self, range: Range<DeviceSize>) -> Result<(), RuntimeError> {
pub unsafe fn invalidate_range(&self, range: Range<DeviceSize>) -> Result<(), VulkanError> {
// VUID-VkMappedMemoryRange-memory-00684
if let Some(atom_size) = self.atom_size {
let range = self.create_memory_range(range, atom_size);
@ -237,7 +237,7 @@ impl MemoryAlloc {
let fns = device.fns();
(fns.v1_0.invalidate_mapped_memory_ranges)(device.handle(), 1, &range)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
} else {
self.debug_validate_memory_range(&range);
}
@ -269,7 +269,7 @@ impl MemoryAlloc {
/// [host-coherent]: crate::memory::MemoryPropertyFlags::HOST_COHERENT
/// [`non_coherent_atom_size`]: crate::device::Properties::non_coherent_atom_size
#[inline]
pub unsafe fn flush_range(&self, range: Range<DeviceSize>) -> Result<(), RuntimeError> {
pub unsafe fn flush_range(&self, range: Range<DeviceSize>) -> Result<(), VulkanError> {
// VUID-VkMappedMemoryRange-memory-00684
if let Some(atom_size) = self.atom_size {
let range = self.create_memory_range(range, atom_size);
@ -277,7 +277,7 @@ impl MemoryAlloc {
let fns = device.fns();
(fns.v1_0.flush_mapped_memory_ranges)(device.handle(), 1, &range)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
} else {
self.debug_validate_memory_range(&range);
}

View File

@ -13,7 +13,7 @@ use crate::{
instance::InstanceOwnedDebugWrapper,
macros::{impl_id_counter, vulkan_bitflags, vulkan_bitflags_enum},
memory::{is_aligned, MemoryPropertyFlags},
DeviceSize, Requires, RequiresAllOf, RequiresOneOf, RuntimeError, ValidationError, Version,
DeviceSize, Requires, RequiresAllOf, RequiresOneOf, Validated, ValidationError, Version,
VulkanError, VulkanObject,
};
use std::{
@ -78,7 +78,7 @@ impl DeviceMemory {
pub fn allocate(
device: Arc<Device>,
mut allocate_info: MemoryAllocateInfo<'_>,
) -> Result<Self, VulkanError> {
) -> Result<Self, Validated<VulkanError>> {
if !(device.api_version() >= Version::V1_1
|| device.enabled_extensions().khr_dedicated_allocation)
{
@ -107,7 +107,7 @@ impl DeviceMemory {
device: Arc<Device>,
mut allocate_info: MemoryAllocateInfo<'_>,
import_info: MemoryImportInfo,
) -> Result<Self, VulkanError> {
) -> Result<Self, Validated<VulkanError>> {
if !(device.api_version() >= Version::V1_1
|| device.enabled_extensions().khr_dedicated_allocation)
{
@ -129,7 +129,7 @@ impl DeviceMemory {
device: &Device,
allocate_info: &MemoryAllocateInfo<'_>,
import_info: Option<&MemoryImportInfo>,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
allocate_info
.validate(device)
.map_err(|err| err.add_context("allocate_info"))?;
@ -149,7 +149,7 @@ impl DeviceMemory {
device: Arc<Device>,
mut allocate_info: MemoryAllocateInfo<'_>,
import_info: Option<MemoryImportInfo>,
) -> Result<Self, RuntimeError> {
) -> Result<Self, VulkanError> {
if !(device.api_version() >= Version::V1_1
|| device.enabled_extensions().khr_dedicated_allocation)
{
@ -261,7 +261,7 @@ impl DeviceMemory {
.fetch_update(Ordering::Acquire, Ordering::Relaxed, move |count| {
(count < max_allocations).then_some(count + 1)
})
.map_err(|_| RuntimeError::TooManyObjects)?;
.map_err(|_| VulkanError::TooManyObjects)?;
let handle = {
let fns = device.fns();
@ -275,7 +275,7 @@ impl DeviceMemory {
.result()
.map_err(|e| {
device.allocation_count.fetch_sub(1, Ordering::Release);
RuntimeError::from(e)
VulkanError::from(e)
})?;
output.assume_init()
@ -381,13 +381,13 @@ impl DeviceMemory {
///
/// [`LAZILY_ALLOCATED`]: crate::memory::MemoryPropertyFlags::LAZILY_ALLOCATED
#[inline]
pub fn commitment(&self) -> Result<DeviceSize, ValidationError> {
pub fn commitment(&self) -> Result<DeviceSize, Box<ValidationError>> {
self.validate_commitment()?;
unsafe { Ok(self.commitment_unchecked()) }
}
fn validate_commitment(&self) -> Result<(), ValidationError> {
fn validate_commitment(&self) -> Result<(), Box<ValidationError>> {
let memory_type = &self
.device
.physical_device()
@ -398,13 +398,13 @@ impl DeviceMemory {
.property_flags
.intersects(MemoryPropertyFlags::LAZILY_ALLOCATED)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the `property_flags` of the memory type does not contain the \
`MemoryPropertyFlags::LAZILY_ALLOCATED` flag"
.into(),
vuids: &["VUID-vkGetDeviceMemoryCommitment-memory-00690"],
..Default::default()
});
}));
}
Ok(())
@ -427,7 +427,10 @@ impl DeviceMemory {
///
/// - Panics if the user requests an invalid handle type for this device memory object.
#[inline]
pub fn export_fd(&self, handle_type: ExternalMemoryHandleType) -> Result<File, VulkanError> {
pub fn export_fd(
&self,
handle_type: ExternalMemoryHandleType,
) -> Result<File, Validated<VulkanError>> {
self.validate_export_fd(handle_type)?;
unsafe { Ok(self.export_fd_unchecked(handle_type)?) }
@ -436,7 +439,7 @@ impl DeviceMemory {
fn validate_export_fd(
&self,
handle_type: ExternalMemoryHandleType,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
handle_type
.validate_device(&self.device)
.map_err(|err| ValidationError {
@ -449,23 +452,23 @@ impl DeviceMemory {
handle_type,
ExternalMemoryHandleType::OpaqueFd | ExternalMemoryHandleType::DmaBuf
) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "handle_type".into(),
problem: "is not `ExternalMemoryHandleType::OpaqueFd` or \
`ExternalMemoryHandleType::DmaBuf`"
.into(),
vuids: &["VUID-VkMemoryGetFdInfoKHR-handleType-00672"],
..Default::default()
});
}));
}
if !self.export_handle_types.contains_enum(handle_type) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "handle_type".into(),
problem: "is not contained in this memory's `export_handle_types`".into(),
vuids: &["VUID-VkMemoryGetFdInfoKHR-handleType-00671"],
..Default::default()
});
}));
}
Ok(())
@ -475,7 +478,7 @@ impl DeviceMemory {
pub unsafe fn export_fd_unchecked(
&self,
handle_type: ExternalMemoryHandleType,
) -> Result<File, RuntimeError> {
) -> Result<File, VulkanError> {
debug_assert!(self.device().enabled_extensions().khr_external_memory_fd);
#[cfg(not(unix))]
@ -500,7 +503,7 @@ impl DeviceMemory {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -604,7 +607,7 @@ impl<'d> MemoryAllocateInfo<'d> {
}
}
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
allocation_size,
memory_type_index,
@ -631,7 +634,7 @@ impl<'d> MemoryAllocateInfo<'d> {
.intersects(MemoryPropertyFlags::PROTECTED)
&& !device.enabled_features().protected_memory
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "memory_type_index".into(),
problem: "refers to a memory type where `property_flags` contains \
`MemoryPropertyFlags::PROTECTED`"
@ -640,7 +643,7 @@ impl<'d> MemoryAllocateInfo<'d> {
"protected_memory",
)])]),
vuids: &["VUID-VkMemoryAllocateInfo-memoryTypeIndex-01872"],
});
}));
}
if memory_type
@ -648,7 +651,7 @@ impl<'d> MemoryAllocateInfo<'d> {
.intersects(MemoryPropertyFlags::DEVICE_COHERENT)
&& !device.enabled_features().device_coherent_memory
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "memory_type_index".into(),
problem: "refers to a memory type where `property_flags` contains \
`MemoryPropertyFlags::DEVICE_COHERENT`"
@ -657,25 +660,25 @@ impl<'d> MemoryAllocateInfo<'d> {
"device_coherent_memory",
)])]),
vuids: &["VUID-vkAllocateMemory-deviceCoherentMemory-02790"],
});
}));
}
if allocation_size == 0 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "allocation_size".into(),
problem: "is zero".into(),
vuids: &["VUID-VkMemoryAllocateInfo-pNext-01874"],
..Default::default()
});
}));
}
if memory_heap.size != 0 && allocation_size > memory_heap.size {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "allocation_size".into(),
problem: "is greater than the size of the memory heap".into(),
vuids: &["VUID-vkAllocateMemory-pAllocateInfo-01713"],
..Default::default()
});
}));
}
if let Some(dedicated_allocation) = dedicated_allocation {
@ -687,13 +690,13 @@ impl<'d> MemoryAllocateInfo<'d> {
let required_size = buffer.memory_requirements().layout.size();
if allocation_size != required_size {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`allocation_size` does not equal the size required for the \
buffer specified in `dedicated_allocation`"
.into(),
vuids: &["VUID-VkMemoryDedicatedAllocateInfo-buffer-02965"],
..Default::default()
});
}));
}
}
DedicatedAllocation::Image(image) => {
@ -703,13 +706,13 @@ impl<'d> MemoryAllocateInfo<'d> {
let required_size = image.memory_requirements()[0].layout.size();
if allocation_size != required_size {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`allocation_size` does not equal the size required for the \
image specified in `dedicated_allocation`"
.into(),
vuids: &["VUID-VkMemoryDedicatedAllocateInfo-image-02964"],
..Default::default()
});
}));
}
}
}
@ -719,7 +722,7 @@ impl<'d> MemoryAllocateInfo<'d> {
if !(device.api_version() >= Version::V1_1
|| device.enabled_extensions().khr_external_memory)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "export_handle_types".into(),
problem: "is not empty".into(),
requires_one_of: RequiresOneOf(&[
@ -727,7 +730,7 @@ impl<'d> MemoryAllocateInfo<'d> {
RequiresAllOf(&[Requires::DeviceExtension("khr_external_memory")]),
]),
..Default::default()
});
}));
}
export_handle_types
@ -749,7 +752,7 @@ impl<'d> MemoryAllocateInfo<'d> {
if !(device.physical_device().api_version() >= Version::V1_1
|| device.enabled_extensions().khr_device_group)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "flags".into(),
problem: "is not empty".into(),
requires_one_of: RequiresOneOf(&[
@ -757,7 +760,7 @@ impl<'d> MemoryAllocateInfo<'d> {
RequiresAllOf(&[Requires::DeviceExtension("khr_device_group")]),
]),
..Default::default()
});
}));
}
if flags.intersects(MemoryAllocateFlags::DEVICE_ADDRESS) {
@ -765,7 +768,7 @@ impl<'d> MemoryAllocateInfo<'d> {
|| device.enabled_extensions().khr_buffer_device_address)
&& device.enabled_features().buffer_device_address)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "flags".into(),
problem: "contains `MemoryAllocateFlags::DEVICE_ADDRESS`".into(),
requires_one_of: RequiresOneOf(&[
@ -779,7 +782,7 @@ impl<'d> MemoryAllocateInfo<'d> {
]),
]),
vuids: &["VUID-VkMemoryAllocateInfo-flags-03331"],
});
}));
}
}
}
@ -843,7 +846,7 @@ pub enum MemoryImportInfo {
}
impl MemoryImportInfo {
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
match self {
MemoryImportInfo::Fd {
#[cfg(unix)]
@ -853,13 +856,13 @@ impl MemoryImportInfo {
file: _,
} => {
if !device.enabled_extensions().khr_external_memory_fd {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "is `MemoryImportInfo::Fd`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[
Requires::DeviceExtension("khr_external_memory_fd"),
])]),
..Default::default()
});
}));
}
#[cfg(not(unix))]
@ -888,14 +891,14 @@ impl MemoryImportInfo {
}
ExternalMemoryHandleType::DmaBuf => {}
_ => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "handle_type".into(),
problem: "is not `ExternalMemoryHandleType::OpaqueFd` or \
`ExternalMemoryHandleType::DmaBuf`"
.into(),
vuids: &["VUID-VkImportMemoryFdInfoKHR-handleType-00669"],
..Default::default()
});
}));
}
}
@ -911,13 +914,13 @@ impl MemoryImportInfo {
handle: _,
} => {
if !device.enabled_extensions().khr_external_memory_win32 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "is `MemoryImportInfo::Win32`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[
Requires::DeviceExtension("khr_external_memory_win32"),
])]),
..Default::default()
});
}));
}
#[cfg(not(windows))]
@ -948,14 +951,14 @@ impl MemoryImportInfo {
// Can't validate, must be ensured by user
}
_ => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "handle_type".into(),
problem: "is not `ExternalMemoryHandleType::OpaqueWin32` or \
`ExternalMemoryHandleType::OpaqueWin32Kmt`"
.into(),
vuids: &["VUID-VkImportMemoryWin32HandleInfoKHR-handleType-00660"],
..Default::default()
});
}));
}
}
@ -1132,7 +1135,10 @@ impl MappedDeviceMemory {
///
/// - Panics if `range` is empty.
#[inline]
pub fn new(memory: DeviceMemory, range: Range<DeviceSize>) -> Result<Self, VulkanError> {
pub fn new(
memory: DeviceMemory,
range: Range<DeviceSize>,
) -> Result<Self, Validated<VulkanError>> {
Self::validate_new(&memory, range.clone())?;
unsafe { Ok(Self::new_unchecked(memory, range)?) }
@ -1141,14 +1147,14 @@ impl MappedDeviceMemory {
fn validate_new(
memory: &DeviceMemory,
range: Range<DeviceSize>,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
if range.is_empty() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "range".into(),
problem: "is empty".into(),
vuids: &["VUID-vkMapMemory-size-00680"],
..Default::default()
});
}));
}
let device = memory.device();
@ -1159,28 +1165,28 @@ impl MappedDeviceMemory {
.property_flags
.intersects(MemoryPropertyFlags::HOST_VISIBLE)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "memory".into(),
problem: "has a memory type whose `property_flags` does not contain \
`MemoryPropertyFlags::HOST_VISIBLE`"
.into(),
vuids: &["VUID-vkMapMemory-memory-00682"],
..Default::default()
});
}));
}
// VUID-vkMapMemory-memory-00678
// Guaranteed because we take ownership of `memory`, no other mapping can exist.
if range.end > memory.allocation_size {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`range.end` is greater than `memory.allocation_size()`".into(),
vuids: &[
"VUID-vkMapMemory-offset-00679",
"VUID-vkMapMemory-size-00681",
],
..Default::default()
});
}));
}
let is_coherent = memory_type
@ -1195,13 +1201,13 @@ impl MappedDeviceMemory {
&& (!is_aligned(range.start, atom_size)
|| (!is_aligned(range.end, atom_size) && range.end != memory.allocation_size))
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`memory` has a memory type whose `property_flags` does not contain \
`MemoryPropertyFlags::HOST_COHERENT`, and `range.start` and/or `range.end` \
are not aligned to the `non_coherent_atom_size` device property"
.into(),
..Default::default()
});
}));
}
Ok(())
@ -1211,7 +1217,7 @@ impl MappedDeviceMemory {
pub unsafe fn new_unchecked(
memory: DeviceMemory,
range: Range<DeviceSize>,
) -> Result<Self, RuntimeError> {
) -> Result<Self, VulkanError> {
let device = memory.device();
let pointer = unsafe {
@ -1226,7 +1232,7 @@ impl MappedDeviceMemory {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -1279,7 +1285,10 @@ impl MappedDeviceMemory {
///
/// - Panics if `range` is empty.
#[inline]
pub unsafe fn invalidate_range(&self, range: Range<DeviceSize>) -> Result<(), VulkanError> {
pub unsafe fn invalidate_range(
&self,
range: Range<DeviceSize>,
) -> Result<(), Validated<VulkanError>> {
self.validate_range(range.clone())?;
Ok(self.invalidate_range_unchecked(range)?)
@ -1289,7 +1298,7 @@ impl MappedDeviceMemory {
pub unsafe fn invalidate_range_unchecked(
&self,
range: Range<DeviceSize>,
) -> Result<(), RuntimeError> {
) -> Result<(), VulkanError> {
if self.is_coherent {
return Ok(());
}
@ -1304,7 +1313,7 @@ impl MappedDeviceMemory {
let fns = self.memory.device().fns();
(fns.v1_0.invalidate_mapped_memory_ranges)(self.memory.device().handle(), 1, &range)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
Ok(())
}
@ -1330,7 +1339,10 @@ impl MappedDeviceMemory {
///
/// - Panics if `range` is empty.
#[inline]
pub unsafe fn flush_range(&self, range: Range<DeviceSize>) -> Result<(), VulkanError> {
pub unsafe fn flush_range(
&self,
range: Range<DeviceSize>,
) -> Result<(), Validated<VulkanError>> {
self.validate_range(range.clone())?;
Ok(self.flush_range_unchecked(range)?)
@ -1340,7 +1352,7 @@ impl MappedDeviceMemory {
pub unsafe fn flush_range_unchecked(
&self,
range: Range<DeviceSize>,
) -> Result<(), RuntimeError> {
) -> Result<(), VulkanError> {
if self.is_coherent {
return Ok(());
}
@ -1355,7 +1367,7 @@ impl MappedDeviceMemory {
let fns = self.device().fns();
(fns.v1_0.flush_mapped_memory_ranges)(self.memory.device().handle(), 1, &range)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
Ok(())
}
@ -1379,7 +1391,7 @@ impl MappedDeviceMemory {
///
/// - Panics if `range` is empty.
#[inline]
pub unsafe fn read(&self, range: Range<DeviceSize>) -> Result<&[u8], ValidationError> {
pub unsafe fn read(&self, range: Range<DeviceSize>) -> Result<&[u8], Box<ValidationError>> {
self.validate_range(range.clone())?;
Ok(self.read_unchecked(range))
@ -1413,7 +1425,10 @@ impl MappedDeviceMemory {
///
/// - Panics if `range` is empty.
#[inline]
pub unsafe fn write(&self, range: Range<DeviceSize>) -> Result<&mut [u8], ValidationError> {
pub unsafe fn write(
&self,
range: Range<DeviceSize>,
) -> Result<&mut [u8], Box<ValidationError>> {
self.validate_range(range.clone())?;
Ok(self.write_unchecked(range))
@ -1430,25 +1445,25 @@ impl MappedDeviceMemory {
}
#[inline]
fn validate_range(&self, range: Range<DeviceSize>) -> Result<(), ValidationError> {
fn validate_range(&self, range: Range<DeviceSize>) -> Result<(), Box<ValidationError>> {
// VUID-VkMappedMemoryRange-memory-00684
// Guaranteed because `self` owns the memory and it's mapped during our lifetime.
if range.is_empty() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "range".into(),
problem: "is empty".into(),
..Default::default()
});
}));
}
if range.start < self.range.start || range.end > self.range.end {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "range".into(),
problem: "is not within the mapped range of this mapped device memory".into(),
vuids: &["VUID-VkMappedMemoryRange-size-00685"],
..Default::default()
});
}));
}
if !self.is_coherent {
@ -1456,7 +1471,7 @@ impl MappedDeviceMemory {
|| (!is_aligned(range.end, self.atom_size)
&& range.end != self.memory.allocation_size)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "this mapped device memory has a memory type whose `property_flags` \
does not contain `MemoryPropertyFlags::HOST_COHERENT`, and \
`range.start` and/or `range.end` are not aligned to the \
@ -1467,7 +1482,7 @@ impl MappedDeviceMemory {
"VUID-VkMappedMemoryRange-size-01390",
],
..Default::default()
});
}));
}
}

View File

@ -25,7 +25,7 @@ use crate::{
device::{Device, DeviceOwned},
instance::InstanceOwnedDebugWrapper,
macros::{impl_id_counter, vulkan_bitflags},
RuntimeError, ValidationError, VulkanError, VulkanObject,
Validated, ValidationError, VulkanError, VulkanObject,
};
use smallvec::SmallVec;
use std::{mem::MaybeUninit, num::NonZeroU64, ptr, sync::Arc};
@ -92,7 +92,7 @@ impl PipelineCache {
pub unsafe fn new(
device: Arc<Device>,
create_info: PipelineCacheCreateInfo,
) -> Result<Arc<PipelineCache>, VulkanError> {
) -> Result<Arc<PipelineCache>, Validated<VulkanError>> {
Self::validate_new(&device, &create_info)?;
Ok(Self::new_unchecked(device, create_info)?)
@ -101,7 +101,7 @@ impl PipelineCache {
fn validate_new(
device: &Device,
create_info: &PipelineCacheCreateInfo,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
create_info
.validate(device)
.map_err(|err| err.add_context("create_info"))?;
@ -113,7 +113,7 @@ impl PipelineCache {
pub unsafe fn new_unchecked(
device: Arc<Device>,
create_info: PipelineCacheCreateInfo,
) -> Result<Arc<PipelineCache>, RuntimeError> {
) -> Result<Arc<PipelineCache>, VulkanError> {
let &PipelineCacheCreateInfo {
flags,
ref initial_data,
@ -141,7 +141,7 @@ impl PipelineCache {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -205,7 +205,7 @@ impl PipelineCache {
/// }
/// ```
#[inline]
pub fn get_data(&self) -> Result<Vec<u8>, RuntimeError> {
pub fn get_data(&self) -> Result<Vec<u8>, VulkanError> {
let fns = self.device.fns();
let data = unsafe {
@ -218,7 +218,7 @@ impl PipelineCache {
ptr::null_mut(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
let mut data: Vec<u8> = Vec::with_capacity(count);
let result = (fns.v1_0.get_pipeline_cache_data)(
@ -234,7 +234,7 @@ impl PipelineCache {
break data;
}
ash::vk::Result::INCOMPLETE => (),
err => return Err(RuntimeError::from(err)),
err => return Err(VulkanError::from(err)),
}
}
};
@ -251,22 +251,22 @@ impl PipelineCache {
pub fn merge<'a>(
&self,
src_caches: impl IntoIterator<Item = &'a PipelineCache>,
) -> Result<(), VulkanError> {
) -> Result<(), Validated<VulkanError>> {
let src_caches: SmallVec<[_; 8]> = src_caches.into_iter().collect();
self.validate_merge(&src_caches)?;
unsafe { Ok(self.merge_unchecked(src_caches)?) }
}
fn validate_merge(&self, src_caches: &[&PipelineCache]) -> Result<(), ValidationError> {
fn validate_merge(&self, src_caches: &[&PipelineCache]) -> Result<(), Box<ValidationError>> {
for (index, &src_cache) in src_caches.iter().enumerate() {
if src_cache == self {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("src_caches[{}]", index).into(),
problem: "equals `self`".into(),
vuids: &["VUID-vkMergePipelineCaches-dstCache-00770"],
..Default::default()
});
}));
}
}
@ -277,7 +277,7 @@ impl PipelineCache {
pub unsafe fn merge_unchecked<'a>(
&self,
src_caches: impl IntoIterator<Item = &'a PipelineCache>,
) -> Result<(), RuntimeError> {
) -> Result<(), VulkanError> {
let src_caches_vk: SmallVec<[_; 8]> =
src_caches.into_iter().map(VulkanObject::handle).collect();
@ -289,7 +289,7 @@ impl PipelineCache {
src_caches_vk.as_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
Ok(())
}
@ -358,7 +358,7 @@ impl Default for PipelineCacheCreateInfo {
}
impl PipelineCacheCreateInfo {
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
flags,
initial_data: _,

View File

@ -29,7 +29,7 @@ use crate::{
macros::impl_id_counter,
pipeline::{cache::PipelineCache, layout::PipelineLayout, Pipeline, PipelineBindPoint},
shader::{DescriptorBindingRequirements, ShaderExecution, ShaderStage},
RuntimeError, ValidationError, VulkanError, VulkanObject,
Validated, ValidationError, VulkanError, VulkanObject,
};
use ahash::HashMap;
use std::{ffi::CString, fmt::Debug, mem::MaybeUninit, num::NonZeroU64, ptr, sync::Arc};
@ -59,7 +59,7 @@ impl ComputePipeline {
device: Arc<Device>,
cache: Option<Arc<PipelineCache>>,
create_info: ComputePipelineCreateInfo,
) -> Result<Arc<ComputePipeline>, VulkanError> {
) -> Result<Arc<ComputePipeline>, Validated<VulkanError>> {
Self::validate_new(&device, cache.as_ref().map(AsRef::as_ref), &create_info)?;
unsafe { Ok(Self::new_unchecked(device, cache, create_info)?) }
@ -69,7 +69,7 @@ impl ComputePipeline {
device: &Device,
cache: Option<&PipelineCache>,
create_info: &ComputePipelineCreateInfo,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
// VUID-vkCreateComputePipelines-pipelineCache-parent
if let Some(cache) = &cache {
assert_eq!(device, cache.device().as_ref());
@ -87,7 +87,7 @@ impl ComputePipeline {
device: Arc<Device>,
cache: Option<Arc<PipelineCache>>,
create_info: ComputePipelineCreateInfo,
) -> Result<Arc<ComputePipeline>, RuntimeError> {
) -> Result<Arc<ComputePipeline>, VulkanError> {
let &ComputePipelineCreateInfo {
flags,
ref stage,
@ -170,7 +170,7 @@ impl ComputePipeline {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -312,7 +312,7 @@ impl ComputePipelineCreateInfo {
}
}
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
flags,
ref stage,
@ -342,12 +342,12 @@ impl ComputePipelineCreateInfo {
let entry_point_info = entry_point.info();
if !matches!(entry_point_info.execution, ShaderExecution::Compute) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "stage.entry_point".into(),
problem: "is not a `ShaderStage::Compute` entry point".into(),
vuids: &["VUID-VkComputePipelineCreateInfo-stage-00701"],
..Default::default()
});
}));
}
// TODO: Make sure that all VUIDs are indeed checked.

View File

@ -145,7 +145,7 @@ impl ColorBlendState {
self
}
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
flags,
logic_op,
@ -164,14 +164,14 @@ impl ColorBlendState {
if let Some(logic_op) = logic_op {
if !device.enabled_features().logic_op {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "logic_op".into(),
problem: "is `Some`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"logic_op",
)])]),
vuids: &["VUID-VkPipelineColorBlendStateCreateInfo-logicOpEnable-00606"],
});
}));
}
match logic_op {
@ -188,14 +188,14 @@ impl ColorBlendState {
}
StateMode::Dynamic => {
if !device.enabled_features().extended_dynamic_state2_logic_op {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "logic_op".into(),
problem: "is dynamic".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"extended_dynamic_state2_logic_op",
)])]),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04869"],
});
}));
}
}
}
@ -214,7 +214,7 @@ impl ColorBlendState {
for (index, state) in attachments.iter().enumerate().skip(1) {
if state != first {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: format!(
"`attachments[{}]` does not equal `attachments[0]`",
index
@ -225,7 +225,7 @@ impl ColorBlendState {
)])]),
vuids: &["VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605"],
..Default::default()
});
}));
}
}
}
@ -348,7 +348,7 @@ pub struct ColorBlendAttachmentState {
}
impl ColorBlendAttachmentState {
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
ref blend,
color_write_mask: _,
@ -364,26 +364,26 @@ impl ColorBlendAttachmentState {
match color_write_enable {
StateMode::Fixed(enable) => {
if !enable && !device.enabled_features().color_write_enable {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "color_write_enable".into(),
problem: "is `false`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"color_write_enable",
)])]),
vuids: &["VUID-VkPipelineColorWriteCreateInfoEXT-pAttachments-04801"],
});
}));
}
}
StateMode::Dynamic => {
if !device.enabled_features().color_write_enable {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "color_write_enable".into(),
problem: "is dynamic".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"color_write_enable",
)])]),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04800"],
});
}));
}
}
}
@ -459,7 +459,7 @@ impl AttachmentBlend {
}
}
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
src_color_blend_factor,
dst_color_blend_factor,
@ -525,14 +525,14 @@ impl AttachmentBlend {
| BlendFactor::Src1Alpha
| BlendFactor::OneMinusSrc1Alpha
) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "src_color_blend_factor".into(),
problem: "is `BlendFactor::Src1*`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"dual_src_blend",
)])]),
vuids: &["VUID-VkPipelineColorBlendAttachmentState-srcColorBlendFactor-00608"],
});
}));
}
if matches!(
@ -542,14 +542,14 @@ impl AttachmentBlend {
| BlendFactor::Src1Alpha
| BlendFactor::OneMinusSrc1Alpha
) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "dst_color_blend_factor".into(),
problem: "is `BlendFactor::Src1*`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"dual_src_blend",
)])]),
vuids: &["VUID-VkPipelineColorBlendAttachmentState-dstColorBlendFactor-00609"],
});
}));
}
if matches!(
@ -559,14 +559,14 @@ impl AttachmentBlend {
| BlendFactor::Src1Alpha
| BlendFactor::OneMinusSrc1Alpha
) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "src_alpha_blend_factor".into(),
problem: "is `BlendFactor::Src1*`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"dual_src_blend",
)])]),
vuids: &["VUID-VkPipelineColorBlendAttachmentState-srcAlphaBlendFactor-00610"],
});
}));
}
if matches!(
@ -576,14 +576,14 @@ impl AttachmentBlend {
| BlendFactor::Src1Alpha
| BlendFactor::OneMinusSrc1Alpha
) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "dst_alpha_blend_factor".into(),
problem: "is `BlendFactor::Src1*`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"dual_src_blend",
)])]),
vuids: &["VUID-VkPipelineColorBlendAttachmentState-dstAlphaBlendFactor-00611"],
});
}));
}
}
@ -594,7 +594,7 @@ impl AttachmentBlend {
src_color_blend_factor,
BlendFactor::ConstantAlpha | BlendFactor::OneMinusConstantAlpha
) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "this device is a portability subset device, and \
`src_color_blend_factor` is `BlendFactor::ConstantAlpha` or \
`BlendFactor::OneMinusConstantAlpha`".into(),
@ -603,14 +603,14 @@ impl AttachmentBlend {
)])]),
vuids: &["VUID-VkPipelineColorBlendAttachmentState-constantAlphaColorBlendFactors-04454"],
..Default::default()
});
}));
}
if matches!(
dst_color_blend_factor,
BlendFactor::ConstantAlpha | BlendFactor::OneMinusConstantAlpha
) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "this device is a portability subset device, and \
`dst_color_blend_factor` is `BlendFactor::ConstantAlpha` or \
`BlendFactor::OneMinusConstantAlpha`".into(),
@ -619,7 +619,7 @@ impl AttachmentBlend {
)])]),
vuids: &["VUID-VkPipelineColorBlendAttachmentState-constantAlphaColorBlendFactors-04455"],
..Default::default()
});
}));
}
}

View File

@ -87,7 +87,7 @@ impl DepthStencilState {
}
}
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
flags,
ref depth,
@ -112,7 +112,7 @@ impl DepthStencilState {
if let Some(depth_bounds_state) = depth_bounds {
if !device.enabled_features().depth_bounds {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "depth_bounds".into(),
problem: "is `Some`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
@ -121,7 +121,7 @@ impl DepthStencilState {
vuids: &[
"VUID-VkPipelineDepthStencilStateCreateInfo-depthBoundsTestEnable-00598",
],
});
}));
}
depth_bounds_state
@ -198,7 +198,7 @@ pub struct DepthState {
}
impl DepthState {
pub(crate) fn validate(self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(self, device: &Device) -> Result<(), Box<ValidationError>> {
let Self {
enable_dynamic,
write_enable,
@ -209,7 +209,7 @@ impl DepthState {
&& !(device.api_version() >= Version::V1_3
|| device.enabled_features().extended_dynamic_state)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "enable_dynamic".into(),
problem: "is `true`".into(),
requires_one_of: RequiresOneOf(&[
@ -218,7 +218,7 @@ impl DepthState {
]),
// vuids?
..Default::default()
});
}));
}
match write_enable {
@ -227,7 +227,7 @@ impl DepthState {
if !(device.api_version() >= Version::V1_3
|| device.enabled_features().extended_dynamic_state)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "write_enable".into(),
problem: "is dynamic".into(),
requires_one_of: RequiresOneOf(&[
@ -236,7 +236,7 @@ impl DepthState {
]),
// vuids?
..Default::default()
});
}));
}
}
}
@ -257,7 +257,7 @@ impl DepthState {
if !(device.api_version() >= Version::V1_3
|| device.enabled_features().extended_dynamic_state)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "compare_op".into(),
problem: "is dynamic".into(),
requires_one_of: RequiresOneOf(&[
@ -266,7 +266,7 @@ impl DepthState {
]),
// vuids?
..Default::default()
});
}));
}
}
}
@ -310,7 +310,7 @@ pub struct DepthBoundsState {
}
impl DepthBoundsState {
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
enable_dynamic,
ref bounds,
@ -320,7 +320,7 @@ impl DepthBoundsState {
&& !(device.api_version() >= Version::V1_3
|| device.enabled_features().extended_dynamic_state)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "enable_dynamic".into(),
problem: "is `true`".into(),
requires_one_of: RequiresOneOf(&[
@ -329,31 +329,31 @@ impl DepthBoundsState {
]),
// vuids?
..Default::default()
});
}));
}
if let StateMode::Fixed(bounds) = bounds {
if !device.enabled_extensions().ext_depth_range_unrestricted {
if !(0.0..1.0).contains(bounds.start()) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "bounds.start".into(),
problem: "is not between 0.0 and 1.0 inclusive".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[
Requires::DeviceExtension("ext_depth_range_unrestricted"),
])]),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-02510"],
});
}));
}
if !(0.0..1.0).contains(bounds.end()) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "bounds.end".into(),
problem: "is not between 0.0 and 1.0 inclusive".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[
Requires::DeviceExtension("ext_depth_range_unrestricted"),
])]),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-02510"],
});
}));
}
}
}
@ -397,7 +397,7 @@ pub struct StencilState {
}
impl StencilState {
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &StencilState {
enable_dynamic,
ref front,
@ -408,7 +408,7 @@ impl StencilState {
&& !(device.api_version() >= Version::V1_3
|| device.enabled_features().extended_dynamic_state)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "enable_dynamic".into(),
problem: "is `true`".into(),
requires_one_of: RequiresOneOf(&[
@ -417,7 +417,7 @@ impl StencilState {
]),
// vuids?
..Default::default()
});
}));
}
match (front.ops, back.ops) {
@ -433,7 +433,7 @@ impl StencilState {
if !(device.api_version() >= Version::V1_3
|| device.enabled_features().extended_dynamic_state)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`front.ops` and `back.ops` are dynamic".into(),
requires_one_of: RequiresOneOf(&[
RequiresAllOf(&[Requires::APIVersion(Version::V1_3)]),
@ -441,17 +441,17 @@ impl StencilState {
]),
// vuids?
..Default::default()
});
}));
}
}
_ => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`front.ops` and `back.ops` are \
not both fixed or both dynamic"
.into(),
// vuids?
..Default::default()
});
}));
}
}
@ -459,39 +459,39 @@ impl StencilState {
(front.compare_mask, back.compare_mask),
(StateMode::Fixed(_), StateMode::Fixed(_)) | (StateMode::Dynamic, StateMode::Dynamic)
) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`front.compare_mask` and `back.compare_mask` are \
not both fixed or both dynamic"
.into(),
// vuids?
..Default::default()
});
}));
}
if !matches!(
(front.write_mask, back.write_mask),
(StateMode::Fixed(_), StateMode::Fixed(_)) | (StateMode::Dynamic, StateMode::Dynamic)
) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`front.write_mask` and `back.write_mask` are \
not both fixed or both dynamic"
.into(),
// vuids?
..Default::default()
});
}));
}
if !matches!(
(front.reference, back.reference),
(StateMode::Fixed(_), StateMode::Fixed(_)) | (StateMode::Dynamic, StateMode::Dynamic)
) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`front.reference` and `back.reference` are \
not both fixed or both dynamic"
.into(),
// vuids?
..Default::default()
});
}));
}
Ok(())
@ -560,7 +560,7 @@ pub struct StencilOps {
}
impl StencilOps {
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
fail_op,
pass_op,

View File

@ -46,7 +46,7 @@ impl DiscardRectangleState {
}
}
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
mode,
ref rectangles,
@ -67,14 +67,14 @@ impl DiscardRectangleState {
};
if discard_rectangle_count > properties.max_discard_rectangles.unwrap() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "rectangles".into(),
problem: "the length exceeds the `max_discard_rectangles` limit".into(),
vuids: &[
"VUID-VkPipelineDiscardRectangleStateCreateInfoEXT-discardRectangleCount-00582",
],
..Default::default()
});
}));
}
Ok(())

View File

@ -84,7 +84,7 @@ impl InputAssemblyState {
self
}
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
topology,
primitive_restart_enable,
@ -106,7 +106,7 @@ impl InputAssemblyState {
if device.enabled_extensions().khr_portability_subset
&& !device.enabled_features().triangle_fans
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "this device is a portability subset device, and \
`topology` is `PrimitiveTopology::TriangleFan`"
.into(),
@ -115,7 +115,7 @@ impl InputAssemblyState {
])]),
vuids: &["VUID-VkPipelineInputAssemblyStateCreateInfo-triangleFans-04452"],
..Default::default()
});
}));
}
}
PrimitiveTopology::LineListWithAdjacency
@ -123,7 +123,7 @@ impl InputAssemblyState {
| PrimitiveTopology::TriangleListWithAdjacency
| PrimitiveTopology::TriangleStripWithAdjacency => {
if !device.enabled_features().geometry_shader {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "topology".into(),
problem: "is `PrimitiveTopology::*WithAdjacency`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[
@ -132,12 +132,12 @@ impl InputAssemblyState {
vuids: &[
"VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00429",
],
});
}));
}
}
PrimitiveTopology::PatchList => {
if !device.enabled_features().tessellation_shader {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "topology".into(),
problem: "is `PrimitiveTopology::PatchList`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[
@ -146,7 +146,7 @@ impl InputAssemblyState {
vuids: &[
"VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00430",
],
});
}));
}
}
_ => (),
@ -165,7 +165,7 @@ impl InputAssemblyState {
if !(device.api_version() >= Version::V1_3
|| device.enabled_features().extended_dynamic_state)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "topology".into(),
problem: "is dynamic".into(),
requires_one_of: RequiresOneOf(&[
@ -174,7 +174,7 @@ impl InputAssemblyState {
]),
// vuids?
..Default::default()
});
}));
}
}
}
@ -191,7 +191,7 @@ impl InputAssemblyState {
| PrimitiveTopology::TriangleListWithAdjacency,
) => {
if !device.enabled_features().primitive_topology_list_restart {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`topology` is `PrimitiveTopology::*List`, and \
`primitive_restart_enable` is `true`"
.into(),
@ -200,7 +200,7 @@ impl InputAssemblyState {
])]),
vuids: &["VUID-VkPipelineInputAssemblyStateCreateInfo-topology-06252"],
..Default::default()
});
}));
}
}
PartialStateMode::Fixed(PrimitiveTopology::PatchList) => {
@ -208,7 +208,7 @@ impl InputAssemblyState {
.enabled_features()
.primitive_topology_patch_list_restart
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`topology` is `PrimitiveTopology::PatchList`, and \
`primitive_restart_enable` is `true`"
.into(),
@ -217,7 +217,7 @@ impl InputAssemblyState {
])]),
vuids: &["VUID-VkPipelineInputAssemblyStateCreateInfo-topology-06253"],
..Default::default()
});
}));
}
}
_ => (),
@ -228,7 +228,7 @@ impl InputAssemblyState {
if !(device.api_version() >= Version::V1_3
|| device.enabled_features().extended_dynamic_state2)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "primitive_restart_enable".into(),
problem: "is dynamic".into(),
requires_one_of: RequiresOneOf(&[
@ -237,7 +237,7 @@ impl InputAssemblyState {
]),
// vuids?
..Default::default()
});
}));
}
}
}

View File

@ -93,8 +93,7 @@ use crate::{
DescriptorBindingRequirements, FragmentShaderExecution, FragmentTestsStages,
ShaderExecution, ShaderScalarType, ShaderStage, ShaderStages,
},
Requires, RequiresAllOf, RequiresOneOf, RuntimeError, ValidationError, VulkanError,
VulkanObject,
Requires, RequiresAllOf, RequiresOneOf, Validated, ValidationError, VulkanError, VulkanObject,
};
use ahash::HashMap;
use smallvec::SmallVec;
@ -154,7 +153,7 @@ impl GraphicsPipeline {
device: Arc<Device>,
cache: Option<Arc<PipelineCache>>,
create_info: GraphicsPipelineCreateInfo,
) -> Result<Arc<Self>, VulkanError> {
) -> Result<Arc<Self>, Validated<VulkanError>> {
Self::validate_new(&device, cache.as_ref().map(AsRef::as_ref), &create_info)?;
unsafe { Ok(Self::new_unchecked(device, cache, create_info)?) }
@ -164,7 +163,7 @@ impl GraphicsPipeline {
device: &Device,
_cache: Option<&PipelineCache>,
create_info: &GraphicsPipelineCreateInfo,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
create_info
.validate(device)
.map_err(|err| err.add_context("create_info"))?;
@ -177,7 +176,7 @@ impl GraphicsPipeline {
device: Arc<Device>,
cache: Option<Arc<PipelineCache>>,
create_info: GraphicsPipelineCreateInfo,
) -> Result<Arc<Self>, RuntimeError> {
) -> Result<Arc<Self>, VulkanError> {
let &GraphicsPipelineCreateInfo {
flags,
ref stages,
@ -1141,7 +1140,7 @@ impl GraphicsPipeline {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -1880,7 +1879,7 @@ impl GraphicsPipelineCreateInfo {
}
}
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
flags,
ref stages,
@ -1926,7 +1925,7 @@ impl GraphicsPipelineCreateInfo {
let stage_flag = ShaderStages::from(stage_enum);
if stages_present.intersects(stage_flag) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "stages".into(),
problem: format!(
"contains more than one element whose stage is \
@ -1936,7 +1935,7 @@ impl GraphicsPipelineCreateInfo {
.into(),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-stage-06897"],
..Default::default()
});
}));
}
const PRIMITIVE_SHADING_STAGES: ShaderStages = ShaderStages::VERTEX
@ -1950,13 +1949,13 @@ impl GraphicsPipelineCreateInfo {
|| stage_flag.intersects(MESH_SHADING_STAGES)
&& stages_present.intersects(PRIMITIVE_SHADING_STAGES)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "stages".into(),
problem: "contains both primitive shading stages and mesh shading stages"
.into(),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-pStages-02095"],
..Default::default()
});
}));
}
let stage_slot = match stage_enum {
@ -1966,12 +1965,12 @@ impl GraphicsPipelineCreateInfo {
ShaderStage::Geometry => &mut geometry_stage,
ShaderStage::Fragment => &mut fragment_stage,
_ => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("stages[{}]", stage_index).into(),
problem: "is not a pre-rasterization or fragment shader stage".into(),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-pStages-06896"],
..Default::default()
});
}));
}
};
@ -1991,24 +1990,24 @@ impl GraphicsPipelineCreateInfo {
need_pre_rasterization_shader_state,
) {
(true, false) => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the pipeline is not being created with \
pre-rasterization shader state, but \
`rasterization_state` is `Some`"
.into(),
// vuids?
..Default::default()
});
}));
}
(false, true) => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the pipeline is being created with \
pre-rasterization shader state, but \
`rasterization_state` is `None`"
.into(),
// vuids?
..Default::default()
});
}));
}
_ => (),
}
@ -2032,24 +2031,24 @@ impl GraphicsPipelineCreateInfo {
match (vertex_stage.is_some(), need_pre_rasterization_shader_state) {
(true, false) => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the pipeline is not being created with \
pre-rasterization shader state, but `stages` contains a \
`ShaderStage::Vertex` stage"
.into(),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-pStages-06895"],
..Default::default()
});
}));
}
(false, true) => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the pipeline is being created with \
pre-rasterization shader state, but `stages` does not contain a \
`ShaderStage::Vertex` stage"
.into(),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-stage-02096"],
..Default::default()
});
}));
}
_ => (),
}
@ -2059,14 +2058,14 @@ impl GraphicsPipelineCreateInfo {
need_pre_rasterization_shader_state,
) {
(true, false) => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the pipeline is not being created with \
pre-rasterization shader state, but `stages` contains a \
`ShaderStage::TessellationControl` stage"
.into(),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-pStages-06895"],
..Default::default()
});
}));
}
(false, true) => (),
_ => (),
@ -2077,14 +2076,14 @@ impl GraphicsPipelineCreateInfo {
need_pre_rasterization_shader_state,
) {
(true, false) => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the pipeline is not being created with \
pre-rasterization shader state, but `stages` contains a \
`ShaderStage::TessellationEvaluation` stage"
.into(),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-pStages-06895"],
..Default::default()
});
}));
}
(false, true) => (),
_ => (),
@ -2093,25 +2092,25 @@ impl GraphicsPipelineCreateInfo {
if stages_present.intersects(ShaderStages::TESSELLATION_CONTROL)
&& !stages_present.intersects(ShaderStages::TESSELLATION_EVALUATION)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "stages".into(),
problem: "contains a `ShaderStage::TessellationControl` stage, but not a \
`ShaderStage::TessellationEvaluation` stage"
.into(),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-pStages-00729"],
..Default::default()
});
}));
} else if stages_present.intersects(ShaderStages::TESSELLATION_EVALUATION)
&& !stages_present.intersects(ShaderStages::TESSELLATION_CONTROL)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "stages".into(),
problem: "contains a `ShaderStage::TessellationEvaluation` stage, but not a \
`ShaderStage::TessellationControl` stage"
.into(),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-pStages-00730"],
..Default::default()
});
}));
}
match (
@ -2119,14 +2118,14 @@ impl GraphicsPipelineCreateInfo {
need_pre_rasterization_shader_state,
) {
(true, false) => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the pipeline is not being created with \
pre-rasterization shader state, but `stages` contains a \
`ShaderStage::Geometry` stage"
.into(),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-pStages-06895"],
..Default::default()
});
}));
}
(false, true) => (),
_ => (),
@ -2134,14 +2133,14 @@ impl GraphicsPipelineCreateInfo {
match (fragment_stage.is_some(), need_fragment_shader_state) {
(true, false) => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the pipeline is not being created with \
fragment shader state, but `stages` contains a \
`ShaderStage::Geometry` stage"
.into(),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-pStages-06894"],
..Default::default()
});
}));
}
(false, true) => (),
_ => (),
@ -2149,46 +2148,46 @@ impl GraphicsPipelineCreateInfo {
match (vertex_input_state.is_some(), need_vertex_input_state) {
(true, false) => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the pipeline is not being created with \
vertex input state, but \
`vertex_input_state` is `Some`"
.into(),
..Default::default()
});
}));
}
(false, true) => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the pipeline is being created with \
vertex input state, but \
`vertex_input_state` is `None`"
.into(),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-pStages-02097"],
..Default::default()
});
}));
}
_ => (),
}
match (input_assembly_state.is_some(), need_vertex_input_state) {
(true, false) => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the pipeline is not being created with \
vertex input state, but \
`input_assembly_state` is `Some`"
.into(),
..Default::default()
});
}));
}
(false, true) => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the pipeline is being created with \
vertex input state, but \
`input_assembly_state` is `None`"
.into(),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-pStages-02098"],
..Default::default()
});
}));
}
_ => (),
}
@ -2201,17 +2200,17 @@ impl GraphicsPipelineCreateInfo {
),
) {
(true, false) => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the pipeline is not being created with \
pre-rasterization state, or \
`stages` does not contain tessellation shader stages, but \
`tessellation_state` is `Some`"
.into(),
..Default::default()
});
}));
}
(false, true) => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the pipeline is being created with \
pre-rasterization state, and \
`stages` contains tessellation shader stages, but \
@ -2219,7 +2218,7 @@ impl GraphicsPipelineCreateInfo {
.into(),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-pStages-00731"],
..Default::default()
});
}));
}
_ => (),
}
@ -2234,17 +2233,17 @@ impl GraphicsPipelineCreateInfo {
!= StateMode::Fixed(true),
) {
(true, false) => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the pipeline is not being created with \
pre-rasterization state, or \
`rasterization_state.rasterization_discard_enable` is `true`, but \
`viewport_state` is `Some`"
.into(),
..Default::default()
});
}));
}
(false, true) => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the pipeline is being created with \
pre-rasterization state, and \
`rasterization_state.rasterization_discard_enable` is `false` \
@ -2255,30 +2254,30 @@ impl GraphicsPipelineCreateInfo {
"VUID-VkGraphicsPipelineCreateInfo-pViewportState-04892",
],
..Default::default()
});
}));
}
_ => (),
}
match (multisample_state.is_some(), need_fragment_output_state) {
(true, false) => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the pipeline is not being created with \
fragment output state, but \
`multisample_state` is `Some`"
.into(),
..Default::default()
});
}));
}
(false, true) => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the pipeline is being created with \
fragment output state, but \
`multisample_state` is `None`"
.into(),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-rasterizerDiscardEnable-00751"],
..Default::default()
});
}));
}
_ => (),
}
@ -2298,17 +2297,17 @@ impl GraphicsPipelineCreateInfo {
},
) {
(true, false) => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the pipeline is being created with \
fragment output state, and \
`subpass` does not have a depth/stencil attachment, but \
`depth_stencil_state` is `Some`"
.into(),
..Default::default()
});
}));
}
(false, true) => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the pipeline is not being created with \
fragment output state, or \
`subpass` has a depth/stencil attachment, but \
@ -2320,7 +2319,7 @@ impl GraphicsPipelineCreateInfo {
"VUID-VkGraphicsPipelineCreateInfo-renderPass-06053",
],
..Default::default()
});
}));
}
_ => (),
}
@ -2339,17 +2338,17 @@ impl GraphicsPipelineCreateInfo {
},
) {
(true, false) => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the pipeline is not being created with \
fragment output state, or \
`subpass` does not have any color attachments, but \
`color_blend_state` is `Some`"
.into(),
..Default::default()
});
}));
}
(false, true) => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the pipeline is being created with \
fragment output state, and \
`subpass` has a color attachment, but \
@ -2360,7 +2359,7 @@ impl GraphicsPipelineCreateInfo {
"VUID-VkGraphicsPipelineCreateInfo-renderPass-06054",
],
..Default::default()
});
}));
}
_ => (),
}
@ -2372,23 +2371,23 @@ impl GraphicsPipelineCreateInfo {
|| need_fragment_output_state,
) {
(true, false) => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the pipeline is not being created with \
pre-rasterization, fragment shader or fragment output state, but \
`subpass` is `Some`"
.into(),
..Default::default()
});
}));
}
(false, true) => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the pipeline is being created with \
pre-rasterization, fragment shader or fragment output state, but \
`subpass` is `None`"
.into(),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-renderPass-06575"],
..Default::default()
});
}));
}
_ => (),
}
@ -2398,14 +2397,14 @@ impl GraphicsPipelineCreateInfo {
need_pre_rasterization_shader_state,
) {
(true, false) => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the pipeline is not being created with \
pre-rasterization state, but \
`discard_rectangle_state` is `Some`"
.into(),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04058"],
..Default::default()
});
}));
}
(false, true) => (),
_ => (),
@ -2461,7 +2460,7 @@ impl GraphicsPipelineCreateInfo {
if let Err(err) = (input.entry_point.info().input_interface)
.matches(&output.entry_point.info().output_interface)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "stages".into(),
problem: format!(
"the output interface of the `ShaderStage::{:?}` stage does not \
@ -2476,7 +2475,7 @@ impl GraphicsPipelineCreateInfo {
"VUID-VkGraphicsPipelineCreateInfo-None-04889",
],
..Default::default()
});
}));
}
}
@ -2566,7 +2565,7 @@ impl GraphicsPipelineCreateInfo {
| ShaderStages::TESSELLATION_EVALUATION,
) && !device.enabled_features().multiview_tessellation_shader
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`stages` contains tessellation shaders, and \
`subpass` has a non-zero `view_mask`"
.into(),
@ -2575,13 +2574,13 @@ impl GraphicsPipelineCreateInfo {
])]),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-renderPass-06047"],
..Default::default()
});
}));
}
if stages_present.intersects(ShaderStages::GEOMETRY)
&& !device.enabled_features().multiview_geometry_shader
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`stages` contains a geometry shader, and \
`subpass` has a non-zero `view_mask`"
.into(),
@ -2590,20 +2589,20 @@ impl GraphicsPipelineCreateInfo {
])]),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-renderPass-06048"],
..Default::default()
});
}));
}
}
}
PipelineSubpassType::BeginRendering(rendering_info) => {
if !device.enabled_features().dynamic_rendering {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "subpass".into(),
problem: "is `PipelineRenderPassType::BeginRendering`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"dynamic_rendering",
)])]),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-dynamicRendering-06576"],
});
}));
}
rendering_info
@ -2624,7 +2623,7 @@ impl GraphicsPipelineCreateInfo {
| ShaderStages::TESSELLATION_EVALUATION,
) && !device.enabled_features().multiview_tessellation_shader
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`stages` contains tessellation shaders, and \
`subpass.view_mask` is not 0"
.into(),
@ -2633,13 +2632,13 @@ impl GraphicsPipelineCreateInfo {
])]),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-renderPass-06057"],
..Default::default()
});
}));
}
if stages_present.intersects(ShaderStages::GEOMETRY)
&& !device.enabled_features().multiview_geometry_shader
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`stages` contains a geometry shader, and \
`subpass.view_mask` is not 0"
.into(),
@ -2648,7 +2647,7 @@ impl GraphicsPipelineCreateInfo {
])]),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-renderPass-06058"],
..Default::default()
});
}));
}
}
}
@ -2657,14 +2656,14 @@ impl GraphicsPipelineCreateInfo {
if let Some(discard_rectangle_state) = discard_rectangle_state {
if !device.enabled_extensions().ext_discard_rectangles {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "discard_rectangle_state".into(),
problem: "is `Some`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceExtension(
"ext_discard_rectangles",
)])]),
..Default::default()
});
}));
}
discard_rectangle_state
@ -2686,7 +2685,7 @@ impl GraphicsPipelineCreateInfo {
let attribute_desc = match vertex_input_state.attributes.get(&location) {
Some(attribute_desc) => attribute_desc,
None => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: format!(
"the vertex shader has an input variable with location {0}, but \
`vertex_input_state.attributes` does not contain {0}",
@ -2695,7 +2694,7 @@ impl GraphicsPipelineCreateInfo {
.into(),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-Input-07905"],
..Default::default()
});
}));
}
};
@ -2720,7 +2719,7 @@ impl GraphicsPipelineCreateInfo {
) | (ShaderScalarType::Sint, NumericType::SINT)
| (ShaderScalarType::Uint, NumericType::UINT)
) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: format!(
"`vertex_input_state.attributes[{}].format` has a different \
scalar type than the vertex shader input variable with \
@ -2730,7 +2729,7 @@ impl GraphicsPipelineCreateInfo {
.into(),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-Input-07905"],
..Default::default()
});
}));
}
}
}
@ -2764,13 +2763,13 @@ impl GraphicsPipelineCreateInfo {
if let PartialStateMode::Fixed(topology) = input_assembly_state.topology {
if !input.is_compatible_with(topology) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`input_assembly_state.topology` is not compatible with the \
input topology of the geometry shader"
.into(),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-pStages-00738"],
..Default::default()
});
}));
}
}
}
@ -2782,12 +2781,12 @@ impl GraphicsPipelineCreateInfo {
match subpass {
PipelineSubpassType::BeginRenderPass(subpass) => {
if !subpass.is_compatible_with(&entry_point_info.output_interface) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`subpass` is not compatible with the \
output interface of the fragment shader"
.into(),
..Default::default()
});
}));
}
}
PipelineSubpassType::BeginRendering(_) => {
@ -2808,13 +2807,13 @@ impl GraphicsPipelineCreateInfo {
PartialStateMode::Dynamic(PrimitiveTopologyClass::Patch)
| PartialStateMode::Fixed(PrimitiveTopology::PatchList)
) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`stages` contains tessellation shaders, but \
`input_assembly_state.topology` is not `PrimitiveTopology::PatchList`"
.into(),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-pStages-00736"],
..Default::default()
});
}));
}
}
@ -2833,7 +2832,7 @@ impl GraphicsPipelineCreateInfo {
)
&& front_reference != back_reference
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "this device is a portability subset device, \
`rasterization_state.cull_mode` is `CullMode::None`, and \
`depth_stencil_state.stencil.front.reference` does not equal \
@ -2843,7 +2842,7 @@ impl GraphicsPipelineCreateInfo {
)])]),
vuids: &["VUID-VkPipelineDepthStencilStateCreateInfo-separateStencilMaskRef-04453"],
..Default::default()
});
}));
}
}
}
@ -2854,14 +2853,14 @@ impl GraphicsPipelineCreateInfo {
PipelineSubpassType::BeginRenderPass(subpass) => {
if let Some(samples) = subpass.num_samples() {
if multisample_state.rasterization_samples != samples {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`multisample_state.rasterization_samples` does not \
equal the number of samples in the color and depth/stencil \
attachments of `subpass`"
.into(),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-subpass-00757"],
..Default::default()
});
}));
}
}
@ -2899,13 +2898,13 @@ impl GraphicsPipelineCreateInfo {
};
if !has_depth_attachment {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`depth_stencil_state.depth` is `Some`, but `subpass` does not \
have a depth attachment"
.into(),
// vuids?
..Default::default()
});
}));
}
if let StateMode::Fixed(true) = depth_state.write_enable {
@ -2929,14 +2928,14 @@ impl GraphicsPipelineCreateInfo {
.intersects(ImageAspects::DEPTH)
})
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`depth_stencil_state.depth.write_enable` is `true`, \
but `subpass` does not have a depth attachment whose \
layout for the depth aspect allows writing"
.into(),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-renderPass-06039"],
..Default::default()
});
}));
}
}
PipelineSubpassType::BeginRendering(_) => {
@ -2966,13 +2965,13 @@ impl GraphicsPipelineCreateInfo {
};
if !has_stencil_attachment {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`depth_stencil_state.stencil` is `Some`, but `subpass` does not \
have a stencil attachment"
.into(),
// vuids?
..Default::default()
});
}));
}
}
}
@ -2988,7 +2987,7 @@ impl GraphicsPipelineCreateInfo {
};
if color_attachment_count != color_blend_state.attachments.len() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the length of `color_blend_state.attachments` does not equal the \
number of color attachments in `subpass`"
.into(),
@ -2998,7 +2997,7 @@ impl GraphicsPipelineCreateInfo {
"VUID-VkGraphicsPipelineCreateInfo-renderPass-06060",
],
..Default::default()
});
}));
}
for (attachment_index, state) in color_blend_state.attachments.iter().enumerate() {
@ -3025,7 +3024,7 @@ impl GraphicsPipelineCreateInfo {
.potential_format_features()
.intersects(FormatFeatures::COLOR_ATTACHMENT_BLEND)
}) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: format!(
"`color_blend_state.attachments[{}].blend` is `Some`, but \
the format features of that color attachment in `subpass` \
@ -3038,7 +3037,7 @@ impl GraphicsPipelineCreateInfo {
"VUID-VkGraphicsPipelineCreateInfo-renderPass-06062",
],
..Default::default()
});
}));
}
}
}

View File

@ -75,7 +75,7 @@ impl MultisampleState {
}
}
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
rasterization_samples,
sample_shading,
@ -97,35 +97,35 @@ impl MultisampleState {
if let Some(min_sample_shading) = sample_shading {
if !device.enabled_features().sample_rate_shading {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "min_sample_shading".into(),
problem: "is `Some`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"sample_rate_shading",
)])]),
vuids: &["VUID-VkPipelineMultisampleStateCreateInfo-sampleShadingEnable-00784"],
});
}));
}
if !(0.0..=1.0).contains(&min_sample_shading) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "min_sample_shading".into(),
problem: "is not between 0.0 and 1.0 inclusive".into(),
vuids: &["VUID-VkPipelineMultisampleStateCreateInfo-minSampleShading-00786"],
..Default::default()
});
}));
}
}
if alpha_to_one_enable && !device.enabled_features().alpha_to_one {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "alpha_to_one_enable".into(),
problem: "is `true`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"alpha_to_one",
)])]),
vuids: &["VUID-VkPipelineMultisampleStateCreateInfo-alphaToOneEnable-00785"],
});
}));
}
Ok(())

View File

@ -140,7 +140,7 @@ impl RasterizationState {
self
}
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
depth_clamp_enable,
rasterizer_discard_enable,
@ -173,25 +173,25 @@ impl RasterizationState {
})?;
if depth_clamp_enable && !device.enabled_features().depth_clamp {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "depth_clamp_enable".into(),
problem: "is `true`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"depth_clamp",
)])]),
vuids: &["VUID-VkPipelineRasterizationStateCreateInfo-depthClampEnable-00782"],
});
}));
}
if polygon_mode != PolygonMode::Fill && !device.enabled_features().fill_mode_non_solid {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "polygon_mode".into(),
problem: "is not `PolygonMode::Fill`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"fill_mode_non_solid",
)])]),
vuids: &["VUID-VkPipelineRasterizationStateCreateInfo-polygonMode-01507"],
});
}));
}
match rasterizer_discard_enable {
@ -200,7 +200,7 @@ impl RasterizationState {
&& !device.enabled_features().point_polygons
&& polygon_mode == PolygonMode::Point
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "this device is a portability subset device, \
`rasterizer_discard_enable` is `false`, and \
`polygon_mode` is `PolygonMode::Point`"
@ -210,14 +210,14 @@ impl RasterizationState {
)])]),
vuids: &["VUID-VkPipelineRasterizationStateCreateInfo-pointPolygons-04458"],
..Default::default()
});
}));
}
}
StateMode::Dynamic => {
if !(device.api_version() >= Version::V1_3
|| device.enabled_features().extended_dynamic_state2)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "rasterizer_discard_enable".into(),
problem: "is dynamic".into(),
requires_one_of: RequiresOneOf(&[
@ -226,7 +226,7 @@ impl RasterizationState {
]),
// vuids?
..Default::default()
});
}));
}
}
_ => (),
@ -246,7 +246,7 @@ impl RasterizationState {
if !(device.api_version() >= Version::V1_3
|| device.enabled_features().extended_dynamic_state)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "cull_mode".into(),
problem: "is dynamic".into(),
requires_one_of: RequiresOneOf(&[
@ -255,7 +255,7 @@ impl RasterizationState {
]),
// vuids?
..Default::default()
});
}));
}
}
}
@ -274,7 +274,7 @@ impl RasterizationState {
if !(device.api_version() >= Version::V1_3
|| device.enabled_features().extended_dynamic_state)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "front_face".into(),
problem: "is dynamic".into(),
requires_one_of: RequiresOneOf(&[
@ -283,7 +283,7 @@ impl RasterizationState {
]),
// vuids?
..Default::default()
});
}));
}
}
}
@ -298,7 +298,7 @@ impl RasterizationState {
&& !(device.api_version() >= Version::V1_3
|| device.enabled_features().extended_dynamic_state2)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "depth_bias.enable_dynamic".into(),
problem: "is `true`".into(),
requires_one_of: RequiresOneOf(&[
@ -307,84 +307,84 @@ impl RasterizationState {
]),
// vuids?
..Default::default()
});
}));
}
if matches!(bias, StateMode::Fixed(bias) if bias.clamp != 0.0)
&& !device.enabled_features().depth_bias_clamp
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "depth_bias.bias.clamp".into(),
problem: "is not 0.0".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"depth_bias_clamp",
)])]),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00754"],
});
}));
}
}
if matches!(line_width, StateMode::Fixed(line_width) if line_width != 1.0)
&& !device.enabled_features().wide_lines
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "line_width".into(),
problem: "is not 1.0".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"wide_lines",
)])]),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00749"],
});
}));
}
if line_rasterization_mode != LineRasterizationMode::Default {
if !device.enabled_extensions().ext_line_rasterization {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "line_rasterization_mode".into(),
problem: "`is not `LineRasterizationMode::Default`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceExtension(
"ext_line_rasterization",
)])]),
..Default::default()
});
}));
}
match line_rasterization_mode {
LineRasterizationMode::Default => (),
LineRasterizationMode::Rectangular => {
if !device.enabled_features().rectangular_lines {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "line_rasterization_mode".into(),
problem: "is `LineRasterizationMode::Rectangular`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"rectangular_lines",
)])]),
vuids: &["VUID-VkPipelineRasterizationLineStateCreateInfoEXT-lineRasterizationMode-02768"],
});
}));
}
}
LineRasterizationMode::Bresenham => {
if !device.enabled_features().bresenham_lines {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "line_rasterization_mode".into(),
problem: "is `LineRasterizationMode::Bresenham`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"bresenham_lines",
)])]),
vuids: &["VUID-VkPipelineRasterizationLineStateCreateInfoEXT-lineRasterizationMode-02769"],
});
}));
}
}
LineRasterizationMode::RectangularSmooth => {
if !device.enabled_features().smooth_lines {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "line_rasterization_mode".into(),
problem: "is `LineRasterizationMode::RectangularSmooth`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"smooth_lines",
)])]),
vuids: &["VUID-VkPipelineRasterizationLineStateCreateInfoEXT-lineRasterizationMode-02770"],
});
}));
}
}
}
@ -392,33 +392,33 @@ impl RasterizationState {
if let Some(line_stipple) = line_stipple {
if !device.enabled_extensions().ext_line_rasterization {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "line_stipple".into(),
problem: "is `Some`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceExtension(
"ext_line_rasterization",
)])]),
..Default::default()
});
}));
}
if let StateMode::Fixed(line_stipple) = line_stipple {
let &LineStipple { factor, pattern: _ } = line_stipple;
if !(1..=256).contains(&factor) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "line_stipple.factor".into(),
problem: "is not between 1 and 256 inclusive".into(),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-stippledLineEnable-02767"],
..Default::default()
});
}));
}
}
match line_rasterization_mode {
LineRasterizationMode::Default => {
if !device.enabled_features().stippled_rectangular_lines {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`line_stipple` is `Some`, and \
`line_rasterization_mode` is \
`LineRasterizationMode::Default`".into(),
@ -427,23 +427,23 @@ impl RasterizationState {
)])]),
vuids: &["VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02774"],
..Default::default()
});
}));
}
if !properties.strict_lines {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`line_stipple` is `Some`, and \
`line_rasterization_mode` is \
`LineRasterizationMode::Default`, \
but the `strict_lines` property is `false`".into(),
vuids: &["VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02774"],
..Default::default()
});
}));
}
}
LineRasterizationMode::Rectangular => {
if !device.enabled_features().stippled_rectangular_lines {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`line_stipple` is `Some`, and \
`line_rasterization_mode` is \
`LineRasterizationMode::Rectangular`".into(),
@ -452,12 +452,12 @@ impl RasterizationState {
)])]),
vuids: &["VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02771"],
..Default::default()
});
}));
}
}
LineRasterizationMode::Bresenham => {
if !device.enabled_features().stippled_bresenham_lines {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`line_stipple` is `Some`, and \
`line_rasterization_mode` is \
`LineRasterizationMode::Bresenham`".into(),
@ -466,12 +466,12 @@ impl RasterizationState {
)])]),
vuids: &["VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02772"],
..Default::default()
});
}));
}
}
LineRasterizationMode::RectangularSmooth => {
if !device.enabled_features().stippled_smooth_lines {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`line_stipple` is `Some`, and \
`line_rasterization_mode` is \
`LineRasterizationMode::RectangularSmooth`".into(),
@ -480,7 +480,7 @@ impl RasterizationState {
)])]),
vuids: &["VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02773"],
..Default::default()
});
}));
}
}
}

View File

@ -151,7 +151,7 @@ impl PipelineRenderingCreateInfo {
}
}
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
view_mask,
ref color_attachment_formats,
@ -163,25 +163,25 @@ impl PipelineRenderingCreateInfo {
let properties = device.physical_device().properties();
if view_mask != 0 && !device.enabled_features().multiview {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "view_mask".into(),
problem: "is not zero".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature("multiview")])]),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-multiview-06577"],
});
}));
}
let view_count = u32::BITS - view_mask.leading_zeros();
if view_count > properties.max_multiview_view_count.unwrap_or(0) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "view_mask".into(),
problem: "the number of views exceeds the \
`max_multiview_view_count` limit"
.into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature("multiview")])]),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-renderPass-06578"],
});
}));
}
for (attachment_index, format) in color_attachment_formats
@ -203,14 +203,14 @@ impl PipelineRenderingCreateInfo {
.potential_format_features()
.intersects(FormatFeatures::COLOR_ATTACHMENT)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("color_attachment_formats[{}]", attachment_index).into(),
problem: "format features do not contain \
`FormatFeature::COLOR_ATTACHMENT`"
.into(),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-renderPass-06582"],
..Default::default()
});
}));
}
}
@ -227,23 +227,23 @@ impl PipelineRenderingCreateInfo {
.potential_format_features()
.intersects(FormatFeatures::DEPTH_STENCIL_ATTACHMENT)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "depth_attachment_format".into(),
problem: "format features do not contain \
`FormatFeature::DEPTH_STENCIL_ATTACHMENT`"
.into(),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-renderPass-06585"],
..Default::default()
});
}));
}
if !format.aspects().intersects(ImageAspects::DEPTH) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "depth_attachment_format".into(),
problem: "does not have a depth aspect".into(),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-renderPass-06587"],
..Default::default()
});
}));
}
}
@ -260,23 +260,23 @@ impl PipelineRenderingCreateInfo {
.potential_format_features()
.intersects(FormatFeatures::DEPTH_STENCIL_ATTACHMENT)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "render_pass.stencil_attachment_format".into(),
problem: "format features do not contain \
`FormatFeature::DEPTH_STENCIL_ATTACHMENT`"
.into(),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-renderPass-06586"],
..Default::default()
});
}));
}
if !format.aspects().intersects(ImageAspects::STENCIL) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "render_pass.stencil_attachment_format".into(),
problem: "does not have a stencil aspect".into(),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-renderPass-06588"],
..Default::default()
});
}));
}
}
@ -284,13 +284,13 @@ impl PipelineRenderingCreateInfo {
(depth_attachment_format, stencil_attachment_format)
{
if depth_format != stencil_format {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`depth_attachment_format` and `stencil_attachment_format` are both \
`Some`, but are not equal"
.into(),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-renderPass-06589"],
..Default::default()
});
}));
}
}

View File

@ -62,7 +62,7 @@ impl TessellationState {
self
}
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
patch_control_points,
domain_origin,
@ -74,25 +74,25 @@ impl TessellationState {
match patch_control_points {
StateMode::Fixed(patch_control_points) => {
if patch_control_points == 0 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "patch_control_points".into(),
problem: "is zero".into(),
vuids: &[
"VUID-VkPipelineTessellationStateCreateInfo-patchControlPoints-01214",
],
..Default::default()
});
}));
}
if patch_control_points > properties.max_tessellation_patch_size {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "patch_control_points".into(),
problem: "exceeds the `max_tessellation_patch_size` limit".into(),
vuids: &[
"VUID-VkPipelineTessellationStateCreateInfo-patchControlPoints-01214",
],
..Default::default()
});
}));
}
}
StateMode::Dynamic => {
@ -100,14 +100,14 @@ impl TessellationState {
.enabled_features()
.extended_dynamic_state2_patch_control_points
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "patch_control_points".into(),
problem: "is dynamic".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"extended_dynamic_state2_patch_control_points",
)])]),
vuids: &["VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04870"],
});
}));
}
}
};
@ -126,7 +126,7 @@ impl TessellationState {
&& !(device.api_version() >= Version::V1_1
|| device.enabled_extensions().khr_maintenance2)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "domain_origin".into(),
problem: "is not `TessellationDomainOrigin::UpperLeft`".into(),
requires_one_of: RequiresOneOf(&[
@ -134,7 +134,7 @@ impl TessellationState {
RequiresAllOf(&[Requires::DeviceExtension("khr_maintenance2")]),
]),
..Default::default()
});
}));
}
Ok(())

View File

@ -62,7 +62,10 @@ impl BuffersDefinition {
#[allow(deprecated)]
unsafe impl VertexDefinition for BuffersDefinition {
#[inline]
fn definition(&self, interface: &ShaderInterface) -> Result<VertexInputState, ValidationError> {
fn definition(
&self,
interface: &ShaderInterface,
) -> Result<VertexInputState, Box<ValidationError>> {
self.0.definition(interface)
}
}

View File

@ -18,12 +18,18 @@ use crate::{
/// Trait for types that can create a [`VertexInputState`] from a [`ShaderInterface`].
pub unsafe trait VertexDefinition {
/// Builds the `VertexInputState` for the provided `interface`.
fn definition(&self, interface: &ShaderInterface) -> Result<VertexInputState, ValidationError>;
fn definition(
&self,
interface: &ShaderInterface,
) -> Result<VertexInputState, Box<ValidationError>>;
}
unsafe impl VertexDefinition for &[VertexBufferDescription] {
#[inline]
fn definition(&self, interface: &ShaderInterface) -> Result<VertexInputState, ValidationError> {
fn definition(
&self,
interface: &ShaderInterface,
) -> Result<VertexInputState, Box<ValidationError>> {
let bindings = self.iter().enumerate().map(|(binding, buffer)| {
(
binding as u32,
@ -47,14 +53,16 @@ unsafe impl VertexDefinition for &[VertexBufferDescription] {
.get(name.as_ref())
.map(|infos| (infos.clone(), binding as u32))
})
.ok_or_else(|| ValidationError {
problem: format!(
"the shader interface contains a variable named \"{}\", \
.ok_or_else(|| {
Box::new(ValidationError {
problem: format!(
"the shader interface contains a variable named \"{}\", \
but no such attribute exists in the vertex definition",
name,
)
.into(),
..Default::default()
name,
)
.into(),
..Default::default()
})
})?;
// TODO: ShaderInterfaceEntryType does not properly support 64bit.
@ -63,7 +71,7 @@ unsafe impl VertexDefinition for &[VertexBufferDescription] {
if infos.num_components() != element.ty.num_components
|| infos.num_elements != element.ty.num_locations()
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: format!(
"for the variable \"{}\", the number of locations and components \
required by the shader don't match the number of locations and components \
@ -72,7 +80,7 @@ unsafe impl VertexDefinition for &[VertexBufferDescription] {
)
.into(),
..Default::default()
});
}));
}
let mut offset = infos.offset as DeviceSize;
@ -106,21 +114,30 @@ unsafe impl VertexDefinition for &[VertexBufferDescription] {
unsafe impl<const N: usize> VertexDefinition for [VertexBufferDescription; N] {
#[inline]
fn definition(&self, interface: &ShaderInterface) -> Result<VertexInputState, ValidationError> {
fn definition(
&self,
interface: &ShaderInterface,
) -> Result<VertexInputState, Box<ValidationError>> {
self.as_slice().definition(interface)
}
}
unsafe impl VertexDefinition for Vec<VertexBufferDescription> {
#[inline]
fn definition(&self, interface: &ShaderInterface) -> Result<VertexInputState, ValidationError> {
fn definition(
&self,
interface: &ShaderInterface,
) -> Result<VertexInputState, Box<ValidationError>> {
self.as_slice().definition(interface)
}
}
unsafe impl VertexDefinition for VertexBufferDescription {
#[inline]
fn definition(&self, interface: &ShaderInterface) -> Result<VertexInputState, ValidationError> {
fn definition(
&self,
interface: &ShaderInterface,
) -> Result<VertexInputState, Box<ValidationError>> {
std::slice::from_ref(self).definition(interface)
}
}

View File

@ -179,7 +179,7 @@ impl VertexInputState {
self
}
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let Self {
bindings,
attributes,
@ -189,14 +189,14 @@ impl VertexInputState {
let properties = device.physical_device().properties();
if bindings.len() > properties.max_vertex_input_bindings as usize {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "bindings".into(),
problem: "the length exceeds the `max_vertex_input_bindings` limit".into(),
vuids: &[
"VUID-VkPipelineVertexInputStateCreateInfo-vertexBindingDescriptionCount-00613",
],
..Default::default()
});
}));
}
// VUID-VkPipelineVertexInputStateCreateInfo-pVertexBindingDescriptions-00616
@ -209,14 +209,14 @@ impl VertexInputState {
}
if attributes.len() > properties.max_vertex_input_attributes as usize {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "attributes".into(),
problem: "the length exceeds the `max_vertex_input_attributes` limit".into(),
vuids: &[
"VUID-VkPipelineVertexInputStateCreateInfo-vertexAttributeDescriptionCount-00614",
],
..Default::default()
});
}));
}
for (&location, attribute_desc) in attributes {
@ -231,7 +231,7 @@ impl VertexInputState {
} = attribute_desc;
if location > properties.max_vertex_input_attributes {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "attributes".into(),
problem: format!(
"the location {} exceeds the `max_vertex_input_attributes` limit",
@ -240,7 +240,7 @@ impl VertexInputState {
.into(),
vuids: &["VUID-VkVertexInputAttributeDescription-location-00620"],
..Default::default()
});
}));
}
let binding_desc = bindings.get(&binding).ok_or(ValidationError {
@ -260,7 +260,7 @@ impl VertexInputState {
&& offset as DeviceSize + format.block_size().unwrap()
> binding_desc.stride as DeviceSize
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: format!(
"this device is a portability subset device, and \
`attributes[{0}].offset + attributes[{0}].format.block_size()` \
@ -273,7 +273,7 @@ impl VertexInputState {
)])]),
vuids: &["VUID-VkVertexInputAttributeDescription-vertexAttributeAccessBeyondStride-04457"],
..Default::default()
});
}));
}
}
@ -286,7 +286,7 @@ impl VertexInputState {
for location in unassigned_locations {
if !attributes.get(&location).is_none() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: format!(
"`attributes[{}].format` takes up two locations, but \
`attributes` also contains a description for location {}",
@ -295,7 +295,7 @@ impl VertexInputState {
.into(),
vuids: &["VUID-VkPipelineVertexInputStateCreateInfo-pVertexAttributeDescriptions-00617"],
..Default::default()
});
}));
}
}
@ -327,18 +327,18 @@ pub struct VertexInputBindingDescription {
}
impl VertexInputBindingDescription {
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self { stride, input_rate } = self;
let properties = device.physical_device().properties();
if stride > properties.max_vertex_input_binding_stride {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "stride".into(),
problem: "exceeds the `max_vertex_input_binding_stride` limit".into(),
vuids: &["VUID-VkVertexInputBindingDescription-stride-00619"],
..Default::default()
});
}));
}
if device.enabled_extensions().khr_portability_subset
@ -349,14 +349,14 @@ impl VertexInputBindingDescription {
.unwrap()
!= 0)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "this device is a portability subset device, and \
`stride` is not a multiple of, and at least as large as, the \
`min_vertex_input_binding_stride_alignment` limit"
.into(),
vuids: &["VUID-VkVertexInputBindingDescription-stride-04456"],
..Default::default()
});
}));
}
match input_rate {
@ -365,7 +365,7 @@ impl VertexInputBindingDescription {
.enabled_features()
.vertex_attribute_instance_rate_divisor
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "input_rate".into(),
problem: "is `VertexInputRate::Instance`, and \
its `divisor` value is not 1".into(),
@ -373,7 +373,7 @@ impl VertexInputBindingDescription {
"vertex_attribute_instance_rate_divisor",
)])]),
vuids: &["VUID-VkVertexInputBindingDivisorDescriptionEXT-vertexAttributeInstanceRateDivisor-02229"],
});
}));
}
if divisor == 0
@ -381,7 +381,7 @@ impl VertexInputBindingDescription {
.enabled_features()
.vertex_attribute_instance_rate_zero_divisor
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "input_rate".into(),
problem: "is `VertexInputRate::Instance`, and \
its `divisor` value is 0".into(),
@ -389,18 +389,18 @@ impl VertexInputBindingDescription {
"vertex_attribute_instance_rate_zero_divisor",
)])]),
vuids: &["VUID-VkVertexInputBindingDivisorDescriptionEXT-vertexAttributeInstanceRateZeroDivisor-02228"],
});
}));
}
if divisor > properties.max_vertex_attrib_divisor.unwrap() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "input_rate".into(),
problem: "is `VertexInputRate::Instance`, and \
its `divisor` value exceeds the `max_vertex_attrib_divisor` limit"
.into(),
vuids: &["VUID-VkVertexInputBindingDivisorDescriptionEXT-divisor-01870"],
..Default::default()
});
}));
}
}
_ => (),
@ -430,7 +430,7 @@ pub struct VertexInputAttributeDescription {
}
impl VertexInputAttributeDescription {
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
binding,
format,
@ -448,21 +448,21 @@ impl VertexInputAttributeDescription {
})?;
if binding > properties.max_vertex_input_bindings {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "binding".into(),
problem: "exceeds the `max_vertex_input_bindings` limit".into(),
vuids: &["VUID-VkVertexInputAttributeDescription-binding-00621"],
..Default::default()
});
}));
}
if offset > properties.max_vertex_input_attribute_offset {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "offset".into(),
problem: "exceeds the `max_vertex_input_attribute_offset` limit".into(),
vuids: &["VUID-VkVertexInputAttributeDescription-offset-00622"],
..Default::default()
});
}));
}
let format_features = unsafe {
@ -473,13 +473,13 @@ impl VertexInputAttributeDescription {
};
if !format_features.intersects(FormatFeatures::VERTEX_BUFFER) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "format".into(),
problem: "the format features do not include `FormatFeatures::VERTEX_BUFFER`"
.into(),
vuids: &["VUID-VkVertexInputAttributeDescription-format-00623"],
..Default::default()
});
}));
}
Ok(())

View File

@ -182,7 +182,7 @@ impl ViewportState {
None
}
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let Self {
viewports,
scissors,
@ -194,12 +194,12 @@ impl ViewportState {
let viewport_count = match viewports {
PartialStateMode::Fixed(viewports) => {
if viewports.is_empty() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "viewports".into(),
problem: "is empty".into(),
vuids: &["VUID-VkPipelineViewportStateCreateInfo-viewportCount-04135"],
..Default::default()
});
}));
}
for (index, viewport) in viewports.iter().enumerate() {
@ -212,12 +212,12 @@ impl ViewportState {
}
PartialStateMode::Dynamic(StateMode::Fixed(count)) => {
if *count == 0 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "viewports".into(),
problem: "is empty".into(),
vuids: &["VUID-VkPipelineViewportStateCreateInfo-viewportCount-04135"],
..Default::default()
});
}));
}
*count
@ -231,12 +231,12 @@ impl ViewportState {
let scissor_count = match scissors {
PartialStateMode::Fixed(scissors) => {
if scissors.is_empty() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "scissors".into(),
problem: "is empty".into(),
vuids: &["VUID-VkPipelineViewportStateCreateInfo-scissorCount-04136"],
..Default::default()
});
}));
}
for (index, scissor) in scissors.iter().enumerate() {
@ -250,12 +250,12 @@ impl ViewportState {
.and_then(|(o, e)| o.checked_add(e))
.is_none()
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("scissors[{}]", index).into(),
problem: "`offset[0] + extent[0]` is greater than `i32::MAX`".into(),
vuids: &["VUID-VkPipelineViewportStateCreateInfo-offset-02822"],
..Default::default()
});
}));
}
if (i32::try_from(offset[1]).ok())
@ -263,12 +263,12 @@ impl ViewportState {
.and_then(|(o, e)| o.checked_add(e))
.is_none()
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("scissors[{}]", index).into(),
problem: "`offset[1] + extent[1]` is greater than `i32::MAX`".into(),
vuids: &["VUID-VkPipelineViewportStateCreateInfo-offset-02823"],
..Default::default()
});
}));
}
}
@ -276,12 +276,12 @@ impl ViewportState {
}
PartialStateMode::Dynamic(StateMode::Fixed(count)) => {
if *count == 0 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "scissors".into(),
problem: "is empty".into(),
vuids: &["VUID-VkPipelineViewportStateCreateInfo-scissorCount-04136"],
..Default::default()
});
}));
}
*count
@ -293,52 +293,52 @@ impl ViewportState {
};
if viewport_count != 0 && scissor_count != 0 && viewport_count != scissor_count {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the length of `viewports` and the length of `scissors` are not equal"
.into(),
vuids: &["VUID-VkPipelineViewportStateCreateInfo-scissorCount-04134"],
..Default::default()
});
}));
}
if viewport_count > 1 && !device.enabled_features().multi_viewport {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "viewports".into(),
problem: "the length is greater than 1".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"multi_viewport",
)])]),
vuids: &["VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216"],
});
}));
}
if scissor_count > 1 && !device.enabled_features().multi_viewport {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "scissors".into(),
problem: "the length is greater than 1".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"multi_viewport",
)])]),
vuids: &["VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217"],
});
}));
}
if viewport_count > properties.max_viewports {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "viewports".into(),
problem: "the length exceeds the `max_viewports` limit".into(),
vuids: &["VUID-VkPipelineViewportStateCreateInfo-viewportCount-01218"],
..Default::default()
});
}));
}
if scissor_count > properties.max_viewports {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "scissors".into(),
problem: "the length exceeds the `max_viewports` limit".into(),
vuids: &["VUID-VkPipelineViewportStateCreateInfo-scissorCount-01219"],
..Default::default()
});
}));
}
Ok(())
@ -373,7 +373,7 @@ pub struct Viewport {
}
impl Viewport {
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
offset,
extent,
@ -383,28 +383,28 @@ impl Viewport {
let properties = device.physical_device().properties();
if extent[0] <= 0.0 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "extent[0]".into(),
problem: "is not greater than zero".into(),
vuids: &["VUID-VkViewport-width-01770"],
..Default::default()
});
}));
}
if extent[0] > properties.max_viewport_dimensions[0] as f32 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "extent[0]".into(),
problem: "exceeds the `max_viewport_dimensions[0]` limit".into(),
vuids: &["VUID-VkViewport-width-01771"],
..Default::default()
});
}));
}
if extent[1] <= 0.0
&& !(device.api_version() >= Version::V1_1
|| device.enabled_extensions().khr_maintenance1)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "extent[1]".into(),
problem: "is not greater than zero".into(),
requires_one_of: RequiresOneOf(&[
@ -412,94 +412,94 @@ impl Viewport {
RequiresAllOf(&[Requires::DeviceExtension("khr_maintenance1")]),
]),
vuids: &["VUID-VkViewport-apiVersion-07917"],
});
}));
}
if extent[1].abs() > properties.max_viewport_dimensions[1] as f32 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "extent[1]".into(),
problem: "exceeds the `max_viewport_dimensions[1]` limit".into(),
vuids: &["VUID-VkViewport-height-01773"],
..Default::default()
});
}));
}
if offset[0] < properties.viewport_bounds_range[0] {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`offset[0]` is less than the `viewport_bounds_range[0]` property".into(),
vuids: &["VUID-VkViewport-x-01774"],
..Default::default()
});
}));
}
if offset[0] + extent[0] > properties.viewport_bounds_range[1] {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`offset[0] + extent[0]` is greater than the \
`viewport_bounds_range[1]` property"
.into(),
vuids: &["VUID-VkViewport-x-01232"],
..Default::default()
});
}));
}
if offset[1] < properties.viewport_bounds_range[0] {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`offset[1]` is less than the `viewport_bounds_range[0]` property".into(),
vuids: &["VUID-VkViewport-y-01775"],
..Default::default()
});
}));
}
if offset[1] > properties.viewport_bounds_range[1] {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`offset[1]` is greater than the `viewport_bounds_range[1]` property"
.into(),
vuids: &["VUID-VkViewport-y-01776"],
..Default::default()
});
}));
}
if offset[1] + extent[1] < properties.viewport_bounds_range[0] {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`offset[1] + extent[1]` is less than the \
`viewport_bounds_range[0]` property"
.into(),
vuids: &["VUID-VkViewport-y-01777"],
..Default::default()
});
}));
}
if offset[1] + extent[1] > properties.viewport_bounds_range[1] {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`offset[1] + extent[1]` is greater than the \
`viewport_bounds_range[1]` property"
.into(),
vuids: &["VUID-VkViewport-y-01233"],
..Default::default()
});
}));
}
if !device.enabled_extensions().ext_depth_range_unrestricted {
if *depth_range.start() < 0.0 || *depth_range.start() > 1.0 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`depth_range.start` is not between 0.0 and 1.0 inclusive".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceExtension(
"ext_depth_range_unrestricted",
)])]),
vuids: &["VUID-VkViewport-minDepth-01234"],
..Default::default()
});
}));
}
if *depth_range.end() < 0.0 || *depth_range.end() > 1.0 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`depth_range.end` is not between 0.0 and 1.0 inclusive".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceExtension(
"ext_depth_range_unrestricted",
)])]),
vuids: &["VUID-VkViewport-maxDepth-01235"],
..Default::default()
});
}));
}
}

View File

@ -73,7 +73,7 @@ use crate::{
instance::InstanceOwnedDebugWrapper,
macros::{impl_id_counter, vulkan_bitflags},
shader::{DescriptorBindingRequirements, ShaderStage, ShaderStages},
RuntimeError, ValidationError, VulkanError, VulkanObject,
Validated, ValidationError, VulkanError, VulkanObject,
};
use ahash::HashMap;
use smallvec::SmallVec;
@ -108,7 +108,7 @@ impl PipelineLayout {
pub fn new(
device: Arc<Device>,
create_info: PipelineLayoutCreateInfo,
) -> Result<Arc<PipelineLayout>, VulkanError> {
) -> Result<Arc<PipelineLayout>, Validated<VulkanError>> {
Self::validate_new(&device, &create_info)?;
unsafe { Ok(Self::new_unchecked(device, create_info)?) }
@ -117,7 +117,7 @@ impl PipelineLayout {
fn validate_new(
device: &Device,
create_info: &PipelineLayoutCreateInfo,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
// VUID-vkCreatePipelineLayout-pCreateInfo-parameter
create_info
.validate(device)
@ -130,7 +130,7 @@ impl PipelineLayout {
pub unsafe fn new_unchecked(
device: Arc<Device>,
create_info: PipelineLayoutCreateInfo,
) -> Result<Arc<PipelineLayout>, RuntimeError> {
) -> Result<Arc<PipelineLayout>, VulkanError> {
let &PipelineLayoutCreateInfo {
flags,
ref set_layouts,
@ -167,7 +167,7 @@ impl PipelineLayout {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -320,13 +320,13 @@ impl PipelineLayout {
/// Makes sure that `self` is a superset of the provided descriptor set layouts and push
/// constant ranges. Returns an `Err` if this is not the case.
pub fn ensure_compatible_with_shader<'a>(
pub(crate) fn ensure_compatible_with_shader<'a>(
&self,
descriptor_requirements: impl IntoIterator<
Item = ((u32, u32), &'a DescriptorBindingRequirements),
>,
push_constant_range: Option<&PushConstantRange>,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
for ((set_num, binding_num), reqs) in descriptor_requirements.into_iter() {
let layout_binding = self
.set_layouts
@ -336,7 +336,7 @@ impl PipelineLayout {
let layout_binding = match layout_binding {
Some(x) => x,
None => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: format!(
"the requirements for descriptor set {} binding {} were not met: \
no such binding exists in the pipeline layout",
@ -344,19 +344,19 @@ impl PipelineLayout {
)
.into(),
..Default::default()
});
}));
}
};
if let Err(error) = layout_binding.ensure_compatible_with_shader(reqs) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: format!(
"the requirements for descriptor set {} binding {} were not met: {}",
set_num, binding_num, error,
)
.into(),
..Default::default()
});
}));
}
}
@ -366,12 +366,12 @@ impl PipelineLayout {
(range.offset < own_range.offset || // our range must start before and end after the given range
own_range.offset + own_range.size < range.offset + range.size)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the required push constant range is larger than the \
push constant range in the pipeline layout"
.into(),
..Default::default()
});
}));
}
}
}
@ -447,7 +447,7 @@ impl Default for PipelineLayoutCreateInfo {
}
impl PipelineLayoutCreateInfo {
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let properties = device.physical_device().properties();
let &Self {
@ -466,12 +466,12 @@ impl PipelineLayoutCreateInfo {
})?;
if set_layouts.len() > properties.max_bound_descriptor_sets as usize {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "set_layouts".into(),
problem: "the length exceeds the `max_bound_descriptor_sets` limit".into(),
vuids: &["VUID-VkPipelineLayoutCreateInfo-setLayoutCount-00286"],
..Default::default()
});
}));
}
struct DescriptorLimit {
@ -640,14 +640,14 @@ impl PipelineLayoutCreateInfo {
.intersects(DescriptorSetLayoutCreateFlags::PUSH_DESCRIPTOR)
{
if has_push_descriptor_set {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "set_layouts".into(),
problem: "contains more than one descriptor set layout whose flags \
include `DescriptorSetLayoutCreateFlags::PUSH_DESCRIPTOR`"
.into(),
vuids: &["VUID-VkPipelineLayoutCreateInfo-pSetLayouts-00293"],
..Default::default()
});
}));
}
has_push_descriptor_set = true;
@ -688,7 +688,7 @@ impl PipelineLayoutCreateInfo {
{
if let Some((max_stage, max_count)) = count.into_iter().max_by_key(|(_, c)| *c) {
if max_count > (limit.get_limit)(properties) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "set_layouts".into(),
problem: format!(
"the combined number of {} descriptors accessible to the \
@ -706,14 +706,14 @@ impl PipelineLayoutCreateInfo {
.into(),
vuids: limit.vuids,
..Default::default()
});
}));
}
}
}
for (limit, count) in TOTAL_DESCRIPTOR_LIMITS.iter().zip(total_descriptors) {
if count > (limit.get_limit)(properties) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "set_layouts".into(),
problem: format!(
"the combined number of {} descriptors accessible across all \
@ -730,7 +730,7 @@ impl PipelineLayoutCreateInfo {
.into(),
vuids: limit.vuids,
..Default::default()
});
}));
}
}
@ -748,12 +748,12 @@ impl PipelineLayoutCreateInfo {
} = range;
if seen_stages.intersects(stages) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "push_constant_ranges".into(),
problem: "contains more than one range with the same stage".into(),
vuids: &["VUID-VkPipelineLayoutCreateInfo-pPushConstantRanges-00292"],
..Default::default()
});
}));
}
seen_stages |= stages;
@ -812,7 +812,7 @@ impl Default for PushConstantRange {
}
impl PushConstantRange {
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
stages,
offset,
@ -828,12 +828,12 @@ impl PushConstantRange {
})?;
if stages.is_empty() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "stages".into(),
problem: "is empty".into(),
vuids: &["VUID-VkPushConstantRange-stageFlags-requiredbitmask"],
..Default::default()
});
}));
}
let max_push_constants_size = device
@ -842,48 +842,48 @@ impl PushConstantRange {
.max_push_constants_size;
if offset >= max_push_constants_size {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "offset".into(),
problem: "is not less than the `max_push_constants_size` limit".into(),
vuids: &["VUID-VkPushConstantRange-offset-00294"],
..Default::default()
});
}));
}
if offset % 4 != 0 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "offset".into(),
problem: "is not a multiple of 4".into(),
vuids: &["VUID-VkPushConstantRange-offset-00295"],
..Default::default()
});
}));
}
if size == 0 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "size".into(),
problem: "is zero".into(),
vuids: &["VUID-VkPushConstantRange-size-00296"],
..Default::default()
});
}));
}
if size % 4 != 0 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "size".into(),
problem: "is not a multiple of 4".into(),
vuids: &["VUID-VkPushConstantRange-size-00297"],
..Default::default()
});
}));
}
if size > max_push_constants_size - offset {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`size` is greater than `max_push_constants_size` limit minus `offset`"
.into(),
vuids: &["VUID-VkPushConstantRange-size-00298"],
..Default::default()
});
}));
}
Ok(())
@ -1006,7 +1006,7 @@ impl PipelineDescriptorSetLayoutCreateInfo {
#[derive(Clone, Debug)]
pub struct IntoPipelineLayoutCreateInfoError {
pub set_num: u32,
pub error: VulkanError,
pub error: Validated<VulkanError>,
}
impl Display for IntoPipelineLayoutCreateInfoError {

View File

@ -336,7 +336,7 @@ impl PipelineShaderStageCreateInfo {
}
}
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
flags,
ref entry_point,
@ -381,7 +381,7 @@ impl PipelineShaderStageCreateInfo {
}
ShaderStage::TessellationControl | ShaderStage::TessellationEvaluation => {
if !device.enabled_features().tessellation_shader {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "entry_point".into(),
problem: "specifies a `ShaderStage::TessellationControl` or \
`ShaderStage::TessellationEvaluation` entry point"
@ -390,7 +390,7 @@ impl PipelineShaderStageCreateInfo {
"tessellation_shader",
)])]),
vuids: &["VUID-VkPipelineShaderStageCreateInfo-stage-00705"],
});
}));
}
// VUID-VkPipelineShaderStageCreateInfo-stage-00713
@ -398,14 +398,14 @@ impl PipelineShaderStageCreateInfo {
}
ShaderStage::Geometry => {
if !device.enabled_features().geometry_shader {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "entry_point".into(),
problem: "specifies a `ShaderStage::Geometry` entry point".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"geometry_shader",
)])]),
vuids: &["VUID-VkPipelineShaderStageCreateInfo-stage-00704"],
});
}));
}
// TODO:
@ -427,26 +427,26 @@ impl PipelineShaderStageCreateInfo {
ShaderStage::Callable => (),
ShaderStage::Task => {
if !device.enabled_features().task_shader {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "entry_point".into(),
problem: "specifies a `ShaderStage::Task` entry point".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"task_shader",
)])]),
vuids: &["VUID-VkPipelineShaderStageCreateInfo-stage-02092"],
});
}));
}
}
ShaderStage::Mesh => {
if !device.enabled_features().mesh_shader {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "entry_point".into(),
problem: "specifies a `ShaderStage::Mesh` entry point".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"mesh_shader",
)])]),
vuids: &["VUID-VkPipelineShaderStageCreateInfo-stage-02091"],
});
}));
}
}
ShaderStage::SubpassShading => (),
@ -461,7 +461,7 @@ impl PipelineShaderStageCreateInfo {
{
// Check for equal types rather than only equal size.
if !provided_value.eq_type(default_value) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: format!(
"`specialization_info[{0}]` does not have the same type as \
`entry_point.info().specialization_constants[{0}]`",
@ -470,7 +470,7 @@ impl PipelineShaderStageCreateInfo {
.into(),
vuids: &["VUID-VkSpecializationMapEntry-constantID-00776"],
..Default::default()
});
}));
}
}
}

View File

@ -18,7 +18,7 @@ use crate::{
device::{Device, DeviceOwned},
instance::InstanceOwnedDebugWrapper,
macros::{impl_id_counter, vulkan_bitflags},
DeviceSize, OomError, RequirementNotMet, Requires, RequiresAllOf, RequiresOneOf, RuntimeError,
DeviceSize, OomError, RequirementNotMet, Requires, RequiresAllOf, RequiresOneOf, VulkanError,
VulkanObject,
};
use std::{
@ -96,7 +96,7 @@ impl QueryPool {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -291,13 +291,13 @@ impl From<RequirementNotMet> for QueryPoolCreationError {
}
}
impl From<RuntimeError> for QueryPoolCreationError {
fn from(err: RuntimeError) -> QueryPoolCreationError {
impl From<VulkanError> for QueryPoolCreationError {
fn from(err: VulkanError) -> QueryPoolCreationError {
match err {
err @ RuntimeError::OutOfHostMemory => {
err @ VulkanError::OutOfHostMemory => {
QueryPoolCreationError::OomError(OomError::from(err))
}
err @ RuntimeError::OutOfDeviceMemory => {
err @ VulkanError::OutOfDeviceMemory => {
QueryPoolCreationError::OomError(OomError::from(err))
}
_ => panic!("unexpected error: {:?}", err),
@ -424,7 +424,7 @@ impl<'a> QueriesRange<'a> {
match result {
ash::vk::Result::SUCCESS => Ok(true),
ash::vk::Result::NOT_READY => Ok(false),
err => Err(RuntimeError::from(err).into()),
err => Err(VulkanError::from(err).into()),
}
}
}
@ -486,13 +486,13 @@ impl Display for GetResultsError {
}
}
impl From<RuntimeError> for GetResultsError {
fn from(err: RuntimeError) -> Self {
impl From<VulkanError> for GetResultsError {
fn from(err: VulkanError) -> Self {
match err {
RuntimeError::OutOfHostMemory | RuntimeError::OutOfDeviceMemory => {
VulkanError::OutOfHostMemory | VulkanError::OutOfDeviceMemory => {
Self::OomError(OomError::from(err))
}
RuntimeError::DeviceLost => Self::DeviceLost,
VulkanError::DeviceLost => Self::DeviceLost,
_ => panic!("unexpected error: {:?}", err),
}
}

View File

@ -11,7 +11,7 @@ use super::{AttachmentDescription, AttachmentReference, RenderPass, RenderPassCr
use crate::{
device::Device,
render_pass::{SubpassDependency, SubpassDescription},
RuntimeError, Version, VulkanObject,
Version, VulkanError, VulkanObject,
};
use smallvec::SmallVec;
use std::{mem::MaybeUninit, ptr};
@ -20,7 +20,7 @@ impl RenderPass {
pub(super) unsafe fn create_v2(
device: &Device,
create_info: &RenderPassCreateInfo,
) -> Result<ash::vk::RenderPass, RuntimeError> {
) -> Result<ash::vk::RenderPass, VulkanError> {
let &RenderPassCreateInfo {
flags,
ref attachments,
@ -522,7 +522,7 @@ impl RenderPass {
)
}
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
})
@ -531,7 +531,7 @@ impl RenderPass {
pub(super) unsafe fn create_v1(
device: &Device,
create_info: &RenderPassCreateInfo,
) -> Result<ash::vk::RenderPass, RuntimeError> {
) -> Result<ash::vk::RenderPass, VulkanError> {
let &RenderPassCreateInfo {
flags,
ref attachments,
@ -891,7 +891,7 @@ impl RenderPass {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
})
}

View File

@ -15,7 +15,7 @@ use crate::{
ImageAspects, ImageType, ImageUsage,
},
macros::{impl_id_counter, vulkan_bitflags},
RuntimeError, ValidationError, VulkanError, VulkanObject,
Validated, ValidationError, VulkanError, VulkanObject,
};
use smallvec::SmallVec;
use std::{mem::MaybeUninit, num::NonZeroU64, ops::Range, ptr, sync::Arc};
@ -61,7 +61,7 @@ impl Framebuffer {
pub fn new(
render_pass: Arc<RenderPass>,
mut create_info: FramebufferCreateInfo,
) -> Result<Arc<Framebuffer>, VulkanError> {
) -> Result<Arc<Framebuffer>, Validated<VulkanError>> {
create_info.set_auto_extent_layers(&render_pass);
Self::validate_new(&render_pass, &create_info)?;
@ -71,7 +71,7 @@ impl Framebuffer {
fn validate_new(
render_pass: &RenderPass,
create_info: &FramebufferCreateInfo,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
// VUID-vkCreateFramebuffer-pCreateInfo-parameter
create_info
.validate(render_pass.device())
@ -86,13 +86,13 @@ impl Framebuffer {
} = create_info;
if attachments.len() != render_pass.attachments().len() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`create_info.attachments` does not have the same length as \
`render_pass.attachments()`"
.into(),
vuids: &["VUID-VkFramebufferCreateInfo-attachmentCount-00876"],
..Default::default()
});
}));
}
for (index, ((image_view, attachment_desc), attachment_use)) in attachments
@ -104,7 +104,7 @@ impl Framebuffer {
if attachment_use.color_attachment
&& !image_view.usage().intersects(ImageUsage::COLOR_ATTACHMENT)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: format!(
"`render_pass` uses `create_info.attachments[{}]` as \
a color attachment, but it was not created with the \
@ -114,7 +114,7 @@ impl Framebuffer {
.into(),
vuids: &["VUID-VkFramebufferCreateInfo-pAttachments-00877"],
..Default::default()
});
}));
}
if attachment_use.depth_stencil_attachment
@ -122,7 +122,7 @@ impl Framebuffer {
.usage()
.intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: format!(
"`render_pass` uses `create_info.attachments[{}]` as \
a depth or stencil attachment, but it was not created with the \
@ -135,13 +135,13 @@ impl Framebuffer {
"VUID-VkFramebufferCreateInfo-pAttachments-02634",
],
..Default::default()
});
}));
}
if attachment_use.input_attachment
&& !image_view.usage().intersects(ImageUsage::INPUT_ATTACHMENT)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: format!(
"`render_pass` uses `create_info.attachments[{}]` as \
an input attachment, but it was not created with the \
@ -151,11 +151,11 @@ impl Framebuffer {
.into(),
vuids: &["VUID-VkFramebufferCreateInfo-pAttachments-02633"],
..Default::default()
});
}));
}
if image_view.format() != attachment_desc.format {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: format!(
"the format of `create_info.attachments[{}]` does not equal \
`render_pass.attachments()[{0}].format`",
@ -164,11 +164,11 @@ impl Framebuffer {
.into(),
vuids: &["VUID-VkFramebufferCreateInfo-pAttachments-00880"],
..Default::default()
});
}));
}
if image_view.image().samples() != attachment_desc.samples {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: format!(
"the samples of `create_info.attachments[{}]` does not equal \
`render_pass.attachments()[{0}].samples`",
@ -177,7 +177,7 @@ impl Framebuffer {
.into(),
vuids: &["VUID-VkFramebufferCreateInfo-pAttachments-00881"],
..Default::default()
});
}));
}
let image_view_extent = image_view.image().extent();
@ -189,7 +189,7 @@ impl Framebuffer {
|| attachment_use.depth_stencil_attachment
{
if image_view_extent[0] < extent[0] || image_view_extent[1] < extent[1] {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: format!(
"`render_pass` uses `create_info.attachments[{}]` as an input, color, \
depth or stencil attachment, but \
@ -202,11 +202,11 @@ impl Framebuffer {
"VUID-VkFramebufferCreateInfo-flags-04534",
],
..Default::default()
});
}));
}
if image_view_array_layers < layers {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: format!(
"`render_pass` uses `create_info.attachments[{}]` as an input, color, \
depth or stencil attachment, but \
@ -216,11 +216,11 @@ impl Framebuffer {
.into(),
vuids: &["VUID-VkFramebufferCreateInfo-flags-04535"],
..Default::default()
});
}));
}
if image_view_array_layers < render_pass.views_used() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: format!(
"`render_pass` has multiview enabled, and uses \
`create_info.attachments[{}]` as an input, color, depth or stencil \
@ -231,18 +231,18 @@ impl Framebuffer {
.into(),
vuids: &["VUID-VkFramebufferCreateInfo-renderPass-04536"],
..Default::default()
});
}));
}
}
if render_pass.views_used() != 0 && layers != 1 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`render_pass` has multiview enabled, but \
`create_info.layers` is not 1"
.into(),
vuids: &["VUID-VkFramebufferCreateInfo-renderPass-02531"],
..Default::default()
});
}));
}
}
@ -253,7 +253,7 @@ impl Framebuffer {
pub unsafe fn new_unchecked(
render_pass: Arc<RenderPass>,
mut create_info: FramebufferCreateInfo,
) -> Result<Arc<Framebuffer>, RuntimeError> {
) -> Result<Arc<Framebuffer>, VulkanError> {
create_info.set_auto_extent_layers(&render_pass);
let &FramebufferCreateInfo {
@ -288,7 +288,7 @@ impl Framebuffer {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -514,7 +514,7 @@ impl FramebufferCreateInfo {
}
}
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
flags,
ref attachments,
@ -538,21 +538,21 @@ impl FramebufferCreateInfo {
- image_view.subresource_range().mip_levels.start;
if image_view_mip_levels != 1 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("attachments[{}]", index).into(),
problem: "has more than one mip level".into(),
vuids: &["VUID-VkFramebufferCreateInfo-pAttachments-00883"],
..Default::default()
});
}));
}
if !image_view.component_mapping().is_identity() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("attachments[{}]", index).into(),
problem: "is not identity swizzled".into(),
vuids: &["VUID-VkFramebufferCreateInfo-pAttachments-00884"],
..Default::default()
});
}));
}
match image_view.view_type() {
@ -561,23 +561,23 @@ impl FramebufferCreateInfo {
&& (image_view.format().unwrap().aspects())
.intersects(ImageAspects::DEPTH | ImageAspects::STENCIL)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("attachments[{}]", index).into(),
problem: "is a 2D or 2D array image view, but its format is a \
depth/stencil format"
.into(),
vuids: &["VUID-VkFramebufferCreateInfo-pAttachments-00891"],
..Default::default()
});
}));
}
}
ImageViewType::Dim3d => {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("attachments[{}]", index).into(),
problem: "is a 3D image view".into(),
vuids: &["VUID-VkFramebufferCreateInfo-flags-04113"],
..Default::default()
});
}));
}
_ => (),
}
@ -586,57 +586,57 @@ impl FramebufferCreateInfo {
let properties = device.physical_device().properties();
if extent[0] == 0 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "extent[0]".into(),
problem: "is zero".into(),
vuids: &["VUID-VkFramebufferCreateInfo-width-00885"],
..Default::default()
});
}));
}
if extent[0] > properties.max_framebuffer_width {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "extent[0]".into(),
problem: "exceeds the `max_framebuffer_width` limit".into(),
vuids: &["VUID-VkFramebufferCreateInfo-width-00886"],
..Default::default()
});
}));
}
if extent[1] == 0 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "extent[1]".into(),
problem: "is zero".into(),
vuids: &["VUID-VkFramebufferCreateInfo-height-00887"],
..Default::default()
});
}));
}
if extent[1] > properties.max_framebuffer_height {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "extent[1]".into(),
problem: "exceeds the `max_framebuffer_height` limit".into(),
vuids: &["VUID-VkFramebufferCreateInfo-height-00888"],
..Default::default()
});
}));
}
if layers == 0 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "layers".into(),
problem: "is zero".into(),
vuids: &["VUID-VkFramebufferCreateInfo-layers-00889"],
..Default::default()
});
}));
}
if layers > properties.max_framebuffer_layers {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "layers".into(),
problem: "exceeds the `max_framebuffer_layers` limit".into(),
vuids: &["VUID-VkFramebufferCreateInfo-layers-00890"],
..Default::default()
});
}));
}
Ok(())

File diff suppressed because it is too large Load Diff

View File

@ -141,7 +141,7 @@ use crate::{
pipeline::{graphics::input_assembly::PrimitiveTopology, layout::PushConstantRange},
shader::spirv::{Capability, Spirv, SpirvError},
sync::PipelineStages,
OomError, RuntimeError, Version, VulkanObject,
OomError, Version, VulkanError, VulkanObject,
};
use ahash::{HashMap, HashSet};
use std::{
@ -277,7 +277,7 @@ impl ShaderModule {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -1283,8 +1283,8 @@ impl Display for ShaderModuleCreationError {
}
}
impl From<RuntimeError> for ShaderModuleCreationError {
fn from(err: RuntimeError) -> Self {
impl From<VulkanError> for ShaderModuleCreationError {
fn from(err: VulkanError) -> Self {
Self::OomError(err.into())
}
}

View File

@ -17,7 +17,7 @@ use crate::{
future::{AccessCheckError, AccessError, FlushError, GpuFuture, SubmitAnyBuilder},
semaphore::{Semaphore, SemaphoreError},
},
DeviceSize, OomError, RequirementNotMet, Requires, RequiresAllOf, RequiresOneOf, RuntimeError,
DeviceSize, OomError, RequirementNotMet, Requires, RequiresAllOf, RequiresOneOf, VulkanError,
VulkanObject,
};
use smallvec::smallvec;
@ -132,7 +132,7 @@ pub unsafe fn acquire_next_image_raw(
ash::vk::Result::SUBOPTIMAL_KHR => true,
ash::vk::Result::NOT_READY => return Err(AcquireError::Timeout),
ash::vk::Result::TIMEOUT => return Err(AcquireError::Timeout),
err => return Err(RuntimeError::from(err).into()),
err => return Err(VulkanError::from(err).into()),
};
if let Some(semaphore) = semaphore {
@ -386,15 +386,15 @@ impl From<OomError> for AcquireError {
}
}
impl From<RuntimeError> for AcquireError {
fn from(err: RuntimeError) -> AcquireError {
impl From<VulkanError> for AcquireError {
fn from(err: VulkanError) -> AcquireError {
match err {
err @ RuntimeError::OutOfHostMemory => AcquireError::OomError(OomError::from(err)),
err @ RuntimeError::OutOfDeviceMemory => AcquireError::OomError(OomError::from(err)),
RuntimeError::DeviceLost => AcquireError::DeviceLost,
RuntimeError::SurfaceLost => AcquireError::SurfaceLost,
RuntimeError::OutOfDate => AcquireError::OutOfDate,
RuntimeError::FullScreenExclusiveModeLost => AcquireError::FullScreenExclusiveModeLost,
err @ VulkanError::OutOfHostMemory => AcquireError::OomError(OomError::from(err)),
err @ VulkanError::OutOfDeviceMemory => AcquireError::OomError(OomError::from(err)),
VulkanError::DeviceLost => AcquireError::DeviceLost,
VulkanError::SurfaceLost => AcquireError::SurfaceLost,
VulkanError::OutOfDate => AcquireError::OutOfDate,
VulkanError::FullScreenExclusiveModeLost => AcquireError::FullScreenExclusiveModeLost,
_ => panic!("unexpected error: {:?}", err),
}
}
@ -918,7 +918,7 @@ pub fn wait_for_present(
ash::vk::Result::SUBOPTIMAL_KHR => Ok(true),
ash::vk::Result::TIMEOUT => Err(PresentWaitError::Timeout),
err => {
let err = RuntimeError::from(err).into();
let err = VulkanError::from(err).into();
if let PresentWaitError::FullScreenExclusiveModeLost = &err {
swapchain
@ -1012,15 +1012,15 @@ impl From<RequirementNotMet> for PresentWaitError {
}
}
impl From<RuntimeError> for PresentWaitError {
fn from(err: RuntimeError) -> PresentWaitError {
impl From<VulkanError> for PresentWaitError {
fn from(err: VulkanError) -> PresentWaitError {
match err {
err @ RuntimeError::OutOfHostMemory => Self::OomError(OomError::from(err)),
err @ RuntimeError::OutOfDeviceMemory => Self::OomError(OomError::from(err)),
RuntimeError::DeviceLost => Self::DeviceLost,
RuntimeError::SurfaceLost => Self::SurfaceLost,
RuntimeError::OutOfDate => Self::OutOfDate,
RuntimeError::FullScreenExclusiveModeLost => Self::FullScreenExclusiveModeLost,
err @ VulkanError::OutOfHostMemory => Self::OomError(OomError::from(err)),
err @ VulkanError::OutOfDeviceMemory => Self::OomError(OomError::from(err)),
VulkanError::DeviceLost => Self::DeviceLost,
VulkanError::SurfaceLost => Self::SurfaceLost,
VulkanError::OutOfDate => Self::OutOfDate,
VulkanError::FullScreenExclusiveModeLost => Self::FullScreenExclusiveModeLost,
_ => panic!("unexpected error: {:?}", err),
}
}

View File

@ -29,7 +29,7 @@
#![allow(unused_variables)] // TODO: this module isn't finished
use crate::{
device::physical::PhysicalDevice, swapchain::SurfaceTransforms, OomError, RuntimeError,
device::physical::PhysicalDevice, swapchain::SurfaceTransforms, OomError, VulkanError,
VulkanObject,
};
use std::{
@ -71,7 +71,7 @@ impl DisplayPlane {
ptr::null_mut(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
let mut properties = Vec::with_capacity(count as usize);
let result = (fns
@ -88,7 +88,7 @@ impl DisplayPlane {
break properties;
}
ash::vk::Result::INCOMPLETE => (),
err => return Err(RuntimeError::from(err).into()),
err => return Err(VulkanError::from(err).into()),
}
}
};
@ -107,7 +107,7 @@ impl DisplayPlane {
ptr::null_mut(),
)
.result()
.map_err(RuntimeError::from)
.map_err(VulkanError::from)
.unwrap(); // TODO: shouldn't unwrap
let mut displays = Vec::with_capacity(count as usize);
@ -202,7 +202,7 @@ impl Display {
ptr::null_mut(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
let mut properties = Vec::with_capacity(count as usize);
let result = (fns.khr_display.get_physical_device_display_properties_khr)(
@ -217,7 +217,7 @@ impl Display {
break properties;
}
ash::vk::Result::INCOMPLETE => (),
err => return Err(RuntimeError::from(err).into()),
err => return Err(VulkanError::from(err).into()),
}
}
};
@ -308,7 +308,7 @@ impl Display {
ptr::null_mut(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
let mut properties = Vec::with_capacity(count as usize);
let result = (fns.khr_display.get_display_mode_properties_khr)(
@ -324,7 +324,7 @@ impl Display {
break properties;
}
ash::vk::Result::INCOMPLETE => (),
err => return Err(RuntimeError::from(err).into()),
err => return Err(VulkanError::from(err).into()),
}
}
};
@ -390,7 +390,7 @@ impl DisplayMode {
let mut output = mem::uninitialized();
(fns.v1_0.CreateDisplayModeKHR)(display.device.handle(),
display.display, &infos, ptr::null(),
&mut output).result().map_err(RuntimeError::from)?;
&mut output).result().map_err(VulkanError::from)?;
output
};

View File

@ -336,7 +336,7 @@ use crate::{
instance::InstanceOwnedDebugWrapper,
macros::{impl_id_counter, vulkan_bitflags, vulkan_bitflags_enum, vulkan_enum},
sync::Sharing,
OomError, Requires, RequiresAllOf, RequiresOneOf, RuntimeError, ValidationError, VulkanError,
OomError, Requires, RequiresAllOf, RequiresOneOf, Validated, ValidationError, VulkanError,
VulkanObject,
};
use parking_lot::Mutex;
@ -420,7 +420,7 @@ impl Swapchain {
device: Arc<Device>,
surface: Arc<Surface>,
create_info: SwapchainCreateInfo,
) -> Result<(Arc<Swapchain>, Vec<Arc<Image>>), VulkanError> {
) -> Result<(Arc<Swapchain>, Vec<Arc<Image>>), Validated<VulkanError>> {
Self::validate_new_inner(&device, &surface, &create_info)?;
unsafe { Ok(Self::new_unchecked(device, surface, create_info)?) }
@ -432,7 +432,7 @@ impl Swapchain {
device: Arc<Device>,
surface: Arc<Surface>,
create_info: SwapchainCreateInfo,
) -> Result<(Arc<Swapchain>, Vec<Arc<Image>>), RuntimeError> {
) -> Result<(Arc<Swapchain>, Vec<Arc<Image>>), VulkanError> {
let (handle, image_handles) =
Self::new_inner_unchecked(&device, &surface, &create_info, None)?;
@ -449,7 +449,7 @@ impl Swapchain {
pub fn recreate(
self: &Arc<Self>,
create_info: SwapchainCreateInfo,
) -> Result<(Arc<Swapchain>, Vec<Arc<Image>>), VulkanError> {
) -> Result<(Arc<Swapchain>, Vec<Arc<Image>>), Validated<VulkanError>> {
Self::validate_new_inner(&self.device, &self.surface, &create_info)?;
{
@ -457,12 +457,12 @@ impl Swapchain {
// The swapchain has already been used to create a new one.
if *is_retired {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "self".into(),
problem: "has already been used to recreate a swapchain".into(),
vuids: &["VUID-VkSwapchainCreateInfoKHR-oldSwapchain-01933"],
..Default::default()
}
})
.into());
} else {
// According to the documentation of VkSwapchainCreateInfoKHR:
@ -483,7 +483,7 @@ impl Swapchain {
pub unsafe fn recreate_unchecked(
self: &Arc<Self>,
create_info: SwapchainCreateInfo,
) -> Result<(Arc<Swapchain>, Vec<Arc<Image>>), RuntimeError> {
) -> Result<(Arc<Swapchain>, Vec<Arc<Image>>), VulkanError> {
// According to the documentation of VkSwapchainCreateInfoKHR:
//
// > Upon calling vkCreateSwapchainKHR with a oldSwapchain that is not VK_NULL_HANDLE,
@ -520,14 +520,14 @@ impl Swapchain {
device: &Device,
surface: &Surface,
create_info: &SwapchainCreateInfo,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
if !device.enabled_extensions().khr_swapchain {
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceExtension(
"khr_swapchain",
)])]),
..Default::default()
});
}));
}
create_info
@ -568,12 +568,12 @@ impl Swapchain {
.unwrap_or_default()
})
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "surface".into(),
problem: "is not supported by the physical device".into(),
vuids: &["VUID-VkSwapchainCreateInfoKHR-surface-01270"],
..Default::default()
});
}));
}
let surface_capabilities = unsafe {
@ -630,23 +630,23 @@ impl Swapchain {
.max_image_count
.map_or(false, |c| min_image_count > c)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`create_info.min_image_count` is greater than the `max_image_count` \
value of the capabilities of `surface`"
.into(),
vuids: &["VUID-VkSwapchainCreateInfoKHR-minImageCount-01272"],
..Default::default()
});
}));
}
if min_image_count < surface_capabilities.min_image_count {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`create_info.min_image_count` is less than the `min_image_count` \
value of the capabilities of `surface`"
.into(),
vuids: &["VUID-VkSwapchainCreateInfoKHR-presentMode-02839"],
..Default::default()
});
}));
}
if let Some(image_format) = image_format {
@ -654,24 +654,24 @@ impl Swapchain {
.iter()
.any(|&fc| fc == (image_format, image_color_space))
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the combination of `create_info.image_format` and \
`create_info.image_color_space` is not supported for `surface`"
.into(),
vuids: &["VUID-VkSwapchainCreateInfoKHR-imageFormat-01273"],
..Default::default()
});
}));
}
}
if image_array_layers > surface_capabilities.max_image_array_layers {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`create_info.image_array_layers` is greater than the \
`max_image_array_layers` value of the capabilities of `surface`"
.into(),
vuids: &["VUID-VkSwapchainCreateInfoKHR-imageArrayLayers-01275"],
..Default::default()
});
}));
}
if matches!(
@ -684,7 +684,7 @@ impl Swapchain {
.supported_usage_flags
.contains(image_usage)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`create_info.present_mode` is `PresentMode::Immediate`, \
`PresentMode::Mailbox`, `PresentMode::Fifo` or `PresentMode::FifoRelaxed`, \
and `create_info.image_usage` contains flags that are not set in \
@ -692,41 +692,41 @@ impl Swapchain {
.into(),
vuids: &["VUID-VkSwapchainCreateInfoKHR-presentMode-01427"],
..Default::default()
});
}));
}
if !surface_capabilities
.supported_transforms
.contains_enum(pre_transform)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`create_info.pre_transform` is not present in the \
`supported_transforms` value of the capabilities of `surface`"
.into(),
vuids: &["VUID-VkSwapchainCreateInfoKHR-preTransform-01279"],
..Default::default()
});
}));
}
if !surface_capabilities
.supported_composite_alpha
.contains_enum(composite_alpha)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`create_info.composite_alpha` is not present in the \
`supported_composite_alpha` value of the capabilities of `surface`"
.into(),
vuids: &["VUID-VkSwapchainCreateInfoKHR-compositeAlpha-01280"],
..Default::default()
});
}));
}
if !surface_present_modes.contains(&present_mode) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`create_info.present_mode` is not supported for `surface`".into(),
vuids: &["VUID-VkSwapchainCreateInfoKHR-presentMode-01281"],
..Default::default()
});
}));
}
if present_modes.is_empty() {
@ -735,7 +735,7 @@ impl Swapchain {
.supported_present_scaling
.contains_enum(scaling_behavior)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`create_info.scaling_behavior` is not present in the \
`supported_present_scaling` value of the \
capabilities of `surface`"
@ -744,7 +744,7 @@ impl Swapchain {
"VUID-VkSwapchainPresentScalingCreateInfoEXT-scalingBehavior-07770",
],
..Default::default()
});
}));
}
}
@ -755,7 +755,7 @@ impl Swapchain {
.enumerate()
{
if !supported_present_gravity.contains_enum(present_gravity) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: format!(
"`create_info.present_gravity[{0}]` is not present in the \
`supported_present_gravity[{0}]` value of the \
@ -768,14 +768,14 @@ impl Swapchain {
"VUID-VkSwapchainPresentScalingCreateInfoEXT-presentGravityY-07774",
],
..Default::default()
});
}));
}
}
}
} else {
for (index, &present_mode) in present_modes.iter().enumerate() {
if !surface_present_modes.contains(&present_mode) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: format!(
"`create_info.present_modes[{}]` is not supported for `surface`",
index,
@ -783,14 +783,14 @@ impl Swapchain {
.into(),
vuids: &["VUID-VkSwapchainPresentModesCreateInfoEXT-None-07762"],
..Default::default()
});
}));
}
if !surface_capabilities
.compatible_present_modes
.contains(&present_mode)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: format!(
"`create_info.present_modes[{}]` is not present in the \
`compatible_present_modes` value of the \
@ -800,7 +800,7 @@ impl Swapchain {
.into(),
vuids: &["VUID-VkSwapchainPresentModesCreateInfoEXT-pPresentModes-07763"],
..Default::default()
});
}));
}
if scaling_behavior.is_some() || present_gravity.is_some() {
@ -828,7 +828,7 @@ impl Swapchain {
.supported_present_scaling
.contains_enum(scaling_behavior)
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: format!(
"`create_info.scaling_behavior` is not present in the \
`supported_present_scaling` value of the \
@ -841,7 +841,7 @@ impl Swapchain {
"VUID-VkSwapchainPresentScalingCreateInfoEXT-scalingBehavior-07771",
],
..Default::default()
});
}));
}
}
@ -853,7 +853,7 @@ impl Swapchain {
.enumerate()
{
if !supported_present_gravity.contains_enum(present_gravity) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: format!(
"`create_info.present_gravity[{0}]` is not present in the \
`supported_present_gravity[{0}]` value of the \
@ -867,7 +867,7 @@ impl Swapchain {
"VUID-VkSwapchainPresentScalingCreateInfoEXT-presentGravityY-07775",
],
..Default::default()
});
}));
}
}
}
@ -880,7 +880,7 @@ impl Swapchain {
if image_extent[0] < min_scaled_image_extent[0]
|| image_extent[1] < min_scaled_image_extent[1]
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`scaling_behavior` is `Some`, and an element of \
`create_info.image_extent` is less than the corresponding element \
of the `min_scaled_image_extent` value of the \
@ -888,7 +888,7 @@ impl Swapchain {
.into(),
vuids: &["VUID-VkSwapchainCreateInfoKHR-pNext-07782"],
..Default::default()
});
}));
}
}
@ -896,7 +896,7 @@ impl Swapchain {
if image_extent[0] > max_scaled_image_extent[0]
|| image_extent[1] > max_scaled_image_extent[1]
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`scaling_behavior` is `Some`, and an element of \
`create_info.image_extent` is greater than the corresponding element \
of the `max_scaled_image_extent` value of the \
@ -904,7 +904,7 @@ impl Swapchain {
.into(),
vuids: &["VUID-VkSwapchainCreateInfoKHR-pNext-07782"],
..Default::default()
});
}));
}
}
} else {
@ -919,7 +919,7 @@ impl Swapchain {
if image_extent[0] < surface_capabilities.min_image_extent[0]
|| image_extent[1] < surface_capabilities.min_image_extent[1]
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`scaling_behavior` is `Some`, and an element of \
`create_info.image_extent` is less than the corresponding element \
of the `min_image_extent` value of the \
@ -927,13 +927,13 @@ impl Swapchain {
.into(),
vuids: &["VUID-VkSwapchainCreateInfoKHR-pNext-07781"],
..Default::default()
});
}));
}
if image_extent[0] > surface_capabilities.max_image_extent[0]
|| image_extent[1] > surface_capabilities.max_image_extent[1]
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`scaling_behavior` is `Some`, and an element of \
`create_info.image_extent` is greater than the corresponding element \
of the `max_image_extent` value of the \
@ -941,7 +941,7 @@ impl Swapchain {
.into(),
vuids: &["VUID-VkSwapchainCreateInfoKHR-pNext-07781"],
..Default::default()
});
}));
}
*/
}
@ -950,7 +950,7 @@ impl Swapchain {
&& full_screen_exclusive == FullScreenExclusive::ApplicationControlled
{
if win32_monitor.is_none() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`surface` is a Win32 surface, and \
`create_info.full_screen_exclusive` is \
`FullScreenExclusive::ApplicationControlled`, but \
@ -958,18 +958,18 @@ impl Swapchain {
.into(),
vuids: &["VUID-VkSwapchainCreateInfoKHR-pNext-02679"],
..Default::default()
});
}));
}
} else {
if win32_monitor.is_some() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`surface` is not a Win32 surface, or \
`create_info.full_screen_exclusive` is not \
`FullScreenExclusive::ApplicationControlled`, but \
`create_info.win32_monitor` is `Some`"
.into(),
..Default::default()
});
}));
}
}
@ -981,7 +981,7 @@ impl Swapchain {
surface: &Surface,
create_info: &SwapchainCreateInfo,
old_swapchain: Option<&Swapchain>,
) -> Result<(ash::vk::SwapchainKHR, Vec<ash::vk::Image>), RuntimeError> {
) -> Result<(ash::vk::SwapchainKHR, Vec<ash::vk::Image>), VulkanError> {
let &SwapchainCreateInfo {
flags,
min_image_count,
@ -1103,7 +1103,7 @@ impl Swapchain {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -1116,7 +1116,7 @@ impl Swapchain {
ptr::null_mut(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
let mut images = Vec::with_capacity(count as usize);
let result = (fns.khr_swapchain.get_swapchain_images_khr)(
@ -1132,7 +1132,7 @@ impl Swapchain {
break images;
}
ash::vk::Result::INCOMPLETE => (),
err => return Err(RuntimeError::from(err)),
err => return Err(VulkanError::from(err)),
}
};
@ -1154,7 +1154,7 @@ impl Swapchain {
image_handles: impl IntoIterator<Item = ash::vk::Image>,
surface: Arc<Surface>,
create_info: SwapchainCreateInfo,
) -> Result<(Arc<Swapchain>, Vec<Arc<Image>>), RuntimeError> {
) -> Result<(Arc<Swapchain>, Vec<Arc<Image>>), VulkanError> {
let SwapchainCreateInfo {
flags,
min_image_count,
@ -1223,7 +1223,7 @@ impl Swapchain {
image_index as u32,
)?))
})
.collect::<Result<_, RuntimeError>>()?;
.collect::<Result<_, VulkanError>>()?;
Ok((swapchain, swapchain_images))
}
@ -1398,7 +1398,7 @@ impl Swapchain {
self.device.handle(), self.handle
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
}
Ok(())
@ -1428,7 +1428,7 @@ impl Swapchain {
self.device.handle(), self.handle
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
}
Ok(())
@ -1662,7 +1662,7 @@ impl Default for SwapchainCreateInfo {
}
impl SwapchainCreateInfo {
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
flags,
min_image_count: _,
@ -1724,12 +1724,12 @@ impl SwapchainCreateInfo {
})?;
if image_usage.is_empty() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "image_usage".into(),
problem: "is empty".into(),
vuids: &["VUID-VkSwapchainCreateInfoKHR-imageUsage-requiredbitmask"],
..Default::default()
});
}));
}
pre_transform
@ -1757,35 +1757,35 @@ impl SwapchainCreateInfo {
})?;
if image_extent.contains(&0) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "image_extent".into(),
problem: "one or more elements are zero".into(),
vuids: &["VUID-VkSwapchainCreateInfoKHR-imageExtent-01689"],
..Default::default()
});
}));
}
if image_array_layers == 0 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "image_array_layers".into(),
problem: "is zero".into(),
vuids: &["VUID-VkSwapchainCreateInfoKHR-imageArrayLayers-01275"],
..Default::default()
});
}));
}
match image_sharing {
Sharing::Exclusive => (),
Sharing::Concurrent(queue_family_indices) => {
if queue_family_indices.len() < 2 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "image_sharing".into(),
problem: "is `Sharing::Concurrent`, and contains less than 2 \
queue family indices"
.into(),
vuids: &["VUID-VkSwapchainCreateInfoKHR-imageSharingMode-01278"],
..Default::default()
});
}));
}
let queue_family_count =
@ -1793,7 +1793,7 @@ impl SwapchainCreateInfo {
for (index, &queue_family_index) in queue_family_indices.iter().enumerate() {
if queue_family_indices[..index].contains(&queue_family_index) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "queue_family_indices".into(),
problem: format!(
"the queue family index in the list at index {} is contained in \
@ -1803,18 +1803,18 @@ impl SwapchainCreateInfo {
.into(),
vuids: &["VUID-VkSwapchainCreateInfoKHR-imageSharingMode-01428"],
..Default::default()
});
}));
}
if queue_family_index >= queue_family_count {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: format!("queue_family_indices[{}]", index).into(),
problem: "is not less than the number of queue families in the \
physical device"
.into(),
vuids: &["VUID-VkSwapchainCreateInfoKHR-imageSharingMode-01428"],
..Default::default()
});
}));
}
}
}
@ -1838,25 +1838,25 @@ impl SwapchainCreateInfo {
};
if image_format_properties.is_none() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "the combination of `image_format` and `image_usage` is not supported \
for images by the physical device"
.into(),
vuids: &["VUID-VkSwapchainCreateInfoKHR-imageFormat-01778"],
..Default::default()
});
}));
}
if !present_modes.is_empty() {
if !device.enabled_extensions().ext_swapchain_maintenance1 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "present_modes".into(),
problem: "is not empty".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceExtension(
"ext_swapchain_maintenance1",
)])]),
..Default::default()
});
}));
}
for (index, &present_mode) in present_modes.iter().enumerate() {
@ -1872,25 +1872,25 @@ impl SwapchainCreateInfo {
}
if !present_modes.contains(&present_mode) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`present_modes` is not empty, but does not contain `present_mode`"
.into(),
vuids: &["VUID-VkSwapchainPresentModesCreateInfoEXT-presentMode-07764"],
..Default::default()
});
}));
}
}
if let Some(scaling_behavior) = scaling_behavior {
if !device.enabled_extensions().ext_swapchain_maintenance1 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "scaling_behavior".into(),
problem: "is `Some`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceExtension(
"ext_swapchain_maintenance1",
)])]),
..Default::default()
});
}));
}
scaling_behavior
@ -1909,14 +1909,14 @@ impl SwapchainCreateInfo {
if let Some(present_gravity) = present_gravity {
if !device.enabled_extensions().ext_swapchain_maintenance1 {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "present_gravity".into(),
problem: "is `Some`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceExtension(
"ext_swapchain_maintenance1",
)])]),
..Default::default()
});
}));
}
for (axis_index, present_gravity) in present_gravity.into_iter().enumerate() {
@ -1943,14 +1943,14 @@ impl SwapchainCreateInfo {
if full_screen_exclusive != FullScreenExclusive::Default {
if !device.enabled_extensions().ext_full_screen_exclusive {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "full_screen_exclusive".into(),
problem: "is not `FullScreenExclusive::Default`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceExtension(
"ext_full_screen_exclusive",
)])]),
..Default::default()
});
}));
}
full_screen_exclusive
@ -2145,17 +2145,17 @@ impl Display for FullScreenExclusiveError {
}
}
impl From<RuntimeError> for FullScreenExclusiveError {
fn from(err: RuntimeError) -> FullScreenExclusiveError {
impl From<VulkanError> for FullScreenExclusiveError {
fn from(err: VulkanError) -> FullScreenExclusiveError {
match err {
err @ RuntimeError::OutOfHostMemory => {
err @ VulkanError::OutOfHostMemory => {
FullScreenExclusiveError::OomError(OomError::from(err))
}
err @ RuntimeError::OutOfDeviceMemory => {
err @ VulkanError::OutOfDeviceMemory => {
FullScreenExclusiveError::OomError(OomError::from(err))
}
RuntimeError::SurfaceLost => FullScreenExclusiveError::SurfaceLost,
RuntimeError::InitializationFailed => FullScreenExclusiveError::InitializationFailed,
VulkanError::SurfaceLost => FullScreenExclusiveError::SurfaceLost,
VulkanError::InitializationFailed => FullScreenExclusiveError::InitializationFailed,
_ => panic!("unexpected error: {:?}", err),
}
}

View File

@ -16,8 +16,8 @@ use crate::{
instance::{Instance, InstanceExtensions, InstanceOwned},
macros::{impl_id_counter, vulkan_bitflags_enum, vulkan_enum},
swapchain::display::{DisplayMode, DisplayPlane},
DebugWrapper, Requires, RequiresAllOf, RequiresOneOf, RuntimeError, ValidationError,
VulkanError, VulkanObject,
DebugWrapper, Requires, RequiresAllOf, RequiresOneOf, Validated, ValidationError, VulkanError,
VulkanObject,
};
#[cfg(any(target_os = "macos", target_os = "ios"))]
use objc::{class, msg_send, runtime::Object, sel, sel_impl};
@ -83,7 +83,7 @@ impl Surface {
pub fn from_window(
instance: Arc<Instance>,
window: Arc<impl HasRawWindowHandle + HasRawDisplayHandle + Any + Send + Sync>,
) -> Result<Arc<Self>, VulkanError> {
) -> Result<Arc<Self>, Validated<VulkanError>> {
let mut surface = unsafe { Self::from_window_ref(instance, &*window) }?;
Arc::get_mut(&mut surface).unwrap().object = Some(window);
@ -99,7 +99,7 @@ impl Surface {
pub unsafe fn from_window_ref(
instance: Arc<Instance>,
window: &(impl HasRawWindowHandle + HasRawDisplayHandle),
) -> Result<Arc<Self>, VulkanError> {
) -> Result<Arc<Self>, Validated<VulkanError>> {
match (window.raw_window_handle(), window.raw_display_handle()) {
(RawWindowHandle::AndroidNdk(window), RawDisplayHandle::Android(_display)) => {
Self::from_android(instance, window.a_native_window, None)
@ -169,20 +169,20 @@ impl Surface {
pub fn headless(
instance: Arc<Instance>,
object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, VulkanError> {
) -> Result<Arc<Self>, Validated<VulkanError>> {
Self::validate_headless(&instance)?;
unsafe { Ok(Self::headless_unchecked(instance, object)?) }
}
fn validate_headless(instance: &Instance) -> Result<(), ValidationError> {
fn validate_headless(instance: &Instance) -> Result<(), Box<ValidationError>> {
if !instance.enabled_extensions().ext_headless_surface {
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"ext_headless_surface",
)])]),
..Default::default()
});
}));
}
Ok(())
@ -192,7 +192,7 @@ impl Surface {
pub unsafe fn headless_unchecked(
instance: Arc<Instance>,
object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, RuntimeError> {
) -> Result<Arc<Self>, VulkanError> {
let create_info = ash::vk::HeadlessSurfaceCreateInfoEXT {
flags: ash::vk::HeadlessSurfaceCreateFlagsEXT::empty(),
..Default::default()
@ -208,7 +208,7 @@ impl Surface {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -229,7 +229,7 @@ impl Surface {
pub fn from_display_plane(
display_mode: &DisplayMode,
plane: &DisplayPlane,
) -> Result<Arc<Self>, VulkanError> {
) -> Result<Arc<Self>, Validated<VulkanError>> {
Self::validate_from_display_plane(display_mode, plane)?;
unsafe { Ok(Self::from_display_plane_unchecked(display_mode, plane)?) }
@ -238,7 +238,7 @@ impl Surface {
fn validate_from_display_plane(
display_mode: &DisplayMode,
plane: &DisplayPlane,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
if !display_mode
.display()
.physical_device()
@ -246,12 +246,12 @@ impl Surface {
.enabled_extensions()
.khr_display
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"khr_display",
)])]),
..Default::default()
});
}));
}
assert_eq!(
@ -267,7 +267,7 @@ impl Surface {
pub unsafe fn from_display_plane_unchecked(
display_mode: &DisplayMode,
plane: &DisplayPlane,
) -> Result<Arc<Self>, RuntimeError> {
) -> Result<Arc<Self>, VulkanError> {
let instance = display_mode.display().physical_device().instance();
let create_info = ash::vk::DisplaySurfaceCreateInfoKHR {
@ -296,7 +296,7 @@ impl Surface {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -319,7 +319,7 @@ impl Surface {
instance: Arc<Instance>,
window: *const W,
object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, VulkanError> {
) -> Result<Arc<Self>, Validated<VulkanError>> {
Self::validate_from_android(&instance, window)?;
Ok(Self::from_android_unchecked(instance, window, object)?)
@ -328,14 +328,14 @@ impl Surface {
fn validate_from_android<W>(
instance: &Instance,
_window: *const W,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
if !instance.enabled_extensions().khr_android_surface {
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"khr_android_surface",
)])]),
..Default::default()
});
}));
}
// VUID-VkAndroidSurfaceCreateInfoKHR-window-01248
@ -349,7 +349,7 @@ impl Surface {
instance: Arc<Instance>,
window: *const W,
object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, RuntimeError> {
) -> Result<Arc<Self>, VulkanError> {
let create_info = ash::vk::AndroidSurfaceCreateInfoKHR {
flags: ash::vk::AndroidSurfaceCreateFlagsKHR::empty(),
window: window as *mut _,
@ -366,7 +366,7 @@ impl Surface {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -391,7 +391,7 @@ impl Surface {
dfb: *const D,
surface: *const S,
object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, VulkanError> {
) -> Result<Arc<Self>, Validated<VulkanError>> {
Self::validate_from_directfb(&instance, dfb, surface)?;
Ok(Self::from_directfb_unchecked(
@ -403,14 +403,14 @@ impl Surface {
instance: &Instance,
_dfb: *const D,
_surface: *const S,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
if !instance.enabled_extensions().ext_directfb_surface {
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"ext_directfb_surface",
)])]),
..Default::default()
});
}));
}
// VUID-VkDirectFBSurfaceCreateInfoEXT-dfb-04117
@ -428,7 +428,7 @@ impl Surface {
dfb: *const D,
surface: *const S,
object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, RuntimeError> {
) -> Result<Arc<Self>, VulkanError> {
let create_info = ash::vk::DirectFBSurfaceCreateInfoEXT {
flags: ash::vk::DirectFBSurfaceCreateFlagsEXT::empty(),
dfb: dfb as *mut _,
@ -446,7 +446,7 @@ impl Surface {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -469,7 +469,7 @@ impl Surface {
instance: Arc<Instance>,
image_pipe_handle: ash::vk::zx_handle_t,
object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, VulkanError> {
) -> Result<Arc<Self>, Validated<VulkanError>> {
Self::validate_from_fuchsia_image_pipe(&instance, image_pipe_handle)?;
Ok(Self::from_fuchsia_image_pipe_unchecked(
@ -482,14 +482,14 @@ impl Surface {
fn validate_from_fuchsia_image_pipe(
instance: &Instance,
_image_pipe_handle: ash::vk::zx_handle_t,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
if !instance.enabled_extensions().fuchsia_imagepipe_surface {
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"fuchsia_imagepipe_surface",
)])]),
..Default::default()
});
}));
}
// VUID-VkImagePipeSurfaceCreateInfoFUCHSIA-imagePipeHandle-04863
@ -503,7 +503,7 @@ impl Surface {
instance: Arc<Instance>,
image_pipe_handle: ash::vk::zx_handle_t,
object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, RuntimeError> {
) -> Result<Arc<Self>, VulkanError> {
let create_info = ash::vk::ImagePipeSurfaceCreateInfoFUCHSIA {
flags: ash::vk::ImagePipeSurfaceCreateFlagsFUCHSIA::empty(),
image_pipe_handle,
@ -521,7 +521,7 @@ impl Surface {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -544,7 +544,7 @@ impl Surface {
instance: Arc<Instance>,
stream_descriptor: ash::vk::GgpStreamDescriptor,
object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, VulkanError> {
) -> Result<Arc<Self>, Validated<VulkanError>> {
Self::validate_from_ggp_stream_descriptor(&instance, stream_descriptor)?;
Ok(Self::from_ggp_stream_descriptor_unchecked(
@ -557,14 +557,14 @@ impl Surface {
fn validate_from_ggp_stream_descriptor(
instance: &Instance,
_stream_descriptor: ash::vk::GgpStreamDescriptor,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
if !instance.enabled_extensions().ggp_stream_descriptor_surface {
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"ggp_stream_descriptor_surface",
)])]),
..Default::default()
});
}));
}
// VUID-VkStreamDescriptorSurfaceCreateInfoGGP-streamDescriptor-02681
@ -578,7 +578,7 @@ impl Surface {
instance: Arc<Instance>,
stream_descriptor: ash::vk::GgpStreamDescriptor,
object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, RuntimeError> {
) -> Result<Arc<Self>, VulkanError> {
let create_info = ash::vk::StreamDescriptorSurfaceCreateInfoGGP {
flags: ash::vk::StreamDescriptorSurfaceCreateFlagsGGP::empty(),
stream_descriptor,
@ -596,7 +596,7 @@ impl Surface {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -621,7 +621,7 @@ impl Surface {
instance: Arc<Instance>,
metal_layer: IOSMetalLayer,
object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, VulkanError> {
) -> Result<Arc<Self>, Validated<VulkanError>> {
Self::validate_from_ios(&instance, &metal_layer)?;
Ok(Self::from_ios_unchecked(instance, metal_layer, object)?)
@ -631,14 +631,14 @@ impl Surface {
fn validate_from_ios(
instance: &Instance,
_metal_layer: &IOSMetalLayer,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
if !instance.enabled_extensions().mvk_ios_surface {
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"mvk_ios_surface",
)])]),
..Default::default()
});
}));
}
// VUID-VkIOSSurfaceCreateInfoMVK-pView-04143
@ -656,7 +656,7 @@ impl Surface {
instance: Arc<Instance>,
metal_layer: IOSMetalLayer,
object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, RuntimeError> {
) -> Result<Arc<Self>, VulkanError> {
let create_info = ash::vk::IOSSurfaceCreateInfoMVK {
flags: ash::vk::IOSSurfaceCreateFlagsMVK::empty(),
p_view: metal_layer.render_layer.0 as *const _,
@ -673,7 +673,7 @@ impl Surface {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -698,7 +698,7 @@ impl Surface {
instance: Arc<Instance>,
view: *const V,
object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, VulkanError> {
) -> Result<Arc<Self>, Validated<VulkanError>> {
Self::validate_from_mac_os(&instance, view)?;
Ok(Self::from_mac_os_unchecked(instance, view, object)?)
@ -708,14 +708,14 @@ impl Surface {
fn validate_from_mac_os<V>(
instance: &Instance,
_view: *const V,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
if !instance.enabled_extensions().mvk_macos_surface {
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"mvk_macos_surface",
)])]),
..Default::default()
});
}));
}
// VUID-VkMacOSSurfaceCreateInfoMVK-pView-04144
@ -733,7 +733,7 @@ impl Surface {
instance: Arc<Instance>,
view: *const V,
object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, RuntimeError> {
) -> Result<Arc<Self>, VulkanError> {
let create_info = ash::vk::MacOSSurfaceCreateInfoMVK {
flags: ash::vk::MacOSSurfaceCreateFlagsMVK::empty(),
p_view: view as *const _,
@ -750,7 +750,7 @@ impl Surface {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -773,7 +773,7 @@ impl Surface {
instance: Arc<Instance>,
layer: *const L,
object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, VulkanError> {
) -> Result<Arc<Self>, Validated<VulkanError>> {
Self::validate_from_metal(&instance, layer)?;
Ok(Self::from_metal_unchecked(instance, layer, object)?)
@ -782,14 +782,14 @@ impl Surface {
fn validate_from_metal<L>(
instance: &Instance,
_layer: *const L,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
if !instance.enabled_extensions().ext_metal_surface {
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"ext_metal_surface",
)])]),
..Default::default()
});
}));
}
Ok(())
@ -800,7 +800,7 @@ impl Surface {
instance: Arc<Instance>,
layer: *const L,
object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, RuntimeError> {
) -> Result<Arc<Self>, VulkanError> {
let create_info = ash::vk::MetalSurfaceCreateInfoEXT {
flags: ash::vk::MetalSurfaceCreateFlagsEXT::empty(),
p_layer: layer as *const _,
@ -817,7 +817,7 @@ impl Surface {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -842,7 +842,7 @@ impl Surface {
context: *const C,
window: *const W,
object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, VulkanError> {
) -> Result<Arc<Self>, Validated<VulkanError>> {
Self::validate_from_qnx_screen(&instance, context, window)?;
Ok(Self::from_qnx_screen_unchecked(
@ -854,14 +854,14 @@ impl Surface {
instance: &Instance,
_context: *const C,
_window: *const W,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
if !instance.enabled_extensions().qnx_screen_surface {
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"qnx_screen_surface",
)])]),
..Default::default()
});
}));
}
// VUID-VkScreenSurfaceCreateInfoQNX-context-04741
@ -879,7 +879,7 @@ impl Surface {
context: *const C,
window: *const W,
object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, RuntimeError> {
) -> Result<Arc<Self>, VulkanError> {
let create_info = ash::vk::ScreenSurfaceCreateInfoQNX {
flags: ash::vk::ScreenSurfaceCreateFlagsQNX::empty(),
context: context as *mut _,
@ -897,7 +897,7 @@ impl Surface {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -920,20 +920,23 @@ impl Surface {
instance: Arc<Instance>,
window: *const W,
object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, VulkanError> {
) -> Result<Arc<Self>, Validated<VulkanError>> {
Self::validate_from_vi(&instance, window)?;
Ok(Self::from_vi_unchecked(instance, window, object)?)
}
fn validate_from_vi<W>(instance: &Instance, _window: *const W) -> Result<(), ValidationError> {
fn validate_from_vi<W>(
instance: &Instance,
_window: *const W,
) -> Result<(), Box<ValidationError>> {
if !instance.enabled_extensions().nn_vi_surface {
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"nn_vi_surface",
)])]),
..Default::default()
});
}));
}
// VUID-VkViSurfaceCreateInfoNN-window-01318
@ -947,7 +950,7 @@ impl Surface {
instance: Arc<Instance>,
window: *const W,
object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, RuntimeError> {
) -> Result<Arc<Self>, VulkanError> {
let create_info = ash::vk::ViSurfaceCreateInfoNN {
flags: ash::vk::ViSurfaceCreateFlagsNN::empty(),
window: window as *mut _,
@ -964,7 +967,7 @@ impl Surface {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -991,7 +994,7 @@ impl Surface {
display: *const D,
surface: *const S,
object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, VulkanError> {
) -> Result<Arc<Self>, Validated<VulkanError>> {
Self::validate_from_wayland(&instance, display, surface)?;
Ok(Self::from_wayland_unchecked(
@ -1003,14 +1006,14 @@ impl Surface {
instance: &Instance,
_display: *const D,
_surface: *const S,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
if !instance.enabled_extensions().khr_wayland_surface {
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"khr_wayland_surface",
)])]),
..Default::default()
});
}));
}
// VUID-VkWaylandSurfaceCreateInfoKHR-display-01304
@ -1028,7 +1031,7 @@ impl Surface {
display: *const D,
surface: *const S,
object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, RuntimeError> {
) -> Result<Arc<Self>, VulkanError> {
let create_info = ash::vk::WaylandSurfaceCreateInfoKHR {
flags: ash::vk::WaylandSurfaceCreateFlagsKHR::empty(),
display: display as *mut _,
@ -1046,7 +1049,7 @@ impl Surface {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -1073,7 +1076,7 @@ impl Surface {
hinstance: *const I,
hwnd: *const W,
object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, VulkanError> {
) -> Result<Arc<Self>, Validated<VulkanError>> {
Self::validate_from_win32(&instance, hinstance, hwnd)?;
Ok(Self::from_win32_unchecked(
@ -1085,14 +1088,14 @@ impl Surface {
instance: &Instance,
_hinstance: *const I,
_hwnd: *const W,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
if !instance.enabled_extensions().khr_win32_surface {
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"khr_win32_surface",
)])]),
..Default::default()
});
}));
}
// VUID-VkWin32SurfaceCreateInfoKHR-hinstance-01307
@ -1110,7 +1113,7 @@ impl Surface {
hinstance: *const I,
hwnd: *const W,
object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, RuntimeError> {
) -> Result<Arc<Self>, VulkanError> {
let create_info = ash::vk::Win32SurfaceCreateInfoKHR {
flags: ash::vk::Win32SurfaceCreateFlagsKHR::empty(),
hinstance: hinstance as *mut _,
@ -1128,7 +1131,7 @@ impl Surface {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -1155,7 +1158,7 @@ impl Surface {
connection: *const C,
window: ash::vk::xcb_window_t,
object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, VulkanError> {
) -> Result<Arc<Self>, Validated<VulkanError>> {
Self::validate_from_xcb(&instance, connection, window)?;
Ok(Self::from_xcb_unchecked(
@ -1167,14 +1170,14 @@ impl Surface {
instance: &Instance,
_connection: *const C,
_window: ash::vk::xcb_window_t,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
if !instance.enabled_extensions().khr_xcb_surface {
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"khr_xcb_surface",
)])]),
..Default::default()
});
}));
}
// VUID-VkXcbSurfaceCreateInfoKHR-connection-01310
@ -1192,7 +1195,7 @@ impl Surface {
connection: *const C,
window: ash::vk::xcb_window_t,
object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, RuntimeError> {
) -> Result<Arc<Self>, VulkanError> {
let create_info = ash::vk::XcbSurfaceCreateInfoKHR {
flags: ash::vk::XcbSurfaceCreateFlagsKHR::empty(),
connection: connection as *mut _,
@ -1210,7 +1213,7 @@ impl Surface {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -1237,7 +1240,7 @@ impl Surface {
display: *const D,
window: ash::vk::Window,
object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, VulkanError> {
) -> Result<Arc<Self>, Validated<VulkanError>> {
Self::validate_from_xlib(&instance, display, window)?;
Ok(Self::from_xlib_unchecked(
@ -1249,14 +1252,14 @@ impl Surface {
instance: &Instance,
_display: *const D,
_window: ash::vk::Window,
) -> Result<(), ValidationError> {
) -> Result<(), Box<ValidationError>> {
if !instance.enabled_extensions().khr_xlib_surface {
return Err(ValidationError {
return Err(Box::new(ValidationError {
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::InstanceExtension(
"khr_xlib_surface",
)])]),
..Default::default()
});
}));
}
// VUID-VkXlibSurfaceCreateInfoKHR-dpy-01313
@ -1274,7 +1277,7 @@ impl Surface {
display: *const D,
window: ash::vk::Window,
object: Option<Arc<dyn Any + Send + Sync>>,
) -> Result<Arc<Self>, RuntimeError> {
) -> Result<Arc<Self>, VulkanError> {
let create_info = ash::vk::XlibSurfaceCreateInfoKHR {
flags: ash::vk::XlibSurfaceCreateFlagsKHR::empty(),
dpy: display as *mut _,
@ -1292,7 +1295,7 @@ impl Surface {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -1850,7 +1853,10 @@ impl Default for SurfaceInfo {
}
impl SurfaceInfo {
pub(crate) fn validate(&self, physical_device: &PhysicalDevice) -> Result<(), ValidationError> {
pub(crate) fn validate(
&self,
physical_device: &PhysicalDevice,
) -> Result<(), Box<ValidationError>> {
let &Self {
present_mode,
full_screen_exclusive,
@ -1864,14 +1870,14 @@ impl SurfaceInfo {
.enabled_extensions()
.ext_surface_maintenance1
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "present_mode".into(),
problem: "is `Some`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[
Requires::InstanceExtension("ext_surface_maintenance1"),
])]),
..Default::default()
});
}));
}
present_mode
@ -1888,14 +1894,14 @@ impl SurfaceInfo {
.supported_extensions()
.ext_full_screen_exclusive
{
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "full_screen_exclusive".into(),
problem: "is not `FullScreenExclusive::Default`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceExtension(
"ext_full_screen_exclusive",
)])]),
..Default::default()
});
}));
}
Ok(())
@ -2029,7 +2035,7 @@ pub struct SurfaceCapabilities {
#[cfg(test)]
mod tests {
use crate::{
swapchain::Surface, Requires, RequiresAllOf, RequiresOneOf, ValidationError, VulkanError,
swapchain::Surface, Requires, RequiresAllOf, RequiresOneOf, Validated, ValidationError,
};
use std::ptr;
@ -2037,11 +2043,16 @@ mod tests {
fn khr_win32_surface_ext_missing() {
let instance = instance!();
match unsafe { Surface::from_win32(instance, ptr::null::<u8>(), ptr::null::<u8>(), None) } {
Err(VulkanError::ValidationError(ValidationError {
requires_one_of:
RequiresOneOf([RequiresAllOf([Requires::InstanceExtension("khr_win32_surface")])]),
..
})) => (),
Err(Validated::ValidationError(err))
if matches!(
*err,
ValidationError {
requires_one_of: RequiresOneOf([RequiresAllOf([
Requires::InstanceExtension("khr_win32_surface")
])]),
..
}
) => {}
_ => panic!(),
}
}
@ -2050,11 +2061,16 @@ mod tests {
fn khr_xcb_surface_ext_missing() {
let instance = instance!();
match unsafe { Surface::from_xcb(instance, ptr::null::<u8>(), 0, None) } {
Err(VulkanError::ValidationError(ValidationError {
requires_one_of:
RequiresOneOf([RequiresAllOf([Requires::InstanceExtension("khr_xcb_surface")])]),
..
})) => (),
Err(Validated::ValidationError(err))
if matches!(
*err,
ValidationError {
requires_one_of: RequiresOneOf([RequiresAllOf([
Requires::InstanceExtension("khr_xcb_surface")
])]),
..
}
) => {}
_ => panic!(),
}
}
@ -2063,11 +2079,16 @@ mod tests {
fn khr_xlib_surface_ext_missing() {
let instance = instance!();
match unsafe { Surface::from_xlib(instance, ptr::null::<u8>(), 0, None) } {
Err(VulkanError::ValidationError(ValidationError {
requires_one_of:
RequiresOneOf([RequiresAllOf([Requires::InstanceExtension("khr_xlib_surface")])]),
..
})) => (),
Err(Validated::ValidationError(err))
if matches!(
*err,
ValidationError {
requires_one_of: RequiresOneOf([RequiresAllOf([
Requires::InstanceExtension("khr_xlib_surface")
])]),
..
}
) => {}
_ => panic!(),
}
}
@ -2077,11 +2098,16 @@ mod tests {
let instance = instance!();
match unsafe { Surface::from_wayland(instance, ptr::null::<u8>(), ptr::null::<u8>(), None) }
{
Err(VulkanError::ValidationError(ValidationError {
requires_one_of:
RequiresOneOf([RequiresAllOf([Requires::InstanceExtension("khr_wayland_surface")])]),
..
})) => (),
Err(Validated::ValidationError(err))
if matches!(
*err,
ValidationError {
requires_one_of: RequiresOneOf([RequiresAllOf([
Requires::InstanceExtension("khr_wayland_surface")
])]),
..
}
) => {}
_ => panic!(),
}
}
@ -2090,11 +2116,16 @@ mod tests {
fn khr_android_surface_ext_missing() {
let instance = instance!();
match unsafe { Surface::from_android(instance, ptr::null::<u8>(), None) } {
Err(VulkanError::ValidationError(ValidationError {
requires_one_of:
RequiresOneOf([RequiresAllOf([Requires::InstanceExtension("khr_android_surface")])]),
..
})) => (),
Err(Validated::ValidationError(err))
if matches!(
*err,
ValidationError {
requires_one_of: RequiresOneOf([RequiresAllOf([
Requires::InstanceExtension("khr_android_surface")
])]),
..
}
) => {}
_ => panic!(),
}
}

View File

@ -28,7 +28,7 @@ use crate::{
device::{Device, DeviceOwned},
instance::InstanceOwnedDebugWrapper,
macros::impl_id_counter,
OomError, Requires, RequiresAllOf, RequiresOneOf, RuntimeError, VulkanObject,
OomError, Requires, RequiresAllOf, RequiresOneOf, VulkanError, VulkanObject,
};
use std::{
error::Error,
@ -86,7 +86,7 @@ impl Event {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -114,7 +114,7 @@ impl Event {
let fns = device.fns();
(fns.v1_0.reset_event)(device.handle(), handle)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
}
Event {
handle,
@ -163,7 +163,7 @@ impl Event {
match result {
ash::vk::Result::EVENT_SET => Ok(true),
ash::vk::Result::EVENT_RESET => Ok(false),
err => Err(RuntimeError::from(err).into()),
err => Err(VulkanError::from(err).into()),
}
}
}
@ -175,7 +175,7 @@ impl Event {
let fns = self.device.fns();
(fns.v1_0.set_event)(self.device.handle(), self.handle)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
Ok(())
}
}
@ -199,7 +199,7 @@ impl Event {
let fns = self.device.fns();
(fns.v1_0.reset_event)(self.device.handle(), self.handle)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
Ok(())
}
}
@ -299,10 +299,10 @@ impl Display for EventError {
}
}
impl From<RuntimeError> for EventError {
fn from(err: RuntimeError) -> Self {
impl From<VulkanError> for EventError {
fn from(err: VulkanError) -> Self {
match err {
e @ RuntimeError::OutOfHostMemory | e @ RuntimeError::OutOfDeviceMemory => {
e @ VulkanError::OutOfHostMemory | e @ VulkanError::OutOfDeviceMemory => {
Self::OomError(e.into())
}
_ => panic!("unexpected error: {:?}", err),

View File

@ -14,8 +14,8 @@ use crate::{
device::{physical::PhysicalDevice, Device, DeviceOwned, Queue},
instance::InstanceOwnedDebugWrapper,
macros::{impl_id_counter, vulkan_bitflags, vulkan_bitflags_enum},
OomError, RequirementNotMet, Requires, RequiresAllOf, RequiresOneOf, RuntimeError,
ValidationError, Version, VulkanObject,
OomError, RequirementNotMet, Requires, RequiresAllOf, RequiresOneOf, ValidationError, Version,
VulkanError, VulkanObject,
};
use parking_lot::{Mutex, MutexGuard};
use smallvec::SmallVec;
@ -132,7 +132,7 @@ impl Fence {
pub unsafe fn new_unchecked(
device: Arc<Device>,
create_info: FenceCreateInfo,
) -> Result<Fence, RuntimeError> {
) -> Result<Fence, VulkanError> {
let FenceCreateInfo {
signaled,
export_handle_types,
@ -173,7 +173,7 @@ impl Fence {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -207,7 +207,7 @@ impl Fence {
let fns = device.fns();
(fns.v1_0.reset_fences)(device.handle(), 1, &handle)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
}
Fence {
@ -282,7 +282,7 @@ impl Fence {
match result {
ash::vk::Result::SUCCESS => unsafe { state.set_signaled() },
ash::vk::Result::NOT_READY => return Ok(false),
err => return Err(RuntimeError::from(err).into()),
err => return Err(VulkanError::from(err).into()),
}
};
@ -332,7 +332,7 @@ impl Fence {
match result {
ash::vk::Result::SUCCESS => unsafe { state.set_signaled() },
ash::vk::Result::TIMEOUT => return Err(FenceError::Timeout),
err => return Err(RuntimeError::from(err).into()),
err => return Err(VulkanError::from(err).into()),
}
};
@ -434,7 +434,7 @@ impl Fence {
.filter_map(|(fence, state)| state.set_signaled().map(|state| (state, fence)))
.collect(),
ash::vk::Result::TIMEOUT => return Err(FenceError::Timeout),
err => return Err(RuntimeError::from(err).into()),
err => return Err(VulkanError::from(err).into()),
}
};
@ -469,17 +469,17 @@ impl Fence {
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
#[inline]
pub unsafe fn reset_unchecked(&self) -> Result<(), RuntimeError> {
pub unsafe fn reset_unchecked(&self) -> Result<(), VulkanError> {
let mut state = self.state.lock();
self.reset_unchecked_locked(&mut state)
}
unsafe fn reset_unchecked_locked(&self, state: &mut FenceState) -> Result<(), RuntimeError> {
unsafe fn reset_unchecked_locked(&self, state: &mut FenceState) -> Result<(), VulkanError> {
let fns = self.device.fns();
(fns.v1_0.reset_fences)(self.device.handle(), 1, &self.handle)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
state.reset();
@ -532,7 +532,7 @@ impl Fence {
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
pub unsafe fn multi_reset_unchecked<'a>(
fences: impl IntoIterator<Item = &'a Fence>,
) -> Result<(), RuntimeError> {
) -> Result<(), VulkanError> {
let (fences, mut states): (SmallVec<[_; 8]>, SmallVec<[_; 8]>) = fences
.into_iter()
.map(|fence| {
@ -547,7 +547,7 @@ impl Fence {
unsafe fn multi_reset_unchecked_locked(
fences: &[&Fence],
states: &mut [MutexGuard<'_, FenceState>],
) -> Result<(), RuntimeError> {
) -> Result<(), VulkanError> {
if fences.is_empty() {
return Ok(());
}
@ -558,7 +558,7 @@ impl Fence {
let fns = device.fns();
(fns.v1_0.reset_fences)(device.handle(), fences_vk.len() as u32, fences_vk.as_ptr())
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
for state in states {
state.reset();
@ -654,7 +654,7 @@ impl Fence {
pub unsafe fn export_fd_unchecked(
&self,
handle_type: ExternalFenceHandleType,
) -> Result<File, RuntimeError> {
) -> Result<File, VulkanError> {
let mut state = self.state.lock();
self.export_fd_unchecked_locked(handle_type, &mut state)
}
@ -664,7 +664,7 @@ impl Fence {
&self,
handle_type: ExternalFenceHandleType,
state: &mut FenceState,
) -> Result<File, RuntimeError> {
) -> Result<File, VulkanError> {
use std::os::unix::io::FromRawFd;
let info_vk = ash::vk::FenceGetFdInfoKHR {
@ -681,7 +681,7 @@ impl Fence {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
state.export(handle_type);
@ -785,7 +785,7 @@ impl Fence {
pub unsafe fn export_win32_handle_unchecked(
&self,
handle_type: ExternalFenceHandleType,
) -> Result<*mut std::ffi::c_void, RuntimeError> {
) -> Result<*mut std::ffi::c_void, VulkanError> {
let mut state = self.state.lock();
self.export_win32_handle_unchecked_locked(handle_type, &mut state)
}
@ -795,7 +795,7 @@ impl Fence {
&self,
handle_type: ExternalFenceHandleType,
state: &mut FenceState,
) -> Result<*mut std::ffi::c_void, RuntimeError> {
) -> Result<*mut std::ffi::c_void, VulkanError> {
let info_vk = ash::vk::FenceGetWin32HandleInfoKHR {
fence: self.handle,
handle_type: handle_type.into(),
@ -810,7 +810,7 @@ impl Fence {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
state.export(handle_type);
@ -897,7 +897,7 @@ impl Fence {
pub unsafe fn import_fd_unchecked(
&self,
import_fence_fd_info: ImportFenceFdInfo,
) -> Result<(), RuntimeError> {
) -> Result<(), VulkanError> {
let mut state = self.state.lock();
self.import_fd_unchecked_locked(import_fence_fd_info, &mut state)
}
@ -907,7 +907,7 @@ impl Fence {
&self,
import_fence_fd_info: ImportFenceFdInfo,
state: &mut FenceState,
) -> Result<(), RuntimeError> {
) -> Result<(), VulkanError> {
use std::os::unix::io::IntoRawFd;
let ImportFenceFdInfo {
@ -928,7 +928,7 @@ impl Fence {
let fns = self.device.fns();
(fns.khr_external_fence_fd.import_fence_fd_khr)(self.device.handle(), &info_vk)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
state.import(handle_type, flags.intersects(FenceImportFlags::TEMPORARY));
@ -1015,7 +1015,7 @@ impl Fence {
pub unsafe fn import_win32_handle_unchecked(
&self,
import_fence_win32_handle_info: ImportFenceWin32HandleInfo,
) -> Result<(), RuntimeError> {
) -> Result<(), VulkanError> {
let mut state = self.state.lock();
self.import_win32_handle_unchecked_locked(import_fence_win32_handle_info, &mut state)
}
@ -1025,7 +1025,7 @@ impl Fence {
&self,
import_fence_win32_handle_info: ImportFenceWin32HandleInfo,
state: &mut FenceState,
) -> Result<(), RuntimeError> {
) -> Result<(), VulkanError> {
let ImportFenceWin32HandleInfo {
flags,
handle_type,
@ -1048,7 +1048,7 @@ impl Fence {
&info_vk,
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
state.import(handle_type, flags.intersects(FenceImportFlags::TEMPORARY));
@ -1420,7 +1420,10 @@ impl ExternalFenceInfo {
}
}
pub(crate) fn validate(&self, physical_device: &PhysicalDevice) -> Result<(), ValidationError> {
pub(crate) fn validate(
&self,
physical_device: &PhysicalDevice,
) -> Result<(), Box<ValidationError>> {
let &Self {
handle_type,
_ne: _,
@ -1595,13 +1598,13 @@ impl Display for FenceError {
}
}
impl From<RuntimeError> for FenceError {
fn from(err: RuntimeError) -> Self {
impl From<VulkanError> for FenceError {
fn from(err: VulkanError) -> Self {
match err {
e @ RuntimeError::OutOfHostMemory | e @ RuntimeError::OutOfDeviceMemory => {
e @ VulkanError::OutOfHostMemory | e @ VulkanError::OutOfDeviceMemory => {
Self::OomError(e.into())
}
RuntimeError::DeviceLost => Self::DeviceLost,
VulkanError::DeviceLost => Self::DeviceLost,
_ => panic!("unexpected error: {:?}", err),
}
}

View File

@ -110,7 +110,7 @@ use crate::{
image::{Image, ImageLayout},
memory::BindSparseInfo,
swapchain::{self, PresentFuture, PresentInfo, Swapchain, SwapchainPresentInfo},
DeviceSize, OomError, RuntimeError,
DeviceSize, OomError, VulkanError,
};
use smallvec::SmallVec;
use std::{
@ -672,16 +672,16 @@ impl From<AccessError> for FlushError {
}
}
impl From<RuntimeError> for FlushError {
fn from(err: RuntimeError) -> Self {
impl From<VulkanError> for FlushError {
fn from(err: VulkanError) -> Self {
match err {
RuntimeError::OutOfHostMemory | RuntimeError::OutOfDeviceMemory => {
VulkanError::OutOfHostMemory | VulkanError::OutOfDeviceMemory => {
Self::OomError(err.into())
}
RuntimeError::DeviceLost => Self::DeviceLost,
RuntimeError::SurfaceLost => Self::SurfaceLost,
RuntimeError::OutOfDate => Self::OutOfDate,
RuntimeError::FullScreenExclusiveModeLost => Self::FullScreenExclusiveModeLost,
VulkanError::DeviceLost => Self::DeviceLost,
VulkanError::SurfaceLost => Self::SurfaceLost,
VulkanError::OutOfDate => Self::OutOfDate,
VulkanError::FullScreenExclusiveModeLost => Self::FullScreenExclusiveModeLost,
_ => panic!("unexpected error: {:?}", err),
}
}

View File

@ -25,7 +25,7 @@ pub use self::{
MemoryBarrier, PipelineStage, PipelineStages, QueueFamilyOwnershipTransfer,
},
};
use crate::{device::Queue, RuntimeError, ValidationError};
use crate::{device::Queue, ValidationError, VulkanError};
use std::{
error::Error,
fmt::{Display, Formatter},
@ -103,7 +103,7 @@ pub(crate) enum CurrentAccess {
#[derive(Clone, Debug)]
pub enum HostAccessError {
AccessConflict(AccessConflict),
Invalidate(RuntimeError),
Invalidate(VulkanError),
ValidationError(ValidationError),
}

View File

@ -1862,7 +1862,7 @@ impl Default for MemoryBarrier {
}
impl MemoryBarrier {
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
pub(crate) fn validate(&self, device: &Device) -> Result<(), Box<ValidationError>> {
let &Self {
src_stages,
src_access,
@ -1905,71 +1905,71 @@ impl MemoryBarrier {
if !device.enabled_features().synchronization2 {
if src_stages.contains_flags2() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains flags from `VkPipelineStageFlagBits2`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"synchronization2",
)])]),
..Default::default()
});
}));
}
if dst_stages.contains_flags2() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains flags from `VkPipelineStageFlagBits2`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"synchronization2",
)])]),
..Default::default()
});
}));
}
if src_access.contains_flags2() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "src_access".into(),
problem: "contains flags from `VkAccessFlagBits2`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"synchronization2",
)])]),
..Default::default()
});
}));
}
if dst_access.contains_flags2() {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "dst_access".into(),
problem: "contains flags from `VkAccessFlagBits2`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"synchronization2",
)])]),
..Default::default()
});
}));
}
}
if !device.enabled_features().geometry_shader {
if src_stages.intersects(PipelineStages::GEOMETRY_SHADER) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::GEOMETRY_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"geometry_shader",
)])]),
vuids: &["VUID-VkMemoryBarrier2-srcStageMask-03929"],
});
}));
}
if dst_stages.intersects(PipelineStages::GEOMETRY_SHADER) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::GEOMETRY_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"geometry_shader",
)])]),
vuids: &["VUID-VkMemoryBarrier2-dstStageMask-03929"],
});
}));
}
}
@ -1978,7 +1978,7 @@ impl MemoryBarrier {
PipelineStages::TESSELLATION_CONTROL_SHADER
| PipelineStages::TESSELLATION_EVALUATION_SHADER,
) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::TESSELLATION_CONTROL_SHADER` or \
`PipelineStages::TESSELLATION_EVALUATION_SHADER`"
@ -1987,14 +1987,14 @@ impl MemoryBarrier {
"tessellation_shader",
)])]),
vuids: &["VUID-VkMemoryBarrier2-srcStageMask-03930"],
});
}));
}
if dst_stages.intersects(
PipelineStages::TESSELLATION_CONTROL_SHADER
| PipelineStages::TESSELLATION_EVALUATION_SHADER,
) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::TESSELLATION_CONTROL_SHADER` or \
`PipelineStages::TESSELLATION_EVALUATION_SHADER`"
@ -2003,127 +2003,127 @@ impl MemoryBarrier {
"tessellation_shader",
)])]),
vuids: &["VUID-VkMemoryBarrier2-dstStageMask-03930"],
});
}));
}
}
if !device.enabled_features().conditional_rendering {
if src_stages.intersects(PipelineStages::CONDITIONAL_RENDERING) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::CONDITIONAL_RENDERING`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"conditional_rendering",
)])]),
vuids: &["VUID-VkMemoryBarrier2-srcStageMask-03931"],
});
}));
}
if dst_stages.intersects(PipelineStages::CONDITIONAL_RENDERING) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::CONDITIONAL_RENDERING`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"conditional_rendering",
)])]),
vuids: &["VUID-VkMemoryBarrier2-dstStageMask-03931"],
});
}));
}
}
if !device.enabled_features().fragment_density_map {
if src_stages.intersects(PipelineStages::FRAGMENT_DENSITY_PROCESS) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::FRAGMENT_DENSITY_PROCESS`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"fragment_density_map",
)])]),
vuids: &["VUID-VkMemoryBarrier2-srcStageMask-03932"],
});
}));
}
if dst_stages.intersects(PipelineStages::FRAGMENT_DENSITY_PROCESS) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::FRAGMENT_DENSITY_PROCESS`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"fragment_density_map",
)])]),
vuids: &["VUID-VkMemoryBarrier2-dstStageMask-03932"],
});
}));
}
}
if !device.enabled_features().transform_feedback {
if src_stages.intersects(PipelineStages::TRANSFORM_FEEDBACK) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::TRANSFORM_FEEDBACK`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"transform_feedback",
)])]),
vuids: &["VUID-VkMemoryBarrier2-srcStageMask-03933"],
});
}));
}
if dst_stages.intersects(PipelineStages::TRANSFORM_FEEDBACK) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::TRANSFORM_FEEDBACK`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"transform_feedback",
)])]),
vuids: &["VUID-VkMemoryBarrier2-dstStageMask-03933"],
});
}));
}
}
if !device.enabled_features().mesh_shader {
if src_stages.intersects(PipelineStages::MESH_SHADER) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::MESH_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"mesh_shader",
)])]),
vuids: &["VUID-VkMemoryBarrier2-srcStageMask-03934"],
});
}));
}
if dst_stages.intersects(PipelineStages::MESH_SHADER) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::MESH_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"mesh_shader",
)])]),
vuids: &["VUID-VkMemoryBarrier2-dstStageMask-03934"],
});
}));
}
}
if !device.enabled_features().task_shader {
if src_stages.intersects(PipelineStages::TASK_SHADER) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::TASK_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"task_shader",
)])]),
vuids: &["VUID-VkMemoryBarrier2-srcStageMask-03935"],
});
}));
}
if dst_stages.intersects(PipelineStages::TASK_SHADER) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::TASK_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"task_shader",
)])]),
vuids: &["VUID-VkMemoryBarrier2-dstStageMask-03935"],
});
}));
}
}
@ -2131,7 +2131,7 @@ impl MemoryBarrier {
|| device.enabled_features().shading_rate_image)
{
if src_stages.intersects(PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT`".into(),
requires_one_of: RequiresOneOf(&[
@ -2139,11 +2139,11 @@ impl MemoryBarrier {
RequiresAllOf(&[Requires::Feature("shading_rate_image")]),
]),
vuids: &["VUID-VkMemoryBarrier2-shadingRateImage-07316"],
});
}));
}
if dst_stages.intersects(PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::FRAGMENT_SHADING_RATE_ATTACHMENT`".into(),
requires_one_of: RequiresOneOf(&[
@ -2151,55 +2151,55 @@ impl MemoryBarrier {
RequiresAllOf(&[Requires::Feature("shading_rate_image")]),
]),
vuids: &["VUID-VkMemoryBarrier2-shadingRateImage-07316"],
});
}));
}
}
if !device.enabled_features().subpass_shading {
if src_stages.intersects(PipelineStages::SUBPASS_SHADING) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::SUBPASS_SHADING`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"subpass_shading",
)])]),
vuids: &["VUID-VkMemoryBarrier2-srcStageMask-04957"],
});
}));
}
if dst_stages.intersects(PipelineStages::SUBPASS_SHADING) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::SUBPASS_SHADING`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"subpass_shading",
)])]),
vuids: &["VUID-VkMemoryBarrier2-dstStageMask-04957"],
});
}));
}
}
if !device.enabled_features().invocation_mask {
if src_stages.intersects(PipelineStages::INVOCATION_MASK) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::INVOCATION_MASK`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"invocation_mask",
)])]),
vuids: &["VUID-VkMemoryBarrier2-srcStageMask-04995"],
});
}));
}
if dst_stages.intersects(PipelineStages::INVOCATION_MASK) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::INVOCATION_MASK`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"invocation_mask",
)])]),
vuids: &["VUID-VkMemoryBarrier2-dstStageMask-04995"],
});
}));
}
}
@ -2207,30 +2207,30 @@ impl MemoryBarrier {
|| device.enabled_features().ray_tracing_pipeline)
{
if src_stages.intersects(PipelineStages::RAY_TRACING_SHADER) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "src_stages".into(),
problem: "contains `PipelineStages::RAY_TRACING_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"ray_tracing_pipeline",
)])]),
vuids: &["VUID-VkMemoryBarrier2-srcStageMask-07946"],
});
}));
}
if dst_stages.intersects(PipelineStages::RAY_TRACING_SHADER) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
context: "dst_stages".into(),
problem: "contains `PipelineStages::RAY_TRACING_SHADER`".into(),
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
"ray_tracing_pipeline",
)])]),
vuids: &["VUID-VkMemoryBarrier2-dstStageMask-07946"],
});
}));
}
}
if !AccessFlags::from(src_stages).contains(src_access) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`src_access` contains one or more access types that are not performed \
by any stage in `src_stages`"
.into(),
@ -2278,11 +2278,11 @@ impl MemoryBarrier {
"VUID-VkMemoryBarrier2-srcAccessMask-08118",
],
..Default::default()
});
}));
}
if !AccessFlags::from(dst_stages).contains(dst_access) {
return Err(ValidationError {
return Err(Box::new(ValidationError {
problem: "`dst_access` contains one or more access types that are not performed \
by any stage in `dst_stages`"
.into(),
@ -2330,7 +2330,7 @@ impl MemoryBarrier {
"VUID-VkMemoryBarrier2-dstAccessMask-08118",
],
..Default::default()
});
}));
}
Ok(())

View File

@ -14,8 +14,8 @@ use crate::{
device::{physical::PhysicalDevice, Device, DeviceOwned, Queue},
instance::InstanceOwnedDebugWrapper,
macros::{impl_id_counter, vulkan_bitflags, vulkan_bitflags_enum},
OomError, RequirementNotMet, Requires, RequiresAllOf, RequiresOneOf, RuntimeError,
ValidationError, Version, VulkanObject,
OomError, RequirementNotMet, Requires, RequiresAllOf, RequiresOneOf, ValidationError, Version,
VulkanError, VulkanObject,
};
use parking_lot::{Mutex, MutexGuard};
#[cfg(unix)]
@ -113,7 +113,7 @@ impl Semaphore {
pub unsafe fn new_unchecked(
device: Arc<Device>,
create_info: SemaphoreCreateInfo,
) -> Result<Semaphore, RuntimeError> {
) -> Result<Semaphore, VulkanError> {
let SemaphoreCreateInfo {
export_handle_types,
_ne: _,
@ -147,7 +147,7 @@ impl Semaphore {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
output.assume_init()
};
@ -310,7 +310,7 @@ impl Semaphore {
pub unsafe fn export_fd_unchecked(
&self,
handle_type: ExternalSemaphoreHandleType,
) -> Result<File, RuntimeError> {
) -> Result<File, VulkanError> {
let mut state = self.state.lock();
self.export_fd_unchecked_locked(handle_type, &mut state)
}
@ -320,7 +320,7 @@ impl Semaphore {
&self,
handle_type: ExternalSemaphoreHandleType,
state: &mut SemaphoreState,
) -> Result<File, RuntimeError> {
) -> Result<File, VulkanError> {
use std::os::unix::io::FromRawFd;
let info = ash::vk::SemaphoreGetFdInfoKHR {
@ -337,7 +337,7 @@ impl Semaphore {
output.as_mut_ptr(),
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
state.export(handle_type);
@ -454,7 +454,7 @@ impl Semaphore {
pub unsafe fn export_win32_handle_unchecked(
&self,
handle_type: ExternalSemaphoreHandleType,
) -> Result<*mut std::ffi::c_void, RuntimeError> {
) -> Result<*mut std::ffi::c_void, VulkanError> {
let mut state = self.state.lock();
self.export_win32_handle_unchecked_locked(handle_type, &mut state)
}
@ -464,7 +464,7 @@ impl Semaphore {
&self,
handle_type: ExternalSemaphoreHandleType,
state: &mut SemaphoreState,
) -> Result<*mut std::ffi::c_void, RuntimeError> {
) -> Result<*mut std::ffi::c_void, VulkanError> {
let info_vk = ash::vk::SemaphoreGetWin32HandleInfoKHR {
semaphore: self.handle,
handle_type: handle_type.into(),
@ -478,7 +478,7 @@ impl Semaphore {
self.device.handle(), &info_vk, output.as_mut_ptr()
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
state.export(handle_type);
@ -574,7 +574,7 @@ impl Semaphore {
pub unsafe fn export_zircon_handle_unchecked(
&self,
handle_type: ExternalSemaphoreHandleType,
) -> Result<ash::vk::zx_handle_t, RuntimeError> {
) -> Result<ash::vk::zx_handle_t, VulkanError> {
let mut state = self.state.lock();
self.export_zircon_handle_unchecked_locked(handle_type, &mut state)
}
@ -584,7 +584,7 @@ impl Semaphore {
&self,
handle_type: ExternalSemaphoreHandleType,
state: &mut SemaphoreState,
) -> Result<ash::vk::zx_handle_t, RuntimeError> {
) -> Result<ash::vk::zx_handle_t, VulkanError> {
let info = ash::vk::SemaphoreGetZirconHandleInfoFUCHSIA {
semaphore: self.handle,
handle_type: handle_type.into(),
@ -598,7 +598,7 @@ impl Semaphore {
self.device.handle(), &info, output.as_mut_ptr()
)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
state.export(handle_type);
@ -688,7 +688,7 @@ impl Semaphore {
pub unsafe fn import_fd_unchecked(
&self,
import_semaphore_fd_info: ImportSemaphoreFdInfo,
) -> Result<(), RuntimeError> {
) -> Result<(), VulkanError> {
let mut state = self.state.lock();
self.import_fd_unchecked_locked(import_semaphore_fd_info, &mut state)
}
@ -698,7 +698,7 @@ impl Semaphore {
&self,
import_semaphore_fd_info: ImportSemaphoreFdInfo,
state: &mut SemaphoreState,
) -> Result<(), RuntimeError> {
) -> Result<(), VulkanError> {
use std::os::unix::io::IntoRawFd;
let ImportSemaphoreFdInfo {
@ -719,7 +719,7 @@ impl Semaphore {
let fns = self.device.fns();
(fns.khr_external_semaphore_fd.import_semaphore_fd_khr)(self.device.handle(), &info_vk)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
state.import(
handle_type,
@ -817,7 +817,7 @@ impl Semaphore {
pub unsafe fn import_win32_handle_unchecked(
&self,
import_semaphore_win32_handle_info: ImportSemaphoreWin32HandleInfo,
) -> Result<(), RuntimeError> {
) -> Result<(), VulkanError> {
let mut state = self.state.lock();
self.import_win32_handle_unchecked_locked(import_semaphore_win32_handle_info, &mut state)
}
@ -827,7 +827,7 @@ impl Semaphore {
&self,
import_semaphore_win32_handle_info: ImportSemaphoreWin32HandleInfo,
state: &mut SemaphoreState,
) -> Result<(), RuntimeError> {
) -> Result<(), VulkanError> {
let ImportSemaphoreWin32HandleInfo {
flags,
handle_type,
@ -848,7 +848,7 @@ impl Semaphore {
(fns.khr_external_semaphore_win32
.import_semaphore_win32_handle_khr)(self.device.handle(), &info_vk)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
state.import(
handle_type,
@ -938,7 +938,7 @@ impl Semaphore {
pub unsafe fn import_zircon_handle_unchecked(
&self,
import_semaphore_zircon_handle_info: ImportSemaphoreZirconHandleInfo,
) -> Result<(), RuntimeError> {
) -> Result<(), VulkanError> {
let mut state = self.state.lock();
self.import_zircon_handle_unchecked_locked(import_semaphore_zircon_handle_info, &mut state)
}
@ -948,7 +948,7 @@ impl Semaphore {
&self,
import_semaphore_zircon_handle_info: ImportSemaphoreZirconHandleInfo,
state: &mut SemaphoreState,
) -> Result<(), RuntimeError> {
) -> Result<(), VulkanError> {
let ImportSemaphoreZirconHandleInfo {
flags,
handle_type,
@ -968,7 +968,7 @@ impl Semaphore {
(fns.fuchsia_external_semaphore
.import_semaphore_zircon_handle_fuchsia)(self.device.handle(), &info_vk)
.result()
.map_err(RuntimeError::from)?;
.map_err(VulkanError::from)?;
state.import(
handle_type,
@ -1378,7 +1378,10 @@ impl ExternalSemaphoreInfo {
}
}
pub(crate) fn validate(&self, physical_device: &PhysicalDevice) -> Result<(), ValidationError> {
pub(crate) fn validate(
&self,
physical_device: &PhysicalDevice,
) -> Result<(), Box<ValidationError>> {
let &Self {
handle_type,
_ne: _,
@ -1556,10 +1559,10 @@ impl Display for SemaphoreError {
}
}
impl From<RuntimeError> for SemaphoreError {
fn from(err: RuntimeError) -> Self {
impl From<VulkanError> for SemaphoreError {
fn from(err: VulkanError) -> Self {
match err {
e @ RuntimeError::OutOfHostMemory | e @ RuntimeError::OutOfDeviceMemory => {
e @ VulkanError::OutOfHostMemory | e @ VulkanError::OutOfDeviceMemory => {
Self::OomError(e.into())
}
_ => panic!("unexpected error: {:?}", err),