blob: c86fd5eec29423734543bf1bef31e81467d86aff [file] [log] [blame] [edit]
// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.
//! All the formats supported by Vulkan.
//!
//! A format is mostly used to describe the texel data of an image. However, formats also show up in
//! a few other places, most notably to describe the format of vertex buffers.
//!
//! # Format support
//!
//! Not all formats are supported by every device. Those that devices do support may only be
//! supported for certain use cases. It is an error to use a format where it is not supported, but
//! you can query a device beforehand for its support by calling `format_properties` on the physical
//! device. You can use this to select a usable format from one or more suitable alternatives.
//! Some formats are required to be always supported for a particular usage. These are listed in the
//! [tables in the Vulkan specification](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap43.html#features-required-format-support).
//!
//! # Special format types
//!
//! ## Depth/stencil formats
//!
//! Depth/stencil formats can be identified by the `D` and `S` components in their names. They are
//! used primarily as the format for framebuffer attachments, for the purposes of depth and stencil
//! testing.
//!
//! Some formats have only a depth or stencil component, while others combine both. The two
//! components are represented as separate *aspects*, which means that they can be accessed
//! individually as separate images. These pseudo-images have the same resolution, but different
//! bit depth and numeric representation.
//!
//! Depth/stencil formats deviate from the others in a few more ways. Their data representation is
//! considered opaque, meaning that they do not have a fixed layout in memory nor a fixed size per
//! texel. They also have special limitations in several operations such as copying; a depth/stencil
//! format is not compatible with any other format, only with itself.
//!
//! ## Block-compressed formats
//!
//! A block-compressed format uses compression to encode a larger block of texels into a smaller
//! number of bytes. Individual texels are no longer represented in memory, only the block as a
//! whole. An image must consist of a whole number of blocks, so the dimensions of an image must be
//! a whole multiple of the block dimensions. Vulkan supports several different compression schemes,
//! represented in Vulkano by the `CompressionType` enum.
//!
//! Overall, block-compressed formats do not behave significantly differently from regular formats.
//! They are mostly restricted in terms of compatibility. Because of the compression, the notion of
//! bits per component does not apply, so the `components` method will only return whether a
//! component is present or not.
//!
//! ## YCbCr formats
//!
//! YCbCr, also known as YUV, is an alternative image representation with three components:
//! Y for luminance or *luma* (overall brightness) and two color or *chroma* components Cb and Cr
//! encoding the blueness and redness respectively. YCbCr formats are primarily used in video
//! applications. In Vulkan, the formats used to encode YCbCr data use the green channel to
//! represent the luma component, while the blue and red components hold the chroma.
//!
//! To use most YCbCr formats in an [image view](crate::image::view), a
//! [sampler YCbCr conversion](crate::sampler::ycbcr) object must be created, and attached to both
//! the image view and the sampler. To query whether a format requires the conversion, you can call
//! `ycbcr_chroma_sampling` on a format. As a rule, any format with `444`, `422`, `420`,
//! `3PACK` or `4PACK` in the name requires it.
//!
//! Many YCbCr formats make use of **chroma subsampling**. This is a technique whereby the two
//! chroma components are encoded using a lower resolution than the luma component. The human eye is
//! less sensitive to color detail than to detail in brightness, so this allows more detail to be
//! encoded in less data. Chroma subsampling is indicated with one of three numbered suffixes in a
//! format name:
//! - `444` indicates a YCbCr format without chroma subsampling. All components have the same
//! resolution.
//! - `422` indicates horizontal chroma subsampling. The horizontal resolution of the chroma
//! components is halved, so a single value is shared within a 2x1 block of texels.
//! - `420` indicates horizontal and vertical chroma subsampling. Both dimensions of the chroma
//! components are halved, so a single value is shared within a 2x2 block of texels.
//!
//! Most YCbCr formats, including all of the `444` and `420` formats, are **multi-planar**. Instead
//! of storing the components of a single texel together in memory, the components are separated
//! into *planes*, which act like independent images. In 3-plane formats, the planes hold the Y,
//! Cb and Cr components respectively, while in 2-plane formats, Cb and Cr are combined into a
//! two-component plane. Where chroma subsampling is applied, plane 0 has the full resolution, while
//! planes 1 and 2 have reduced resolution. Effectively, they are standalone images with half the
//! resolution of the original.
//!
//! The texels of multi-planar images cannot be accessed individually, for example to copy or blit,
//! since the components of each texel are split across the planes. Instead, you must access each
//! plane as an individual *aspect* of the image. A single-plane aspect of a multi-planar image
//! behaves as a regular image, and even has its own format, which can be queried with the `plane`
//! method on a format.
use crate::{
device::physical::PhysicalDevice, image::ImageAspects, macros::vulkan_bitflags,
shader::spirv::ImageFormat, DeviceSize,
};
// Generated by build.rs
include!(concat!(env!("OUT_DIR"), "/formats.rs"));
impl Format {
/// Retrieves the properties of a format when used by a certain device.
#[deprecated(
since = "0.28.0",
note = "Use PhysicalDevice::format_properties instead"
)]
#[inline]
pub fn properties(self, physical_device: PhysicalDevice) -> FormatProperties {
physical_device.format_properties(self).unwrap()
}
/// Returns whether the format can be used with a storage image, without specifying
/// the format in the shader, if the
/// [`shader_storage_image_read_without_format`](crate::device::Features::shader_storage_image_read_without_format)
/// and/or
/// [`shader_storage_image_write_without_format`](crate::device::Features::shader_storage_image_write_without_format)
/// features are enabled on the device.
#[inline]
pub fn shader_storage_image_without_format(self) -> bool {
matches!(
self,
Format::R8G8B8A8_UNORM
| Format::R8G8B8A8_SNORM
| Format::R8G8B8A8_UINT
| Format::R8G8B8A8_SINT
| Format::R32_UINT
| Format::R32_SINT
| Format::R32_SFLOAT
| Format::R32G32_UINT
| Format::R32G32_SINT
| Format::R32G32_SFLOAT
| Format::R32G32B32A32_UINT
| Format::R32G32B32A32_SINT
| Format::R32G32B32A32_SFLOAT
| Format::R16G16B16A16_UINT
| Format::R16G16B16A16_SINT
| Format::R16G16B16A16_SFLOAT
| Format::R16G16_SFLOAT
| Format::B10G11R11_UFLOAT_PACK32
| Format::R16_SFLOAT
| Format::R16G16B16A16_UNORM
| Format::A2B10G10R10_UNORM_PACK32
| Format::R16G16_UNORM
| Format::R8G8_UNORM
| Format::R16_UNORM
| Format::R8_UNORM
| Format::R16G16B16A16_SNORM
| Format::R16G16_SNORM
| Format::R8G8_SNORM
| Format::R16_SNORM
| Format::R8_SNORM
| Format::R16G16_SINT
| Format::R8G8_SINT
| Format::R16_SINT
| Format::R8_SINT
| Format::A2B10G10R10_UINT_PACK32
| Format::R16G16_UINT
| Format::R8G8_UINT
| Format::R16_UINT
| Format::R8_UINT
)
}
}
impl From<Format> for ash::vk::Format {
#[inline]
fn from(val: Format) -> Self {
ash::vk::Format::from_raw(val as i32)
}
}
// https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap46.html#spirvenv-image-formats
impl From<ImageFormat> for Option<Format> {
#[inline]
fn from(val: ImageFormat) -> Self {
match val {
ImageFormat::Unknown => None,
ImageFormat::Rgba32f => Some(Format::R32G32B32A32_SFLOAT),
ImageFormat::Rgba16f => Some(Format::R16G16B16A16_SFLOAT),
ImageFormat::R32f => Some(Format::R32_SFLOAT),
ImageFormat::Rgba8 => Some(Format::R8G8B8A8_UNORM),
ImageFormat::Rgba8Snorm => Some(Format::R8G8B8A8_SNORM),
ImageFormat::Rg32f => Some(Format::R32G32_SFLOAT),
ImageFormat::Rg16f => Some(Format::R16G16_SFLOAT),
ImageFormat::R11fG11fB10f => Some(Format::B10G11R11_UFLOAT_PACK32),
ImageFormat::R16f => Some(Format::R16_SFLOAT),
ImageFormat::Rgba16 => Some(Format::R16G16B16A16_UNORM),
ImageFormat::Rgb10A2 => Some(Format::A2B10G10R10_UNORM_PACK32),
ImageFormat::Rg16 => Some(Format::R16G16_UNORM),
ImageFormat::Rg8 => Some(Format::R8G8_UNORM),
ImageFormat::R16 => Some(Format::R16_UNORM),
ImageFormat::R8 => Some(Format::R8_UNORM),
ImageFormat::Rgba16Snorm => Some(Format::R16G16B16A16_SNORM),
ImageFormat::Rg16Snorm => Some(Format::R16G16_SNORM),
ImageFormat::Rg8Snorm => Some(Format::R8G8_SNORM),
ImageFormat::R16Snorm => Some(Format::R16_SNORM),
ImageFormat::R8Snorm => Some(Format::R8_SNORM),
ImageFormat::Rgba32i => Some(Format::R32G32B32A32_SINT),
ImageFormat::Rgba16i => Some(Format::R16G16B16A16_SINT),
ImageFormat::Rgba8i => Some(Format::R8G8B8A8_SINT),
ImageFormat::R32i => Some(Format::R32_SINT),
ImageFormat::Rg32i => Some(Format::R32G32_SINT),
ImageFormat::Rg16i => Some(Format::R16G16_SINT),
ImageFormat::Rg8i => Some(Format::R8G8_SINT),
ImageFormat::R16i => Some(Format::R16_SINT),
ImageFormat::R8i => Some(Format::R8_SINT),
ImageFormat::Rgba32ui => Some(Format::R32G32B32A32_UINT),
ImageFormat::Rgba16ui => Some(Format::R16G16B16A16_UINT),
ImageFormat::Rgba8ui => Some(Format::R8G8B8A8_UINT),
ImageFormat::R32ui => Some(Format::R32_UINT),
ImageFormat::Rgb10a2ui => Some(Format::A2B10G10R10_UINT_PACK32),
ImageFormat::Rg32ui => Some(Format::R32G32_UINT),
ImageFormat::Rg16ui => Some(Format::R16G16_UINT),
ImageFormat::Rg8ui => Some(Format::R8G8_UINT),
ImageFormat::R16ui => Some(Format::R16_UINT),
ImageFormat::R8ui => Some(Format::R8_UINT),
ImageFormat::R64ui => Some(Format::R64_UINT),
ImageFormat::R64i => Some(Format::R64_SINT),
}
}
}
/// The block compression scheme used in a format.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[allow(non_camel_case_types)]
pub enum CompressionType {
/// Adaptive Scalable Texture Compression, low dynamic range.
ASTC_LDR,
/// Adaptive Scalable Texture Compression, high dynamic range.
ASTC_HDR,
/// S3TC Block Compression.
BC,
/// Ericsson Texture Compression 2.
ETC2,
/// ETC2 Alpha Compression.
EAC,
/// PowerVR Texture Compression.
PVRTC,
}
/// For YCbCr formats, the type of chroma sampling used.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum ChromaSampling {
/// The chroma components are represented at the same resolution as the luma component.
Mode444,
/// The chroma components have half the horizontal resolution as the luma component.
Mode422,
/// The chroma components have half the horizontal and vertical resolution as the luma
/// component.
Mode420,
}
impl ChromaSampling {
#[inline]
pub fn subsampled_extent(self, mut extent: [u32; 3]) -> [u32; 3] {
match self {
ChromaSampling::Mode444 => (),
ChromaSampling::Mode422 => {
debug_assert!(extent[0] % 2 == 0);
extent[0] /= 2;
}
ChromaSampling::Mode420 => {
debug_assert!(extent[0] % 2 == 0 && extent[1] % 2 == 0);
extent[0] /= 2;
extent[1] /= 2;
}
}
extent
}
}
/// The numeric type that represents data of a format in memory.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum NumericType {
/// Signed floating-point number.
SFLOAT,
/// Unsigned floating-point number.
UFLOAT,
/// Signed integer.
SINT,
/// Unsigned integer.
UINT,
/// Signed integer that represents a normalized floating-point value in the range \[-1,1].
SNORM,
/// Unsigned integer that represents a normalized floating-point value in the range \[0,1].
UNORM,
/// Signed integer that is converted to a floating-point value directly.
SSCALED,
/// Unsigned integer that is converted to a floating-point value directly.
USCALED,
/// Unsigned integer where R, G, B components represent a normalized floating-point value in the
/// sRGB color space, while the A component is a simple normalized value as in `UNORM`.
SRGB,
}
/// An opaque type that represents a format compatibility class.
///
/// Two formats are compatible if their compatibility classes compare equal.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[repr(transparent)]
pub struct FormatCompatibility(pub(crate) &'static FormatCompatibilityInner);
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[allow(non_camel_case_types)]
pub(crate) enum FormatCompatibilityInner {
Class_8bit,
Class_16bit,
Class_24bit,
Class_32bit,
Class_48bit,
Class_64bit,
Class_96bit,
Class_128bit,
Class_192bit,
Class_256bit,
Class_D16,
Class_D24,
Class_D32,
Class_S8,
Class_D16S8,
Class_D24S8,
Class_D32S8,
Class_64bit_R10G10B10A10,
Class_64bit_R12G12B12A12,
Class_BC1_RGB,
Class_BC1_RGBA,
Class_BC2,
Class_BC3,
Class_BC4,
Class_BC5,
Class_BC6H,
Class_BC7,
Class_ETC2_RGB,
Class_ETC2_RGBA,
Class_ETC2_EAC_RGBA,
Class_EAC_R,
Class_EAC_RG,
Class_ASTC_4x4,
Class_ASTC_5x4,
Class_ASTC_5x5,
Class_ASTC_6x5,
Class_ASTC_6x6,
Class_ASTC_8x5,
Class_ASTC_8x6,
Class_ASTC_8x8,
Class_ASTC_10x5,
Class_ASTC_10x6,
Class_ASTC_10x8,
Class_ASTC_10x10,
Class_ASTC_12x10,
Class_ASTC_12x12,
Class_PVRTC1_2BPP,
Class_PVRTC1_4BPP,
Class_PVRTC2_2BPP,
Class_PVRTC2_4BPP,
Class_32bit_G8B8G8R8,
Class_32bit_B8G8R8G8,
Class_64bit_G10B10G10R10,
Class_64bit_B10G10R10G10,
Class_64bit_G12B12G12R12,
Class_64bit_B12G12R12G12,
Class_64bit_G16B16G16R16,
Class_64bit_B16G16R16G16,
Class_8bit_3plane_420,
Class_8bit_2plane_420,
Class_10bit_3plane_420,
Class_10bit_2plane_420,
Class_12bit_3plane_420,
Class_12bit_2plane_420,
Class_16bit_3plane_420,
Class_16bit_2plane_420,
Class_8bit_3plane_422,
Class_8bit_2plane_422,
Class_10bit_3plane_422,
Class_10bit_2plane_422,
Class_12bit_3plane_422,
Class_12bit_2plane_422,
Class_16bit_3plane_422,
Class_16bit_2plane_422,
Class_8bit_3plane_444,
Class_10bit_3plane_444,
Class_12bit_3plane_444,
Class_16bit_3plane_444,
Class_8bit_2plane_444,
Class_10bit_2plane_444,
Class_12bit_2plane_444,
Class_16bit_2plane_444,
}
/// Describes a uniform value that will be used to fill an image.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum ClearValue {
/// Value for floating-point attachments, including `UNORM`, `SNORM`, `SFLOAT`.
Float([f32; 4]),
/// Value for integer attachments, including `SINT`.
Int([i32; 4]),
/// Value for unsigned integer attachments, including `UINT`.
Uint([u32; 4]),
/// Value for depth attachments.
Depth(f32),
/// Value for stencil attachments.
Stencil(u32),
/// Value for depth and stencil attachments.
DepthStencil((f32, u32)),
}
impl From<ClearValue> for ash::vk::ClearValue {
#[inline]
fn from(val: ClearValue) -> Self {
match val {
ClearValue::Float(val) => Self {
color: ash::vk::ClearColorValue { float32: val },
},
ClearValue::Int(val) => Self {
color: ash::vk::ClearColorValue { int32: val },
},
ClearValue::Uint(val) => Self {
color: ash::vk::ClearColorValue { uint32: val },
},
ClearValue::Depth(depth) => Self {
depth_stencil: ash::vk::ClearDepthStencilValue { depth, stencil: 0 },
},
ClearValue::Stencil(stencil) => Self {
depth_stencil: ash::vk::ClearDepthStencilValue {
depth: 0.0,
stencil,
},
},
ClearValue::DepthStencil((depth, stencil)) => Self {
depth_stencil: ash::vk::ClearDepthStencilValue { depth, stencil },
},
}
}
}
impl From<ClearColorValue> for ClearValue {
#[inline]
fn from(val: ClearColorValue) -> Self {
match val {
ClearColorValue::Float(val) => Self::Float(val),
ClearColorValue::Int(val) => Self::Int(val),
ClearColorValue::Uint(val) => Self::Uint(val),
}
}
}
impl From<[f32; 1]> for ClearValue {
#[inline]
fn from(val: [f32; 1]) -> Self {
Self::Float([val[0], 0.0, 0.0, 1.0])
}
}
impl From<[f32; 2]> for ClearValue {
#[inline]
fn from(val: [f32; 2]) -> Self {
Self::Float([val[0], val[1], 0.0, 1.0])
}
}
impl From<[f32; 3]> for ClearValue {
#[inline]
fn from(val: [f32; 3]) -> Self {
Self::Float([val[0], val[1], val[2], 1.0])
}
}
impl From<[f32; 4]> for ClearValue {
#[inline]
fn from(val: [f32; 4]) -> Self {
Self::Float(val)
}
}
impl From<[u32; 1]> for ClearValue {
#[inline]
fn from(val: [u32; 1]) -> Self {
Self::Uint([val[0], 0, 0, 0]) // TODO: is alpha value 0 correct?
}
}
impl From<[u32; 2]> for ClearValue {
#[inline]
fn from(val: [u32; 2]) -> Self {
Self::Uint([val[0], val[1], 0, 0]) // TODO: is alpha value 0 correct?
}
}
impl From<[u32; 3]> for ClearValue {
#[inline]
fn from(val: [u32; 3]) -> Self {
Self::Uint([val[0], val[1], val[2], 0]) // TODO: is alpha value 0 correct?
}
}
impl From<[u32; 4]> for ClearValue {
#[inline]
fn from(val: [u32; 4]) -> Self {
Self::Uint(val)
}
}
impl From<[i32; 1]> for ClearValue {
#[inline]
fn from(val: [i32; 1]) -> Self {
Self::Int([val[0], 0, 0, 0]) // TODO: is alpha value 0 correct?
}
}
impl From<[i32; 2]> for ClearValue {
#[inline]
fn from(val: [i32; 2]) -> Self {
Self::Int([val[0], val[1], 0, 0]) // TODO: is alpha value 0 correct?
}
}
impl From<[i32; 3]> for ClearValue {
#[inline]
fn from(val: [i32; 3]) -> Self {
Self::Int([val[0], val[1], val[2], 0]) // TODO: is alpha value 0 correct?
}
}
impl From<[i32; 4]> for ClearValue {
#[inline]
fn from(val: [i32; 4]) -> Self {
Self::Int(val)
}
}
impl From<f32> for ClearValue {
#[inline]
fn from(val: f32) -> Self {
Self::Depth(val)
}
}
impl From<u32> for ClearValue {
#[inline]
fn from(val: u32) -> Self {
Self::Stencil(val)
}
}
impl From<(f32, u32)> for ClearValue {
#[inline]
fn from(val: (f32, u32)) -> Self {
Self::DepthStencil(val)
}
}
/// A value that will be used to clear a color image.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum ClearColorValue {
/// Value for formats with a numeric type that is not `SINT` or `UINT`.
Float([f32; 4]),
/// Value for formats with a numeric type of `SINT`.
Int([i32; 4]),
/// Value for formats with a numeric type of `UINT`.
Uint([u32; 4]),
}
impl From<ClearColorValue> for ash::vk::ClearColorValue {
#[inline]
fn from(val: ClearColorValue) -> Self {
match val {
ClearColorValue::Float(float32) => Self { float32 },
ClearColorValue::Int(int32) => Self { int32 },
ClearColorValue::Uint(uint32) => Self { uint32 },
}
}
}
impl From<[f32; 1]> for ClearColorValue {
#[inline]
fn from(val: [f32; 1]) -> Self {
Self::Float([val[0], 0.0, 0.0, 1.0])
}
}
impl From<[f32; 2]> for ClearColorValue {
#[inline]
fn from(val: [f32; 2]) -> Self {
Self::Float([val[0], val[1], 0.0, 1.0])
}
}
impl From<[f32; 3]> for ClearColorValue {
#[inline]
fn from(val: [f32; 3]) -> Self {
Self::Float([val[0], val[1], val[2], 1.0])
}
}
impl From<[f32; 4]> for ClearColorValue {
#[inline]
fn from(val: [f32; 4]) -> Self {
Self::Float(val)
}
}
impl From<[i32; 1]> for ClearColorValue {
#[inline]
fn from(val: [i32; 1]) -> Self {
Self::Int([val[0], 0, 0, 1])
}
}
impl From<[i32; 2]> for ClearColorValue {
#[inline]
fn from(val: [i32; 2]) -> Self {
Self::Int([val[0], val[1], 0, 1])
}
}
impl From<[i32; 3]> for ClearColorValue {
#[inline]
fn from(val: [i32; 3]) -> Self {
Self::Int([val[0], val[1], val[2], 1])
}
}
impl From<[i32; 4]> for ClearColorValue {
#[inline]
fn from(val: [i32; 4]) -> Self {
Self::Int(val)
}
}
impl From<[u32; 1]> for ClearColorValue {
#[inline]
fn from(val: [u32; 1]) -> Self {
Self::Uint([val[0], 0, 0, 1])
}
}
impl From<[u32; 2]> for ClearColorValue {
#[inline]
fn from(val: [u32; 2]) -> Self {
Self::Uint([val[0], val[1], 0, 1])
}
}
impl From<[u32; 3]> for ClearColorValue {
#[inline]
fn from(val: [u32; 3]) -> Self {
Self::Uint([val[0], val[1], val[2], 1])
}
}
impl From<[u32; 4]> for ClearColorValue {
#[inline]
fn from(val: [u32; 4]) -> Self {
Self::Uint(val)
}
}
/// A value that will be used to clear a depth/stencil image.
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct ClearDepthStencilValue {
/// Value for the depth component.
pub depth: f32,
/// Value for the stencil component.
pub stencil: u32,
}
impl From<ClearDepthStencilValue> for ash::vk::ClearDepthStencilValue {
#[inline]
fn from(val: ClearDepthStencilValue) -> Self {
Self {
depth: val.depth,
stencil: val.stencil,
}
}
}
impl From<f32> for ClearDepthStencilValue {
#[inline]
fn from(depth: f32) -> Self {
Self { depth, stencil: 0 }
}
}
impl From<u32> for ClearDepthStencilValue {
#[inline]
fn from(stencil: u32) -> Self {
Self {
depth: 0.0,
stencil,
}
}
}
impl From<(f32, u32)> for ClearDepthStencilValue {
#[inline]
fn from((depth, stencil): (f32, u32)) -> Self {
Self { depth, stencil }
}
}
/// The properties of a format that are supported by a physical device.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct FormatProperties {
/// Features available for images with linear tiling.
pub linear_tiling_features: FormatFeatures,
/// Features available for images with optimal tiling.
pub optimal_tiling_features: FormatFeatures,
/// Features available for buffers.
pub buffer_features: FormatFeatures,
pub _ne: crate::NonExhaustive,
}
impl Default for FormatProperties {
#[inline]
fn default() -> Self {
Self {
linear_tiling_features: Default::default(),
optimal_tiling_features: Default::default(),
buffer_features: Default::default(),
_ne: crate::NonExhaustive(()),
}
}
}
impl FormatProperties {
/// Returns the potential format features, following the definition of
/// <https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap43.html#potential-format-features>.
#[inline]
pub fn potential_format_features(&self) -> FormatFeatures {
self.linear_tiling_features | self.optimal_tiling_features
}
}
vulkan_bitflags! {
#[non_exhaustive]
/// The features supported by a device for an image or buffer with a particular format.
FormatFeatures = FormatFeatureFlags2(u64);
/* Image usage */
/// Can be used with a sampled image descriptor.
SAMPLED_IMAGE = SAMPLED_IMAGE,
/// Can be used with a storage image descriptor.
STORAGE_IMAGE = STORAGE_IMAGE,
/// Can be used with a storage image descriptor with atomic operations in a shader.
STORAGE_IMAGE_ATOMIC = STORAGE_IMAGE_ATOMIC,
/// Can be used with a storage image descriptor for reading, without specifying a format on the
/// image view.
STORAGE_READ_WITHOUT_FORMAT = STORAGE_READ_WITHOUT_FORMAT {
api_version: V1_3,
device_extensions: [khr_format_feature_flags2],
},
/// Can be used with a storage image descriptor for writing, without specifying a format on the
/// image view.
STORAGE_WRITE_WITHOUT_FORMAT = STORAGE_WRITE_WITHOUT_FORMAT {
api_version: V1_3,
device_extensions: [khr_format_feature_flags2],
},
/// Can be used with a color attachment in a framebuffer, or with an input attachment
/// descriptor.
COLOR_ATTACHMENT = COLOR_ATTACHMENT,
/// Can be used with a color attachment in a framebuffer with blending, or with an input
/// attachment descriptor.
COLOR_ATTACHMENT_BLEND = COLOR_ATTACHMENT_BLEND,
/// Can be used with a depth/stencil attachment in a framebuffer, or with an input attachment
/// descriptor.
DEPTH_STENCIL_ATTACHMENT = DEPTH_STENCIL_ATTACHMENT,
/// Can be used with a fragment density map attachment in a framebuffer.
FRAGMENT_DENSITY_MAP = FRAGMENT_DENSITY_MAP_EXT {
device_extensions: [ext_fragment_density_map],
},
/// Can be used with a fragment shading rate attachment in a framebuffer.
FRAGMENT_SHADING_RATE_ATTACHMENT = FRAGMENT_SHADING_RATE_ATTACHMENT_KHR {
device_extensions: [khr_fragment_shading_rate],
},
/// Can be used with the source image in a transfer (copy) operation.
TRANSFER_SRC = TRANSFER_SRC {
api_version: V1_1,
device_extensions: [khr_maintenance1],
},
/// Can be used with the destination image in a transfer (copy) operation.
TRANSFER_DST = TRANSFER_DST {
api_version: V1_1,
device_extensions: [khr_maintenance1],
},
/// Can be used with the source image in a blit operation.
BLIT_SRC = BLIT_SRC,
/// Can be used with the destination image in a blit operation.
BLIT_DST = BLIT_DST,
/* Sampling */
/// Can be used with samplers or as a blit source, using the
/// [`Linear`](crate::sampler::Filter::Linear) filter.
SAMPLED_IMAGE_FILTER_LINEAR = SAMPLED_IMAGE_FILTER_LINEAR,
/// Can be used with samplers or as a blit source, using the
/// [`Cubic`](crate::sampler::Filter::Cubic) filter.
SAMPLED_IMAGE_FILTER_CUBIC = SAMPLED_IMAGE_FILTER_CUBIC_EXT {
device_extensions: [ext_filter_cubic, img_filter_cubic],
},
/// Can be used with samplers using a reduction mode of
/// [`Min`](crate::sampler::SamplerReductionMode::Min) or
/// [`Max`](crate::sampler::SamplerReductionMode::Max).
SAMPLED_IMAGE_FILTER_MINMAX = SAMPLED_IMAGE_FILTER_MINMAX {
api_version: V1_2,
device_extensions: [ext_sampler_filter_minmax],
},
/// Can be used with sampler YCbCr conversions using a chroma offset of
/// [`Midpoint`](crate::sampler::ycbcr::ChromaLocation::Midpoint).
MIDPOINT_CHROMA_SAMPLES = MIDPOINT_CHROMA_SAMPLES {
api_version: V1_1,
device_extensions: [khr_sampler_ycbcr_conversion],
},
/// Can be used with sampler YCbCr conversions using a chroma offset of
/// [`CositedEven`](crate::sampler::ycbcr::ChromaLocation::CositedEven).
COSITED_CHROMA_SAMPLES = COSITED_CHROMA_SAMPLES {
api_version: V1_1,
device_extensions: [khr_sampler_ycbcr_conversion],
},
/// Can be used with sampler YCbCr conversions using the
/// [`Linear`](crate::sampler::Filter::Linear) chroma filter.
SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER = SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER {
api_version: V1_1,
device_extensions: [khr_sampler_ycbcr_conversion],
},
/// Can be used with sampler YCbCr conversions whose chroma filter differs from the filters of
/// the base sampler.
SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER = SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER {
api_version: V1_1,
device_extensions: [khr_sampler_ycbcr_conversion],
},
/// When used with a sampler YCbCr conversion, the implementation will always perform
/// explicit chroma reconstruction.
SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT = SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT {
api_version: V1_1,
device_extensions: [khr_sampler_ycbcr_conversion],
},
/// Can be used with sampler YCbCr conversions with forced explicit reconstruction.
SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE = SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE {
api_version: V1_1,
device_extensions: [khr_sampler_ycbcr_conversion],
},
/// Can be used with samplers using depth comparison.
SAMPLED_IMAGE_DEPTH_COMPARISON = SAMPLED_IMAGE_DEPTH_COMPARISON {
api_version: V1_3,
device_extensions: [khr_format_feature_flags2],
},
/* Video */
/// Can be used with the output image of a video decode operation.
VIDEO_DECODE_OUTPUT = VIDEO_DECODE_OUTPUT_KHR {
device_extensions: [khr_video_decode_queue],
},
/// Can be used with the DPB image of a video decode operation.
VIDEO_DECODE_DPB = VIDEO_DECODE_DPB_KHR {
device_extensions: [khr_video_decode_queue],
},
/// Can be used with the input image of a video encode operation.
VIDEO_ENCODE_INPUT = VIDEO_ENCODE_INPUT_KHR {
device_extensions: [khr_video_encode_queue],
},
/// Can be used with the DPB image of a video encode operation.
VIDEO_ENCODE_DPB = VIDEO_ENCODE_DPB_KHR {
device_extensions: [khr_video_encode_queue],
},
/* Misc image features */
/// For multi-planar formats, can be used with images created with the [`DISJOINT`] flag.
///
/// [`DISJOINT`]: crate::image::ImageCreateFlags::DISJOINT
DISJOINT = DISJOINT {
api_version: V1_1,
device_extensions: [khr_sampler_ycbcr_conversion],
},
// TODO: document
LINEAR_COLOR_ATTACHMENT = LINEAR_COLOR_ATTACHMENT_NV {
device_extensions: [nv_linear_color_attachment],
},
// TODO: document
WEIGHT_IMAGE = WEIGHT_IMAGE_QCOM {
device_extensions: [qcom_image_processing],
},
// TODO: document
WEIGHT_SAMPLED_IMAGE = WEIGHT_SAMPLED_IMAGE_QCOM {
device_extensions: [qcom_image_processing],
},
// TODO: document
BLOCK_MATCHING = BLOCK_MATCHING_QCOM {
device_extensions: [qcom_image_processing],
},
// TODO: document
BOX_FILTER_SAMPLED = BOX_FILTER_SAMPLED_QCOM {
device_extensions: [qcom_image_processing],
},
// TODO: document
OPTICAL_FLOW_IMAGE = OPTICAL_FLOW_IMAGE_NV {
device_extensions: [nv_optical_flow],
},
// TODO: document
OPTICAL_FLOW_VECTOR = OPTICAL_FLOW_VECTOR_NV {
device_extensions: [nv_optical_flow],
},
// TODO: document
OPTICAL_FLOW_COST = OPTICAL_FLOW_COST_NV {
device_extensions: [nv_optical_flow],
},
/* Buffer usage */
/// Can be used with a uniform texel buffer descriptor.
UNIFORM_TEXEL_BUFFER = UNIFORM_TEXEL_BUFFER,
/// Can be used with a storage texel buffer descriptor.
STORAGE_TEXEL_BUFFER = STORAGE_TEXEL_BUFFER,
/// Can be used with a storage texel buffer descriptor with atomic operations in a shader.
STORAGE_TEXEL_BUFFER_ATOMIC = STORAGE_TEXEL_BUFFER_ATOMIC,
/// Can be used as the format of a vertex attribute in the vertex input state of a graphics
/// pipeline.
VERTEX_BUFFER = VERTEX_BUFFER,
/// Can be used with the vertex buffer of an acceleration structure.
ACCELERATION_STRUCTURE_VERTEX_BUFFER = ACCELERATION_STRUCTURE_VERTEX_BUFFER_KHR {
device_extensions: [khr_acceleration_structure],
},
}
impl From<ash::vk::FormatFeatureFlags> for FormatFeatures {
#[inline]
fn from(val: ash::vk::FormatFeatureFlags) -> Self {
Self::from(ash::vk::FormatFeatureFlags2::from_raw(val.as_raw() as u64))
}
}