mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-29 02:04:37 +00:00
ValidationError-ify samplers (#2245)
* ValidationError-ify samplers * Fix doctests
This commit is contained in:
parent
e65a2bc1f8
commit
204811de19
@ -63,7 +63,9 @@ use vulkano::{
|
||||
},
|
||||
format::Format,
|
||||
image::{
|
||||
view::ImageView, ImageAccess, ImageDimensions, ImageUsage, StorageImage, SwapchainImage,
|
||||
sampler::{Sampler, SamplerCreateInfo},
|
||||
view::ImageView,
|
||||
ImageAccess, ImageDimensions, ImageUsage, StorageImage, SwapchainImage,
|
||||
},
|
||||
instance::{Instance, InstanceCreateFlags, InstanceCreateInfo},
|
||||
memory::allocator::{AllocationCreateInfo, MemoryUsage, StandardMemoryAllocator},
|
||||
@ -82,7 +84,6 @@ use vulkano::{
|
||||
PipelineShaderStageCreateInfo,
|
||||
},
|
||||
render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass},
|
||||
sampler::{Sampler, SamplerCreateInfo},
|
||||
swapchain::{
|
||||
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
|
||||
SwapchainPresentInfo,
|
||||
|
@ -28,7 +28,11 @@ mod linux {
|
||||
QueueCreateInfo, QueueFlags,
|
||||
},
|
||||
format::Format,
|
||||
image::{view::ImageView, ImageCreateFlags, ImageUsage, StorageImage, SwapchainImage},
|
||||
image::{
|
||||
sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo},
|
||||
view::ImageView,
|
||||
ImageCreateFlags, ImageUsage, StorageImage, SwapchainImage,
|
||||
},
|
||||
instance::{
|
||||
debug::{DebugUtilsMessenger, DebugUtilsMessengerCreateInfo},
|
||||
Instance, InstanceCreateFlags, InstanceCreateInfo, InstanceExtensions,
|
||||
@ -49,7 +53,6 @@ mod linux {
|
||||
PipelineShaderStageCreateInfo,
|
||||
},
|
||||
render_pass::{Framebuffer, RenderPass, Subpass},
|
||||
sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo},
|
||||
swapchain::{AcquireError, Surface, Swapchain, SwapchainCreateInfo, SwapchainPresentInfo},
|
||||
sync::{
|
||||
now,
|
||||
|
@ -25,8 +25,9 @@ use vulkano::{
|
||||
},
|
||||
format::Format,
|
||||
image::{
|
||||
view::ImageView, ImageAccess, ImageDimensions, ImageLayout, ImageUsage, StorageImage,
|
||||
SwapchainImage,
|
||||
sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo},
|
||||
view::ImageView,
|
||||
ImageAccess, ImageDimensions, ImageLayout, ImageUsage, StorageImage, SwapchainImage,
|
||||
},
|
||||
instance::{Instance, InstanceCreateFlags, InstanceCreateInfo},
|
||||
memory::allocator::{AllocationCreateInfo, MemoryUsage, StandardMemoryAllocator},
|
||||
@ -45,7 +46,6 @@ use vulkano::{
|
||||
PipelineShaderStageCreateInfo,
|
||||
},
|
||||
render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass},
|
||||
sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo},
|
||||
swapchain::{
|
||||
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
|
||||
SwapchainPresentInfo,
|
||||
|
@ -23,8 +23,9 @@ use vulkano::{
|
||||
},
|
||||
format::Format,
|
||||
image::{
|
||||
view::ImageView, ImageAccess, ImageDimensions, ImageUsage, ImmutableImage, MipmapsCount,
|
||||
SwapchainImage,
|
||||
sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo},
|
||||
view::ImageView,
|
||||
ImageAccess, ImageDimensions, ImageUsage, ImmutableImage, MipmapsCount, SwapchainImage,
|
||||
},
|
||||
instance::{Instance, InstanceCreateFlags, InstanceCreateInfo},
|
||||
memory::allocator::{AllocationCreateInfo, MemoryUsage, StandardMemoryAllocator},
|
||||
@ -43,7 +44,6 @@ use vulkano::{
|
||||
PipelineShaderStageCreateInfo,
|
||||
},
|
||||
render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass},
|
||||
sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo},
|
||||
swapchain::{
|
||||
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
|
||||
SwapchainPresentInfo,
|
||||
|
@ -32,8 +32,9 @@ use vulkano::{
|
||||
},
|
||||
format::Format,
|
||||
image::{
|
||||
view::ImageView, ImageAccess, ImageDimensions, ImageUsage, ImmutableImage, MipmapsCount,
|
||||
SwapchainImage,
|
||||
sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo},
|
||||
view::ImageView,
|
||||
ImageAccess, ImageDimensions, ImageUsage, ImmutableImage, MipmapsCount, SwapchainImage,
|
||||
},
|
||||
instance::{Instance, InstanceCreateFlags, InstanceCreateInfo},
|
||||
memory::allocator::{AllocationCreateInfo, MemoryUsage, StandardMemoryAllocator},
|
||||
@ -52,7 +53,6 @@ use vulkano::{
|
||||
PipelineShaderStageCreateInfo,
|
||||
},
|
||||
render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass},
|
||||
sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo},
|
||||
swapchain::{
|
||||
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
|
||||
SwapchainPresentInfo,
|
||||
|
@ -18,7 +18,10 @@ use vulkano::{
|
||||
allocator::StandardDescriptorSetAllocator, PersistentDescriptorSet, WriteDescriptorSet,
|
||||
},
|
||||
device::Queue,
|
||||
image::ImageViewAbstract,
|
||||
image::{
|
||||
sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo, SamplerMipmapMode},
|
||||
ImageViewAbstract,
|
||||
},
|
||||
memory::allocator::{AllocationCreateInfo, MemoryAllocator, MemoryUsage},
|
||||
pipeline::{
|
||||
graphics::{
|
||||
@ -35,7 +38,6 @@ use vulkano::{
|
||||
PipelineShaderStageCreateInfo,
|
||||
},
|
||||
render_pass::Subpass,
|
||||
sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo, SamplerMipmapMode},
|
||||
};
|
||||
|
||||
/// Vertex for textured quads.
|
||||
|
@ -19,7 +19,10 @@ use vulkano::{
|
||||
allocator::StandardDescriptorSetAllocator, PersistentDescriptorSet, WriteDescriptorSet,
|
||||
},
|
||||
device::Queue,
|
||||
image::ImageViewAbstract,
|
||||
image::{
|
||||
sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo, SamplerMipmapMode},
|
||||
ImageViewAbstract,
|
||||
},
|
||||
memory::allocator::{AllocationCreateInfo, MemoryUsage},
|
||||
pipeline::{
|
||||
graphics::{
|
||||
@ -36,7 +39,6 @@ use vulkano::{
|
||||
PipelineShaderStageCreateInfo,
|
||||
},
|
||||
render_pass::Subpass,
|
||||
sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo, SamplerMipmapMode},
|
||||
};
|
||||
|
||||
/// Vertex for textured quads.
|
||||
|
@ -21,8 +21,9 @@ use vulkano::{
|
||||
},
|
||||
format::Format,
|
||||
image::{
|
||||
view::ImageView, ImageAccess, ImageDimensions, ImageUsage, ImmutableImage, MipmapsCount,
|
||||
SwapchainImage,
|
||||
sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo},
|
||||
view::ImageView,
|
||||
ImageAccess, ImageDimensions, ImageUsage, ImmutableImage, MipmapsCount, SwapchainImage,
|
||||
},
|
||||
instance::{Instance, InstanceCreateFlags, InstanceCreateInfo},
|
||||
memory::allocator::{AllocationCreateInfo, MemoryUsage, StandardMemoryAllocator},
|
||||
@ -41,7 +42,6 @@ use vulkano::{
|
||||
PipelineShaderStageCreateInfo,
|
||||
},
|
||||
render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass},
|
||||
sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo},
|
||||
swapchain::{
|
||||
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
|
||||
SwapchainPresentInfo,
|
||||
|
@ -24,8 +24,9 @@ use vulkano::{
|
||||
},
|
||||
format::Format,
|
||||
image::{
|
||||
view::ImageView, ImageAccess, ImageDimensions, ImageUsage, ImmutableImage, MipmapsCount,
|
||||
SwapchainImage,
|
||||
sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo},
|
||||
view::ImageView,
|
||||
ImageAccess, ImageDimensions, ImageUsage, ImmutableImage, MipmapsCount, SwapchainImage,
|
||||
},
|
||||
instance::{Instance, InstanceCreateFlags, InstanceCreateInfo},
|
||||
memory::allocator::{AllocationCreateInfo, MemoryUsage, StandardMemoryAllocator},
|
||||
@ -44,7 +45,6 @@ use vulkano::{
|
||||
PipelineShaderStageCreateInfo,
|
||||
},
|
||||
render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass},
|
||||
sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo},
|
||||
swapchain::{
|
||||
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
|
||||
SwapchainPresentInfo,
|
||||
|
@ -23,8 +23,9 @@ use vulkano::{
|
||||
},
|
||||
format::Format,
|
||||
image::{
|
||||
view::ImageView, ImageAccess, ImageDimensions, ImageUsage, ImmutableImage, MipmapsCount,
|
||||
SwapchainImage,
|
||||
sampler::{Sampler, SamplerCreateInfo},
|
||||
view::ImageView,
|
||||
ImageAccess, ImageDimensions, ImageUsage, ImmutableImage, MipmapsCount, SwapchainImage,
|
||||
},
|
||||
instance::{Instance, InstanceCreateFlags, InstanceCreateInfo},
|
||||
memory::allocator::{AllocationCreateInfo, MemoryUsage, StandardMemoryAllocator},
|
||||
@ -43,7 +44,6 @@ use vulkano::{
|
||||
PipelineShaderStageCreateInfo,
|
||||
},
|
||||
render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass},
|
||||
sampler::{Sampler, SamplerCreateInfo},
|
||||
swapchain::{
|
||||
acquire_next_image, AcquireError, Surface, Swapchain, SwapchainCreateInfo,
|
||||
SwapchainPresentInfo,
|
||||
|
@ -322,9 +322,9 @@ mod tests {
|
||||
PersistentDescriptorSet, WriteDescriptorSet,
|
||||
},
|
||||
device::{Device, DeviceCreateInfo, QueueCreateInfo},
|
||||
image::sampler::{Sampler, SamplerCreateInfo},
|
||||
memory::allocator::{AllocationCreateInfo, MemoryUsage, StandardMemoryAllocator},
|
||||
pipeline::{layout::PipelineLayoutCreateInfo, PipelineBindPoint, PipelineLayout},
|
||||
sampler::{Sampler, SamplerCreateInfo},
|
||||
shader::ShaderStages,
|
||||
sync::GpuFuture,
|
||||
};
|
||||
|
@ -16,10 +16,9 @@ use crate::{
|
||||
device::{DeviceOwned, QueueFlags},
|
||||
format::{Format, FormatFeatures, NumericType},
|
||||
image::{
|
||||
ImageAccess, ImageAspects, ImageDimensions, ImageLayout, ImageSubresourceLayers, ImageType,
|
||||
ImageUsage, SampleCount, SampleCounts,
|
||||
sampler::Filter, ImageAccess, ImageAspects, ImageDimensions, ImageLayout,
|
||||
ImageSubresourceLayers, ImageType, ImageUsage, SampleCount, SampleCounts,
|
||||
},
|
||||
sampler::Filter,
|
||||
sync::PipelineStageAccessFlags,
|
||||
DeviceSize, RequirementNotMet, RequiresOneOf, Version, VulkanObject,
|
||||
};
|
||||
|
@ -24,7 +24,8 @@ use crate::{
|
||||
device::{DeviceOwned, QueueFlags},
|
||||
format::{Format, FormatFeatures},
|
||||
image::{
|
||||
view::ImageViewType, ImageAccess, ImageAspects, ImageLayout, ImageViewAbstract, SampleCount,
|
||||
sampler::Sampler, view::ImageViewType, ImageAccess, ImageAspects, ImageLayout,
|
||||
ImageViewAbstract, SampleCount,
|
||||
},
|
||||
pipeline::{
|
||||
graphics::{
|
||||
@ -34,7 +35,6 @@ use crate::{
|
||||
},
|
||||
DynamicState, GraphicsPipeline, PartialStateMode, Pipeline, PipelineLayout,
|
||||
},
|
||||
sampler::Sampler,
|
||||
shader::{DescriptorBindingRequirements, ShaderScalarType, ShaderStage, ShaderStages},
|
||||
sync::{PipelineStageAccess, PipelineStageAccessFlags},
|
||||
DeviceSize, Requires, RequiresAllOf, RequiresOneOf, ValidationError, VulkanObject,
|
||||
|
@ -13,9 +13,8 @@
|
||||
|
||||
use crate::{
|
||||
device::{Device, DeviceOwned},
|
||||
image::ImageLayout,
|
||||
image::{sampler::Sampler, ImageLayout},
|
||||
macros::{impl_id_counter, vulkan_bitflags, vulkan_enum},
|
||||
sampler::Sampler,
|
||||
shader::{DescriptorBindingRequirements, ShaderStages},
|
||||
Requires, RequiresAllOf, RequiresOneOf, RuntimeError, ValidationError, Version, VulkanError,
|
||||
VulkanObject,
|
||||
|
@ -95,8 +95,7 @@ use crate::{
|
||||
DescriptorBindingFlags, DescriptorSetLayoutCreateFlags, DescriptorType,
|
||||
},
|
||||
device::DeviceOwned,
|
||||
image::ImageLayout,
|
||||
sampler::Sampler,
|
||||
image::{sampler::Sampler, ImageLayout},
|
||||
ValidationError, VulkanObject,
|
||||
};
|
||||
use ahash::HashMap;
|
||||
|
@ -17,9 +17,9 @@ use crate::{
|
||||
descriptor_set::layout::{DescriptorBindingFlags, DescriptorSetLayoutCreateFlags},
|
||||
device::DeviceOwned,
|
||||
image::{
|
||||
view::ImageViewType, ImageAspects, ImageLayout, ImageType, ImageUsage, ImageViewAbstract,
|
||||
sampler::Sampler, view::ImageViewType, ImageAspects, ImageLayout, ImageType, ImageUsage,
|
||||
ImageViewAbstract,
|
||||
},
|
||||
sampler::Sampler,
|
||||
DeviceSize, Requires, RequiresAllOf, RequiresOneOf, ValidationError, VulkanObject,
|
||||
};
|
||||
use smallvec::SmallVec;
|
||||
|
@ -21,7 +21,7 @@ use crate::{
|
||||
},
|
||||
device::{Device, DeviceOwned},
|
||||
format::Format,
|
||||
image::sys::ImageCreateInfo,
|
||||
image::{sampler::Filter, sys::ImageCreateInfo},
|
||||
memory::{
|
||||
allocator::{
|
||||
AllocationCreateInfo, AllocationType, MemoryAllocatePreference, MemoryAllocator,
|
||||
@ -29,7 +29,6 @@ use crate::{
|
||||
},
|
||||
is_aligned, DedicatedAllocation,
|
||||
},
|
||||
sampler::Filter,
|
||||
sync::Sharing,
|
||||
DeviceSize, RuntimeError,
|
||||
};
|
||||
|
@ -75,6 +75,7 @@ mod aspect;
|
||||
pub mod attachment; // TODO: make private
|
||||
pub mod immutable; // TODO: make private
|
||||
mod layout;
|
||||
pub mod sampler;
|
||||
mod storage;
|
||||
pub mod swapchain; // TODO: make private
|
||||
pub mod sys;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -29,13 +29,19 @@
|
||||
//! # let memory_allocator: vulkano::memory::allocator::StandardMemoryAllocator = return;
|
||||
//! # let descriptor_set_allocator: vulkano::descriptor_set::allocator::StandardDescriptorSetAllocator = return;
|
||||
//! # let mut command_buffer_builder: vulkano::command_buffer::AutoCommandBufferBuilder<vulkano::command_buffer::PrimaryAutoCommandBuffer> = return;
|
||||
//! use vulkano::descriptor_set::{PersistentDescriptorSet, WriteDescriptorSet};
|
||||
//! use vulkano::descriptor_set::layout::{DescriptorSetLayout, DescriptorSetLayoutBinding, DescriptorSetLayoutCreateInfo, DescriptorType};
|
||||
//! use vulkano::descriptor_set::{
|
||||
//! layout::{DescriptorSetLayout, DescriptorSetLayoutBinding, DescriptorSetLayoutCreateInfo, DescriptorType},
|
||||
//! PersistentDescriptorSet, WriteDescriptorSet,
|
||||
//! };
|
||||
//! use vulkano::format::Format;
|
||||
//! use vulkano::image::{ImmutableImage, ImageCreateFlags, ImageDimensions, ImageUsage, MipmapsCount};
|
||||
//! use vulkano::image::view::{ImageView, ImageViewCreateInfo};
|
||||
//! use vulkano::sampler::{Sampler, SamplerCreateInfo};
|
||||
//! use vulkano::sampler::ycbcr::{SamplerYcbcrConversion, SamplerYcbcrConversionCreateInfo, SamplerYcbcrModelConversion};
|
||||
//! use vulkano::image::{
|
||||
//! sampler::{
|
||||
//! ycbcr::{SamplerYcbcrConversion, SamplerYcbcrConversionCreateInfo, SamplerYcbcrModelConversion},
|
||||
//! Sampler, SamplerCreateInfo,
|
||||
//! },
|
||||
//! view::{ImageView, ImageViewCreateInfo},
|
||||
//! ImmutableImage, ImageCreateFlags, ImageDimensions, ImageUsage, MipmapsCount,
|
||||
//! };
|
||||
//! use vulkano::shader::ShaderStage;
|
||||
//!
|
||||
//! let conversion = SamplerYcbcrConversion::new(device.clone(), SamplerYcbcrConversionCreateInfo {
|
||||
@ -93,19 +99,12 @@
|
||||
use crate::{
|
||||
device::{Device, DeviceOwned},
|
||||
format::{ChromaSampling, Format, FormatFeatures, NumericType},
|
||||
image::sampler::{ComponentMapping, ComponentSwizzle, Filter},
|
||||
macros::{impl_id_counter, vulkan_enum},
|
||||
sampler::{ComponentMapping, ComponentSwizzle, Filter},
|
||||
OomError, RequirementNotMet, Requires, RequiresAllOf, RequiresOneOf, RuntimeError, Version,
|
||||
Requires, RequiresAllOf, RequiresOneOf, RuntimeError, ValidationError, Version, VulkanError,
|
||||
VulkanObject,
|
||||
};
|
||||
use std::{
|
||||
error::Error,
|
||||
fmt::{Display, Error as FmtError, Formatter},
|
||||
mem::MaybeUninit,
|
||||
num::NonZeroU64,
|
||||
ptr,
|
||||
sync::Arc,
|
||||
};
|
||||
use std::{mem::MaybeUninit, num::NonZeroU64, ptr, sync::Arc};
|
||||
|
||||
/// Describes how sampled image data should converted from a YCbCr representation to an RGB one.
|
||||
#[derive(Debug)]
|
||||
@ -128,11 +127,43 @@ impl SamplerYcbcrConversion {
|
||||
///
|
||||
/// The [`sampler_ycbcr_conversion`](crate::device::Features::sampler_ycbcr_conversion)
|
||||
/// feature must be enabled on the device.
|
||||
#[inline]
|
||||
pub fn new(
|
||||
device: Arc<Device>,
|
||||
create_info: SamplerYcbcrConversionCreateInfo,
|
||||
) -> Result<Arc<SamplerYcbcrConversion>, SamplerYcbcrConversionCreationError> {
|
||||
let SamplerYcbcrConversionCreateInfo {
|
||||
) -> Result<Arc<SamplerYcbcrConversion>, VulkanError> {
|
||||
Self::validate_new(&device, &create_info)?;
|
||||
|
||||
unsafe { Ok(Self::new_unchecked(device, create_info)?) }
|
||||
}
|
||||
|
||||
fn validate_new(
|
||||
device: &Device,
|
||||
create_info: &SamplerYcbcrConversionCreateInfo,
|
||||
) -> Result<(), ValidationError> {
|
||||
if !device.enabled_features().sampler_ycbcr_conversion {
|
||||
return Err(ValidationError {
|
||||
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
|
||||
"sampler_ycbcr_conversion",
|
||||
)])]),
|
||||
vuids: &["VUID-vkCreateSamplerYcbcrConversion-None-01648"],
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
|
||||
create_info
|
||||
.validate(device)
|
||||
.map_err(|err| err.add_context("create_info"))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
|
||||
pub unsafe fn new_unchecked(
|
||||
device: Arc<Device>,
|
||||
create_info: SamplerYcbcrConversionCreateInfo,
|
||||
) -> Result<Arc<SamplerYcbcrConversion>, RuntimeError> {
|
||||
let &SamplerYcbcrConversionCreateInfo {
|
||||
format,
|
||||
ycbcr_model,
|
||||
ycbcr_range,
|
||||
@ -141,189 +172,10 @@ impl SamplerYcbcrConversion {
|
||||
chroma_filter,
|
||||
force_explicit_reconstruction,
|
||||
_ne: _,
|
||||
} = create_info;
|
||||
} = &create_info;
|
||||
|
||||
if !device.enabled_features().sampler_ycbcr_conversion {
|
||||
return Err(SamplerYcbcrConversionCreationError::RequirementNotMet {
|
||||
required_for: "`SamplerYcbcrConversion::new`",
|
||||
requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::Feature(
|
||||
"sampler_ycbcr_conversion",
|
||||
)])]),
|
||||
});
|
||||
}
|
||||
|
||||
let format = match format {
|
||||
Some(f) => f,
|
||||
None => {
|
||||
return Err(SamplerYcbcrConversionCreationError::FormatMissing);
|
||||
}
|
||||
};
|
||||
|
||||
// VUID-VkSamplerYcbcrConversionCreateInfo-format-parameter
|
||||
format.validate_device(&device)?;
|
||||
|
||||
// VUID-VkSamplerYcbcrConversionCreateInfo-ycbcrModel-parameter
|
||||
ycbcr_model.validate_device(&device)?;
|
||||
|
||||
// VUID-VkSamplerYcbcrConversionCreateInfo-ycbcrRange-parameter
|
||||
ycbcr_range.validate_device(&device)?;
|
||||
|
||||
// VUID-VkComponentMapping-r-parameter
|
||||
component_mapping.r.validate_device(&device)?;
|
||||
|
||||
// VUID-VkComponentMapping-g-parameter
|
||||
component_mapping.g.validate_device(&device)?;
|
||||
|
||||
// VUID-VkComponentMapping-b-parameter
|
||||
component_mapping.b.validate_device(&device)?;
|
||||
|
||||
// VUID-VkComponentMapping-a-parameter
|
||||
component_mapping.a.validate_device(&device)?;
|
||||
|
||||
for offset in chroma_offset {
|
||||
// VUID-VkSamplerYcbcrConversionCreateInfo-xChromaOffset-parameter
|
||||
// VUID-VkSamplerYcbcrConversionCreateInfo-yChromaOffset-parameter
|
||||
offset.validate_device(&device)?;
|
||||
}
|
||||
|
||||
// VUID-VkSamplerYcbcrConversionCreateInfo-chromaFilter-parameter
|
||||
chroma_filter.validate_device(&device)?;
|
||||
|
||||
// VUID-VkSamplerYcbcrConversionCreateInfo-format-04061
|
||||
if !format
|
||||
.type_color()
|
||||
.map_or(false, |ty| ty == NumericType::UNORM)
|
||||
{
|
||||
return Err(SamplerYcbcrConversionCreationError::FormatNotUnorm);
|
||||
}
|
||||
|
||||
// Use unchecked, because all validation has been done above.
|
||||
let potential_format_features = unsafe {
|
||||
device
|
||||
.physical_device()
|
||||
.format_properties_unchecked(format)
|
||||
.potential_format_features()
|
||||
};
|
||||
|
||||
// VUID-VkSamplerYcbcrConversionCreateInfo-format-01650
|
||||
if !potential_format_features.intersects(
|
||||
FormatFeatures::MIDPOINT_CHROMA_SAMPLES | FormatFeatures::COSITED_CHROMA_SAMPLES,
|
||||
) {
|
||||
return Err(SamplerYcbcrConversionCreationError::FormatNotSupported);
|
||||
}
|
||||
|
||||
if let Some(chroma_sampling @ (ChromaSampling::Mode422 | ChromaSampling::Mode420)) =
|
||||
format.ycbcr_chroma_sampling()
|
||||
{
|
||||
let chroma_offsets_to_check = match chroma_sampling {
|
||||
ChromaSampling::Mode420 => &chroma_offset[0..2],
|
||||
ChromaSampling::Mode422 => &chroma_offset[0..1],
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
for offset in chroma_offsets_to_check {
|
||||
match offset {
|
||||
ChromaLocation::CositedEven => {
|
||||
// VUID-VkSamplerYcbcrConversionCreateInfo-xChromaOffset-01651
|
||||
if !potential_format_features
|
||||
.intersects(FormatFeatures::COSITED_CHROMA_SAMPLES)
|
||||
{
|
||||
return Err(
|
||||
SamplerYcbcrConversionCreationError::FormatChromaOffsetNotSupported,
|
||||
);
|
||||
}
|
||||
}
|
||||
ChromaLocation::Midpoint => {
|
||||
// VUID-VkSamplerYcbcrConversionCreateInfo-xChromaOffset-01652
|
||||
if !potential_format_features
|
||||
.intersects(FormatFeatures::MIDPOINT_CHROMA_SAMPLES)
|
||||
{
|
||||
return Err(
|
||||
SamplerYcbcrConversionCreationError::FormatChromaOffsetNotSupported,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// VUID-VkSamplerYcbcrConversionCreateInfo-components-02581
|
||||
let g_ok = component_mapping.g_is_identity();
|
||||
|
||||
// VUID-VkSamplerYcbcrConversionCreateInfo-components-02582
|
||||
let a_ok = component_mapping.a_is_identity()
|
||||
|| matches!(
|
||||
component_mapping.a,
|
||||
ComponentSwizzle::One | ComponentSwizzle::Zero
|
||||
);
|
||||
|
||||
// VUID-VkSamplerYcbcrConversionCreateInfo-components-02583
|
||||
// VUID-VkSamplerYcbcrConversionCreateInfo-components-02584
|
||||
// VUID-VkSamplerYcbcrConversionCreateInfo-components-02585
|
||||
let rb_ok1 = component_mapping.r_is_identity() && component_mapping.b_is_identity();
|
||||
let rb_ok2 = matches!(component_mapping.r, ComponentSwizzle::Blue)
|
||||
&& matches!(component_mapping.b, ComponentSwizzle::Red);
|
||||
|
||||
if !(g_ok && a_ok && (rb_ok1 || rb_ok2)) {
|
||||
return Err(SamplerYcbcrConversionCreationError::FormatInvalidComponentMapping);
|
||||
}
|
||||
}
|
||||
|
||||
let components_bits = {
|
||||
let bits = format.components();
|
||||
component_mapping
|
||||
.component_map()
|
||||
.map(move |i| i.map(|i| bits[i]))
|
||||
};
|
||||
|
||||
// VUID-VkSamplerYcbcrConversionCreateInfo-ycbcrModel-01655
|
||||
if ycbcr_model != SamplerYcbcrModelConversion::RgbIdentity
|
||||
&& !components_bits[0..3]
|
||||
.iter()
|
||||
.all(|b| b.map_or(false, |b| b != 0))
|
||||
{
|
||||
return Err(SamplerYcbcrConversionCreationError::YcbcrModelInvalidComponentMapping);
|
||||
}
|
||||
|
||||
// VUID-VkSamplerYcbcrConversionCreateInfo-ycbcrRange-02748
|
||||
if ycbcr_range == SamplerYcbcrRange::ItuNarrow {
|
||||
// TODO: Spec doesn't say how many bits `Zero` and `One` are considered to have, so
|
||||
// just skip them for now.
|
||||
for &bits in components_bits[0..3].iter().flatten() {
|
||||
if bits < 8 {
|
||||
return Err(SamplerYcbcrConversionCreationError::YcbcrRangeFormatNotEnoughBits);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// VUID-VkSamplerYcbcrConversionCreateInfo-forceExplicitReconstruction-01656
|
||||
if force_explicit_reconstruction
|
||||
&& !potential_format_features.intersects(FormatFeatures::
|
||||
SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE)
|
||||
{
|
||||
return Err(
|
||||
SamplerYcbcrConversionCreationError::FormatForceExplicitReconstructionNotSupported,
|
||||
);
|
||||
}
|
||||
|
||||
match chroma_filter {
|
||||
Filter::Nearest => (),
|
||||
Filter::Linear => {
|
||||
// VUID-VkSamplerYcbcrConversionCreateInfo-chromaFilter-01657
|
||||
if !potential_format_features
|
||||
.intersects(FormatFeatures::SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER)
|
||||
{
|
||||
return Err(
|
||||
SamplerYcbcrConversionCreationError::FormatLinearFilterNotSupported,
|
||||
);
|
||||
}
|
||||
}
|
||||
Filter::Cubic => {
|
||||
return Err(SamplerYcbcrConversionCreationError::CubicFilterNotSupported);
|
||||
}
|
||||
}
|
||||
|
||||
let create_info = ash::vk::SamplerYcbcrConversionCreateInfo {
|
||||
format: format.into(),
|
||||
let create_info_vk = ash::vk::SamplerYcbcrConversionCreateInfo {
|
||||
format: format.unwrap().into(),
|
||||
ycbcr_model: ycbcr_model.into(),
|
||||
ycbcr_range: ycbcr_range.into(),
|
||||
components: component_mapping.into(),
|
||||
@ -346,7 +198,7 @@ impl SamplerYcbcrConversion {
|
||||
let mut output = MaybeUninit::uninit();
|
||||
create_sampler_ycbcr_conversion(
|
||||
device.handle(),
|
||||
&create_info,
|
||||
&create_info_vk,
|
||||
ptr::null(),
|
||||
output.as_mut_ptr(),
|
||||
)
|
||||
@ -355,18 +207,7 @@ impl SamplerYcbcrConversion {
|
||||
output.assume_init()
|
||||
};
|
||||
|
||||
Ok(Arc::new(SamplerYcbcrConversion {
|
||||
handle,
|
||||
device,
|
||||
id: Self::next_id(),
|
||||
format: Some(format),
|
||||
ycbcr_model,
|
||||
ycbcr_range,
|
||||
component_mapping,
|
||||
chroma_offset,
|
||||
chroma_filter,
|
||||
force_explicit_reconstruction,
|
||||
}))
|
||||
Ok(Self::from_handle(device, handle, create_info))
|
||||
}
|
||||
|
||||
/// Creates a new `SamplerYcbcrConversion` from a raw object handle.
|
||||
@ -375,7 +216,6 @@ impl SamplerYcbcrConversion {
|
||||
///
|
||||
/// - `handle` must be a valid Vulkan object handle created from `device`.
|
||||
/// - `create_info` must match the info used to create the object.
|
||||
/// - `create_info.format` must be `Some`.
|
||||
#[inline]
|
||||
pub unsafe fn from_handle(
|
||||
device: Arc<Device>,
|
||||
@ -512,138 +352,6 @@ unsafe impl DeviceOwned for SamplerYcbcrConversion {
|
||||
|
||||
impl_id_counter!(SamplerYcbcrConversion);
|
||||
|
||||
/// Error that can happen when creating a `SamplerYcbcrConversion`.
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum SamplerYcbcrConversionCreationError {
|
||||
/// Not enough memory.
|
||||
OomError(OomError),
|
||||
|
||||
RequirementNotMet {
|
||||
required_for: &'static str,
|
||||
requires_one_of: RequiresOneOf,
|
||||
},
|
||||
|
||||
/// The `Cubic` filter was specified.
|
||||
CubicFilterNotSupported,
|
||||
|
||||
/// No format was specified when one was required.
|
||||
FormatMissing,
|
||||
|
||||
/// The format has a color type other than `UNORM`.
|
||||
FormatNotUnorm,
|
||||
|
||||
/// The format does not support sampler YCbCr conversion.
|
||||
FormatNotSupported,
|
||||
|
||||
/// The format does not support the chosen chroma offsets.
|
||||
FormatChromaOffsetNotSupported,
|
||||
|
||||
/// The component mapping was not valid for use with the chosen format.
|
||||
FormatInvalidComponentMapping,
|
||||
|
||||
/// The format does not support `force_explicit_reconstruction`.
|
||||
FormatForceExplicitReconstructionNotSupported,
|
||||
|
||||
/// The format does not support the `Linear` filter.
|
||||
FormatLinearFilterNotSupported,
|
||||
|
||||
/// The component mapping was not valid for use with the chosen YCbCr model.
|
||||
YcbcrModelInvalidComponentMapping,
|
||||
|
||||
/// For the chosen `ycbcr_range`, the R, G or B components being read from the `format` do not
|
||||
/// have the minimum number of required bits.
|
||||
YcbcrRangeFormatNotEnoughBits,
|
||||
}
|
||||
|
||||
impl Error for SamplerYcbcrConversionCreationError {
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match self {
|
||||
SamplerYcbcrConversionCreationError::OomError(err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for SamplerYcbcrConversionCreationError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
match self {
|
||||
Self::OomError(_) => write!(f, "not enough memory available"),
|
||||
Self::RequirementNotMet {
|
||||
required_for,
|
||||
requires_one_of,
|
||||
} => write!(
|
||||
f,
|
||||
"a requirement was not met for: {}; requires one of: {}",
|
||||
required_for, requires_one_of,
|
||||
),
|
||||
Self::CubicFilterNotSupported => {
|
||||
write!(f, "the `Cubic` filter was specified")
|
||||
}
|
||||
Self::FormatMissing => {
|
||||
write!(f, "no format was specified when one was required")
|
||||
}
|
||||
Self::FormatNotUnorm => {
|
||||
write!(f, "the format has a color type other than `UNORM`")
|
||||
}
|
||||
Self::FormatNotSupported => {
|
||||
write!(f, "the format does not support sampler YCbCr conversion")
|
||||
}
|
||||
Self::FormatChromaOffsetNotSupported => {
|
||||
write!(f, "the format does not support the chosen chroma offsets")
|
||||
}
|
||||
Self::FormatInvalidComponentMapping => write!(
|
||||
f,
|
||||
"the component mapping was not valid for use with the chosen format",
|
||||
),
|
||||
Self::FormatForceExplicitReconstructionNotSupported => write!(
|
||||
f,
|
||||
"the format does not support `force_explicit_reconstruction`",
|
||||
),
|
||||
Self::FormatLinearFilterNotSupported => {
|
||||
write!(f, "the format does not support the `Linear` filter")
|
||||
}
|
||||
Self::YcbcrModelInvalidComponentMapping => write!(
|
||||
f,
|
||||
"the component mapping was not valid for use with the chosen YCbCr model",
|
||||
),
|
||||
Self::YcbcrRangeFormatNotEnoughBits => write!(
|
||||
f,
|
||||
"for the chosen `ycbcr_range`, the R, G or B components being read from the \
|
||||
`format` do not have the minimum number of required bits",
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OomError> for SamplerYcbcrConversionCreationError {
|
||||
fn from(err: OomError) -> SamplerYcbcrConversionCreationError {
|
||||
SamplerYcbcrConversionCreationError::OomError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RuntimeError> for SamplerYcbcrConversionCreationError {
|
||||
fn from(err: RuntimeError) -> SamplerYcbcrConversionCreationError {
|
||||
match err {
|
||||
err @ RuntimeError::OutOfHostMemory => {
|
||||
SamplerYcbcrConversionCreationError::OomError(OomError::from(err))
|
||||
}
|
||||
err @ RuntimeError::OutOfDeviceMemory => {
|
||||
SamplerYcbcrConversionCreationError::OomError(OomError::from(err))
|
||||
}
|
||||
_ => panic!("unexpected error: {:?}", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RequirementNotMet> for SamplerYcbcrConversionCreationError {
|
||||
fn from(err: RequirementNotMet) -> Self {
|
||||
Self::RequirementNotMet {
|
||||
required_for: err.required_for,
|
||||
requires_one_of: err.requires_one_of,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Parameters to create a new `SamplerYcbcrConversion`.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SamplerYcbcrConversionCreateInfo {
|
||||
@ -733,6 +441,411 @@ impl Default for SamplerYcbcrConversionCreateInfo {
|
||||
}
|
||||
}
|
||||
|
||||
impl SamplerYcbcrConversionCreateInfo {
|
||||
pub(crate) fn validate(&self, device: &Device) -> Result<(), ValidationError> {
|
||||
let &Self {
|
||||
format,
|
||||
ycbcr_model,
|
||||
ycbcr_range,
|
||||
component_mapping,
|
||||
chroma_offset,
|
||||
chroma_filter,
|
||||
force_explicit_reconstruction,
|
||||
_ne: _,
|
||||
} = self;
|
||||
|
||||
let format = format.ok_or(ValidationError {
|
||||
context: "format".into(),
|
||||
problem: "is `None`".into(),
|
||||
..Default::default()
|
||||
})?;
|
||||
|
||||
format
|
||||
.validate_device(device)
|
||||
.map_err(|err| ValidationError {
|
||||
context: "format".into(),
|
||||
vuids: &["VUID-VkSamplerYcbcrConversionCreateInfo-format-parameter"],
|
||||
..ValidationError::from_requirement(err)
|
||||
})?;
|
||||
|
||||
ycbcr_model
|
||||
.validate_device(device)
|
||||
.map_err(|err| ValidationError {
|
||||
context: "ycbcr_model".into(),
|
||||
vuids: &["VUID-VkSamplerYcbcrConversionCreateInfo-ycbcrModel-parameter"],
|
||||
..ValidationError::from_requirement(err)
|
||||
})?;
|
||||
|
||||
ycbcr_range
|
||||
.validate_device(device)
|
||||
.map_err(|err| ValidationError {
|
||||
context: "ycbcr_range".into(),
|
||||
vuids: &["VUID-VkSamplerYcbcrConversionCreateInfo-ycbcrRange-parameter"],
|
||||
..ValidationError::from_requirement(err)
|
||||
})?;
|
||||
|
||||
component_mapping
|
||||
.validate(device)
|
||||
.map_err(|err| err.add_context("component_mapping"))?;
|
||||
|
||||
for (index, offset) in chroma_offset.into_iter().enumerate() {
|
||||
offset
|
||||
.validate_device(device)
|
||||
.map_err(|err| ValidationError {
|
||||
context: format!("chroma_offset[{}]", index).into(),
|
||||
vuids: &[
|
||||
"VUID-VkSamplerYcbcrConversionCreateInfo-xChromaOffset-parameter",
|
||||
"VUID-VkSamplerYcbcrConversionCreateInfo-yChromaOffset-parameter",
|
||||
],
|
||||
..ValidationError::from_requirement(err)
|
||||
})?;
|
||||
}
|
||||
|
||||
chroma_filter
|
||||
.validate_device(device)
|
||||
.map_err(|err| ValidationError {
|
||||
context: "chroma_filter".into(),
|
||||
vuids: &["VUID-VkSamplerYcbcrConversionCreateInfo-chromaFilter-parameter"],
|
||||
..ValidationError::from_requirement(err)
|
||||
})?;
|
||||
|
||||
if !format
|
||||
.type_color()
|
||||
.map_or(false, |ty| ty == NumericType::UNORM)
|
||||
{
|
||||
return Err(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.
|
||||
let potential_format_features = unsafe {
|
||||
device
|
||||
.physical_device()
|
||||
.format_properties_unchecked(format)
|
||||
.potential_format_features()
|
||||
};
|
||||
|
||||
if !potential_format_features.intersects(
|
||||
FormatFeatures::MIDPOINT_CHROMA_SAMPLES | FormatFeatures::COSITED_CHROMA_SAMPLES,
|
||||
) {
|
||||
return Err(ValidationError {
|
||||
context: "format".into(),
|
||||
problem: "the potential format features do not contain \
|
||||
`FormatFeatures::MIDPOINT_CHROMA_SAMPLES` or \
|
||||
`FormatFeatures::COSITED_CHROMA_SAMPLES`"
|
||||
.into(),
|
||||
vuids: &["VUID-VkSamplerYcbcrConversionCreateInfo-format-01650"],
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(chroma_sampling @ (ChromaSampling::Mode422 | ChromaSampling::Mode420)) =
|
||||
format.ycbcr_chroma_sampling()
|
||||
{
|
||||
match chroma_sampling {
|
||||
ChromaSampling::Mode420 => {
|
||||
if chroma_offset.contains(&ChromaLocation::CositedEven)
|
||||
&& !potential_format_features
|
||||
.intersects(FormatFeatures::COSITED_CHROMA_SAMPLES)
|
||||
{
|
||||
return Err(ValidationError {
|
||||
problem: "`format` has both horizontal and vertical chroma \
|
||||
subsampling, and \
|
||||
its potential format features do not \
|
||||
contain `FormatFeatures::COSITED_CHROMA_SAMPLES`, but \
|
||||
`chroma_offset[0]` or `chroma_offset[1]` are \
|
||||
`ChromaLocation::CositedEven`"
|
||||
.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 {
|
||||
problem: "`format` has both horizontal and vertical chroma \
|
||||
subsampling, and \
|
||||
its potential format features do not \
|
||||
contain `FormatFeatures::MIDPOINT_CHROMA_SAMPLES`, but \
|
||||
`chroma_offset[0]` or `chroma_offset[1]` are \
|
||||
`ChromaLocation::Midpoint`"
|
||||
.into(),
|
||||
vuids: &["VUID-VkSamplerYcbcrConversionCreateInfo-xChromaOffset-01652"],
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
}
|
||||
ChromaSampling::Mode422 => {
|
||||
if chroma_offset[0] == ChromaLocation::CositedEven
|
||||
&& !potential_format_features
|
||||
.intersects(FormatFeatures::COSITED_CHROMA_SAMPLES)
|
||||
{
|
||||
return Err(ValidationError {
|
||||
problem: "`format` has horizontal chroma subsampling, and \
|
||||
its potential format features do not \
|
||||
contain `FormatFeatures::COSITED_CHROMA_SAMPLES`, but \
|
||||
`chroma_offset[0]` is \
|
||||
`ChromaLocation::CositedEven`"
|
||||
.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 {
|
||||
problem: "`format` has horizontal chroma subsampling, and \
|
||||
its potential format features do not \
|
||||
contain `FormatFeatures::MIDPOINT_CHROMA_SAMPLES`, but \
|
||||
`chroma_offset[0]` is \
|
||||
`ChromaLocation::Midpoint`"
|
||||
.into(),
|
||||
vuids: &["VUID-VkSamplerYcbcrConversionCreateInfo-xChromaOffset-01652"],
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
if !component_mapping.g_is_identity() {
|
||||
return Err(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()
|
||||
|| matches!(
|
||||
component_mapping.a,
|
||||
ComponentSwizzle::One | ComponentSwizzle::Zero
|
||||
))
|
||||
{
|
||||
return Err(ValidationError {
|
||||
context: "component_mapping.a".into(),
|
||||
problem: "`format` has chroma subsampling, but \
|
||||
`component_mapping.a` is not identity swizzled, or \
|
||||
`ComponentSwizzle::One` or `ComponentSwizzle::Zero`"
|
||||
.into(),
|
||||
vuids: &["VUID-VkSamplerYcbcrConversionCreateInfo-components-02582"],
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
|
||||
if !(component_mapping.r_is_identity()
|
||||
|| matches!(component_mapping.r, ComponentSwizzle::Blue))
|
||||
{
|
||||
return Err(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 {
|
||||
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 (
|
||||
component_mapping.r_is_identity(),
|
||||
component_mapping.b_is_identity(),
|
||||
) {
|
||||
(true, false) => {
|
||||
return Err(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 {
|
||||
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()
|
||||
});
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
let components_bits = {
|
||||
let bits = format.components();
|
||||
component_mapping
|
||||
.component_map()
|
||||
.map(move |i| i.map(|i| bits[i]))
|
||||
};
|
||||
|
||||
// VUID-VkSamplerYcbcrConversionCreateInfo-ycbcrModel-01655
|
||||
if ycbcr_model != SamplerYcbcrModelConversion::RgbIdentity {
|
||||
if components_bits[0].map_or(true, |bits| bits == 0) {
|
||||
return Err(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 {
|
||||
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 {
|
||||
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 {
|
||||
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()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if ycbcr_range == SamplerYcbcrRange::ItuNarrow {
|
||||
// TODO: Spec doesn't say how many bits `Zero` and `One` are considered to have, so
|
||||
// just skip them for now.
|
||||
|
||||
if components_bits[0].map_or(false, |bits| bits < 8) {
|
||||
return Err(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 {
|
||||
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 {
|
||||
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 {
|
||||
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()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if force_explicit_reconstruction
|
||||
&& !potential_format_features.intersects(FormatFeatures::
|
||||
SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE)
|
||||
{
|
||||
return Err(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 {
|
||||
Filter::Nearest => (),
|
||||
Filter::Linear => {
|
||||
if !potential_format_features
|
||||
.intersects(FormatFeatures::SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER)
|
||||
{
|
||||
return Err(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 {
|
||||
context: "chroma_filter".into(),
|
||||
problem: "is `Filter::Cubic`".into(),
|
||||
// vuids?
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
vulkan_enum! {
|
||||
#[non_exhaustive]
|
||||
|
||||
@ -790,8 +903,8 @@ vulkan_enum! {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{SamplerYcbcrConversion, SamplerYcbcrConversionCreationError};
|
||||
use crate::{Requires, RequiresAllOf, RequiresOneOf};
|
||||
use super::SamplerYcbcrConversion;
|
||||
use crate::{Requires, RequiresAllOf, RequiresOneOf, ValidationError, VulkanError};
|
||||
|
||||
#[test]
|
||||
fn feature_not_enabled() {
|
||||
@ -800,11 +913,11 @@ mod tests {
|
||||
let r = SamplerYcbcrConversion::new(device, Default::default());
|
||||
|
||||
match r {
|
||||
Err(SamplerYcbcrConversionCreationError::RequirementNotMet {
|
||||
Err(VulkanError::ValidationError(ValidationError {
|
||||
requires_one_of:
|
||||
RequiresOneOf([RequiresAllOf([Requires::Feature("sampler_ycbcr_conversion")])]),
|
||||
..
|
||||
}) => (),
|
||||
})) => (),
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
@ -19,9 +19,11 @@ use super::{
|
||||
use crate::{
|
||||
device::{Device, DeviceOwned},
|
||||
format::{ChromaSampling, Format, FormatFeatures},
|
||||
image::{ImageAspects, ImageCreateFlags, ImageTiling, ImageType, SampleCount},
|
||||
macros::{impl_id_counter, vulkan_enum},
|
||||
image::{
|
||||
sampler::{ycbcr::SamplerYcbcrConversion, ComponentMapping},
|
||||
ImageAspects, ImageCreateFlags, ImageTiling, ImageType, SampleCount,
|
||||
},
|
||||
macros::{impl_id_counter, vulkan_enum},
|
||||
OomError, RequirementNotMet, Requires, RequiresAllOf, RequiresOneOf, RuntimeError, Version,
|
||||
VulkanObject,
|
||||
};
|
||||
|
@ -193,7 +193,6 @@ pub mod pipeline;
|
||||
pub mod query;
|
||||
mod range_map;
|
||||
pub mod range_set;
|
||||
pub mod sampler;
|
||||
pub mod shader;
|
||||
pub mod swapchain;
|
||||
pub mod sync;
|
||||
|
Loading…
Reference in New Issue
Block a user