1 // Copyright (c) 2016 The vulkano developers
2 // Licensed under the Apache License, Version 2.0
3 // <LICENSE-APACHE or
4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT
5 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
6 // at your option. All files in the project carrying such
7 // notice may not be copied, modified, or distributed except
8 // according to those terms.
9 
10 //! All the formats supported by Vulkan.
11 //!
12 //! A format is mostly used to describe the texel data of an image. However, formats also show up in
13 //! a few other places, most notably to describe the format of vertex buffers.
14 //!
15 //! # Format support
16 //!
17 //! Not all formats are supported by every device. Those that devices do support may only be
18 //! supported for certain use cases. It is an error to use a format where it is not supported, but
19 //! you can query a device beforehand for its support by calling `format_properties` on the physical
20 //! device. You can use this to select a usable format from one or more suitable alternatives.
21 //! Some formats are required to be always supported for a particular usage. These are listed in the
22 //! [tables in the Vulkan specification](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap43.html#features-required-format-support).
23 //!
24 //! # Special format types
25 //!
26 //! ## Depth/stencil formats
27 //!
28 //! Depth/stencil formats can be identified by the `D` and `S` components in their names. They are
29 //! used primarily as the format for framebuffer attachments, for the purposes of depth and stencil
30 //! testing.
31 //!
32 //! Some formats have only a depth or stencil component, while others combine both. The two
33 //! components are represented as separate *aspects*, which means that they can be accessed
34 //! individually as separate images. These pseudo-images have the same resolution, but different
35 //! bit depth and numeric representation.
36 //!
37 //! Depth/stencil formats deviate from the others in a few more ways. Their data representation is
38 //! considered opaque, meaning that they do not have a fixed layout in memory nor a fixed size per
39 //! texel. They also have special limitations in several operations such as copying; a depth/stencil
40 //! format is not compatible with any other format, only with itself.
41 //!
42 //! ## Block-compressed formats
43 //!
44 //! A block-compressed format uses compression to encode a larger block of texels into a smaller
45 //! number of bytes. Individual texels are no longer represented in memory, only the block as a
46 //! whole. An image must consist of a whole number of blocks, so the dimensions of an image must be
47 //! a whole multiple of the block dimensions. Vulkan supports several different compression schemes,
48 //! represented in Vulkano by the `CompressionType` enum.
49 //!
50 //! Overall, block-compressed formats do not behave significantly differently from regular formats.
51 //! They are mostly restricted in terms of compatibility. Because of the compression, the notion of
52 //! bits per component does not apply, so the `components` method will only return whether a
53 //! component is present or not.
54 //!
55 //! ## YCbCr formats
56 //!
57 //! YCbCr, also known as YUV, is an alternative image representation with three components:
58 //! Y for luminance or *luma* (overall brightness) and two color or *chroma* components Cb and Cr
59 //! encoding the blueness and redness respectively. YCbCr formats are primarily used in video
60 //! applications. In Vulkan, the formats used to encode YCbCr data use the green channel to
61 //! represent the luma component, while the blue and red components hold the chroma.
62 //!
63 //! To use most YCbCr formats in an [image view](crate::image::view), a
64 //! [sampler YCbCr conversion](crate::sampler::ycbcr) object must be created, and attached to both
65 //! the image view and the sampler. To query whether a format requires the conversion, you can call
66 //! `ycbcr_chroma_sampling` on a format. As a rule, any format with `444`, `422`, `420`,
67 //! `3PACK` or `4PACK` in the name requires it.
68 //!
69 //! Many YCbCr formats make use of **chroma subsampling**. This is a technique whereby the two
70 //! chroma components are encoded using a lower resolution than the luma component. The human eye is
71 //! less sensitive to color detail than to detail in brightness, so this allows more detail to be
72 //! encoded in less data. Chroma subsampling is indicated with one of three numbered suffixes in a
73 //! format name:
74 //! - `444` indicates a YCbCr format without chroma subsampling. All components have the same
75 //!   resolution.
76 //! - `422` indicates horizontal chroma subsampling. The horizontal resolution of the chroma
77 //!   components is halved, so a single value is shared within a 2x1 block of texels.
78 //! - `420` indicates horizontal and vertical chroma subsampling. Both dimensions of the chroma
79 //!   components are halved, so a single value is shared within a 2x2 block of texels.
80 //!
81 //! Most YCbCr formats, including all of the `444` and `420` formats, are **multi-planar**. Instead
82 //! of storing the components of a single texel together in memory, the components are separated
83 //! into *planes*, which act like independent images. In 3-plane formats, the planes hold the Y,
84 //! Cb and Cr components respectively, while in 2-plane formats, Cb and Cr are combined into a
85 //! two-component plane. Where chroma subsampling is applied, plane 0 has the full resolution, while
86 //! planes 1 and 2 have reduced resolution. Effectively, they are standalone images with half the
87 //! resolution of the original.
88 //!
89 //! The texels of multi-planar images cannot be accessed individually, for example to copy or blit,
90 //! since the components of each texel are split across the planes. Instead, you must access each
91 //! plane as an individual *aspect* of the image. A single-plane aspect of a multi-planar image
92 //! behaves as a regular image, and even has its own format, which can be queried with the `plane`
93 //! method on a format.
94 
95 use crate::{
96     device::physical::PhysicalDevice, image::ImageAspects, macros::vulkan_bitflags,
97     shader::spirv::ImageFormat, DeviceSize,
98 };
99 
100 // Generated by build.rs
101 include!(concat!(env!("OUT_DIR"), "/formats.rs"));
102 
103 impl Format {
104     /// Retrieves the properties of a format when used by a certain device.
105     #[deprecated(
106         since = "0.28.0",
107         note = "Use PhysicalDevice::format_properties instead"
108     )]
109     #[inline]
properties(self, physical_device: PhysicalDevice) -> FormatProperties110     pub fn properties(self, physical_device: PhysicalDevice) -> FormatProperties {
111         physical_device.format_properties(self).unwrap()
112     }
113 
114     /// Returns whether the format can be used with a storage image, without specifying
115     /// the format in the shader, if the
116     /// [`shader_storage_image_read_without_format`](crate::device::Features::shader_storage_image_read_without_format)
117     /// and/or
118     /// [`shader_storage_image_write_without_format`](crate::device::Features::shader_storage_image_write_without_format)
119     /// features are enabled on the device.
120     #[inline]
shader_storage_image_without_format(self) -> bool121     pub fn shader_storage_image_without_format(self) -> bool {
122         matches!(
123             self,
124             Format::R8G8B8A8_UNORM
125                 | Format::R8G8B8A8_SNORM
126                 | Format::R8G8B8A8_UINT
127                 | Format::R8G8B8A8_SINT
128                 | Format::R32_UINT
129                 | Format::R32_SINT
130                 | Format::R32_SFLOAT
131                 | Format::R32G32_UINT
132                 | Format::R32G32_SINT
133                 | Format::R32G32_SFLOAT
134                 | Format::R32G32B32A32_UINT
135                 | Format::R32G32B32A32_SINT
136                 | Format::R32G32B32A32_SFLOAT
137                 | Format::R16G16B16A16_UINT
138                 | Format::R16G16B16A16_SINT
139                 | Format::R16G16B16A16_SFLOAT
140                 | Format::R16G16_SFLOAT
141                 | Format::B10G11R11_UFLOAT_PACK32
142                 | Format::R16_SFLOAT
143                 | Format::R16G16B16A16_UNORM
144                 | Format::A2B10G10R10_UNORM_PACK32
145                 | Format::R16G16_UNORM
146                 | Format::R8G8_UNORM
147                 | Format::R16_UNORM
148                 | Format::R8_UNORM
149                 | Format::R16G16B16A16_SNORM
150                 | Format::R16G16_SNORM
151                 | Format::R8G8_SNORM
152                 | Format::R16_SNORM
153                 | Format::R8_SNORM
154                 | Format::R16G16_SINT
155                 | Format::R8G8_SINT
156                 | Format::R16_SINT
157                 | Format::R8_SINT
158                 | Format::A2B10G10R10_UINT_PACK32
159                 | Format::R16G16_UINT
160                 | Format::R8G8_UINT
161                 | Format::R16_UINT
162                 | Format::R8_UINT
163         )
164     }
165 }
166 
167 impl From<Format> for ash::vk::Format {
168     #[inline]
from(val: Format) -> Self169     fn from(val: Format) -> Self {
170         ash::vk::Format::from_raw(val as i32)
171     }
172 }
173 
174 // https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap46.html#spirvenv-image-formats
175 impl From<ImageFormat> for Option<Format> {
176     #[inline]
from(val: ImageFormat) -> Self177     fn from(val: ImageFormat) -> Self {
178         match val {
179             ImageFormat::Unknown => None,
180             ImageFormat::Rgba32f => Some(Format::R32G32B32A32_SFLOAT),
181             ImageFormat::Rgba16f => Some(Format::R16G16B16A16_SFLOAT),
182             ImageFormat::R32f => Some(Format::R32_SFLOAT),
183             ImageFormat::Rgba8 => Some(Format::R8G8B8A8_UNORM),
184             ImageFormat::Rgba8Snorm => Some(Format::R8G8B8A8_SNORM),
185             ImageFormat::Rg32f => Some(Format::R32G32_SFLOAT),
186             ImageFormat::Rg16f => Some(Format::R16G16_SFLOAT),
187             ImageFormat::R11fG11fB10f => Some(Format::B10G11R11_UFLOAT_PACK32),
188             ImageFormat::R16f => Some(Format::R16_SFLOAT),
189             ImageFormat::Rgba16 => Some(Format::R16G16B16A16_UNORM),
190             ImageFormat::Rgb10A2 => Some(Format::A2B10G10R10_UNORM_PACK32),
191             ImageFormat::Rg16 => Some(Format::R16G16_UNORM),
192             ImageFormat::Rg8 => Some(Format::R8G8_UNORM),
193             ImageFormat::R16 => Some(Format::R16_UNORM),
194             ImageFormat::R8 => Some(Format::R8_UNORM),
195             ImageFormat::Rgba16Snorm => Some(Format::R16G16B16A16_SNORM),
196             ImageFormat::Rg16Snorm => Some(Format::R16G16_SNORM),
197             ImageFormat::Rg8Snorm => Some(Format::R8G8_SNORM),
198             ImageFormat::R16Snorm => Some(Format::R16_SNORM),
199             ImageFormat::R8Snorm => Some(Format::R8_SNORM),
200             ImageFormat::Rgba32i => Some(Format::R32G32B32A32_SINT),
201             ImageFormat::Rgba16i => Some(Format::R16G16B16A16_SINT),
202             ImageFormat::Rgba8i => Some(Format::R8G8B8A8_SINT),
203             ImageFormat::R32i => Some(Format::R32_SINT),
204             ImageFormat::Rg32i => Some(Format::R32G32_SINT),
205             ImageFormat::Rg16i => Some(Format::R16G16_SINT),
206             ImageFormat::Rg8i => Some(Format::R8G8_SINT),
207             ImageFormat::R16i => Some(Format::R16_SINT),
208             ImageFormat::R8i => Some(Format::R8_SINT),
209             ImageFormat::Rgba32ui => Some(Format::R32G32B32A32_UINT),
210             ImageFormat::Rgba16ui => Some(Format::R16G16B16A16_UINT),
211             ImageFormat::Rgba8ui => Some(Format::R8G8B8A8_UINT),
212             ImageFormat::R32ui => Some(Format::R32_UINT),
213             ImageFormat::Rgb10a2ui => Some(Format::A2B10G10R10_UINT_PACK32),
214             ImageFormat::Rg32ui => Some(Format::R32G32_UINT),
215             ImageFormat::Rg16ui => Some(Format::R16G16_UINT),
216             ImageFormat::Rg8ui => Some(Format::R8G8_UINT),
217             ImageFormat::R16ui => Some(Format::R16_UINT),
218             ImageFormat::R8ui => Some(Format::R8_UINT),
219             ImageFormat::R64ui => Some(Format::R64_UINT),
220             ImageFormat::R64i => Some(Format::R64_SINT),
221         }
222     }
223 }
224 
225 /// The block compression scheme used in a format.
226 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
227 #[allow(non_camel_case_types)]
228 pub enum CompressionType {
229     /// Adaptive Scalable Texture Compression, low dynamic range.
230     ASTC_LDR,
231     /// Adaptive Scalable Texture Compression, high dynamic range.
232     ASTC_HDR,
233     /// S3TC Block Compression.
234     BC,
235     /// Ericsson Texture Compression 2.
236     ETC2,
237     /// ETC2 Alpha Compression.
238     EAC,
239     /// PowerVR Texture Compression.
240     PVRTC,
241 }
242 
243 /// For YCbCr formats, the type of chroma sampling used.
244 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
245 pub enum ChromaSampling {
246     /// The chroma components are represented at the same resolution as the luma component.
247     Mode444,
248     /// The chroma components have half the horizontal resolution as the luma component.
249     Mode422,
250     /// The chroma components have half the horizontal and vertical resolution as the luma
251     /// component.
252     Mode420,
253 }
254 
255 impl ChromaSampling {
256     #[inline]
subsampled_extent(self, mut extent: [u32; 3]) -> [u32; 3]257     pub fn subsampled_extent(self, mut extent: [u32; 3]) -> [u32; 3] {
258         match self {
259             ChromaSampling::Mode444 => (),
260             ChromaSampling::Mode422 => {
261                 debug_assert!(extent[0] % 2 == 0);
262                 extent[0] /= 2;
263             }
264             ChromaSampling::Mode420 => {
265                 debug_assert!(extent[0] % 2 == 0 && extent[1] % 2 == 0);
266                 extent[0] /= 2;
267                 extent[1] /= 2;
268             }
269         }
270 
271         extent
272     }
273 }
274 
275 /// The numeric type that represents data of a format in memory.
276 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
277 pub enum NumericType {
278     /// Signed floating-point number.
279     SFLOAT,
280     /// Unsigned floating-point number.
281     UFLOAT,
282     /// Signed integer.
283     SINT,
284     /// Unsigned integer.
285     UINT,
286     /// Signed integer that represents a normalized floating-point value in the range \[-1,1].
287     SNORM,
288     /// Unsigned integer that represents a normalized floating-point value in the range \[0,1].
289     UNORM,
290     /// Signed integer that is converted to a floating-point value directly.
291     SSCALED,
292     /// Unsigned integer that is converted to a floating-point value directly.
293     USCALED,
294     /// Unsigned integer where R, G, B components represent a normalized floating-point value in the
295     /// sRGB color space, while the A component is a simple normalized value as in `UNORM`.
296     SRGB,
297 }
298 
299 /// An opaque type that represents a format compatibility class.
300 ///
301 /// Two formats are compatible if their compatibility classes compare equal.
302 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
303 #[repr(transparent)]
304 pub struct FormatCompatibility(pub(crate) &'static FormatCompatibilityInner);
305 
306 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
307 #[allow(non_camel_case_types)]
308 pub(crate) enum FormatCompatibilityInner {
309     Class_8bit,
310     Class_16bit,
311     Class_24bit,
312     Class_32bit,
313     Class_48bit,
314     Class_64bit,
315     Class_96bit,
316     Class_128bit,
317     Class_192bit,
318     Class_256bit,
319     Class_D16,
320     Class_D24,
321     Class_D32,
322     Class_S8,
323     Class_D16S8,
324     Class_D24S8,
325     Class_D32S8,
326     Class_64bit_R10G10B10A10,
327     Class_64bit_R12G12B12A12,
328     Class_BC1_RGB,
329     Class_BC1_RGBA,
330     Class_BC2,
331     Class_BC3,
332     Class_BC4,
333     Class_BC5,
334     Class_BC6H,
335     Class_BC7,
336     Class_ETC2_RGB,
337     Class_ETC2_RGBA,
338     Class_ETC2_EAC_RGBA,
339     Class_EAC_R,
340     Class_EAC_RG,
341     Class_ASTC_4x4,
342     Class_ASTC_5x4,
343     Class_ASTC_5x5,
344     Class_ASTC_6x5,
345     Class_ASTC_6x6,
346     Class_ASTC_8x5,
347     Class_ASTC_8x6,
348     Class_ASTC_8x8,
349     Class_ASTC_10x5,
350     Class_ASTC_10x6,
351     Class_ASTC_10x8,
352     Class_ASTC_10x10,
353     Class_ASTC_12x10,
354     Class_ASTC_12x12,
355     Class_PVRTC1_2BPP,
356     Class_PVRTC1_4BPP,
357     Class_PVRTC2_2BPP,
358     Class_PVRTC2_4BPP,
359     Class_32bit_G8B8G8R8,
360     Class_32bit_B8G8R8G8,
361     Class_64bit_G10B10G10R10,
362     Class_64bit_B10G10R10G10,
363     Class_64bit_G12B12G12R12,
364     Class_64bit_B12G12R12G12,
365     Class_64bit_G16B16G16R16,
366     Class_64bit_B16G16R16G16,
367     Class_8bit_3plane_420,
368     Class_8bit_2plane_420,
369     Class_10bit_3plane_420,
370     Class_10bit_2plane_420,
371     Class_12bit_3plane_420,
372     Class_12bit_2plane_420,
373     Class_16bit_3plane_420,
374     Class_16bit_2plane_420,
375     Class_8bit_3plane_422,
376     Class_8bit_2plane_422,
377     Class_10bit_3plane_422,
378     Class_10bit_2plane_422,
379     Class_12bit_3plane_422,
380     Class_12bit_2plane_422,
381     Class_16bit_3plane_422,
382     Class_16bit_2plane_422,
383     Class_8bit_3plane_444,
384     Class_10bit_3plane_444,
385     Class_12bit_3plane_444,
386     Class_16bit_3plane_444,
387     Class_8bit_2plane_444,
388     Class_10bit_2plane_444,
389     Class_12bit_2plane_444,
390     Class_16bit_2plane_444,
391 }
392 
393 /// Describes a uniform value that will be used to fill an image.
394 #[derive(Clone, Copy, Debug, PartialEq)]
395 pub enum ClearValue {
396     /// Value for floating-point attachments, including `UNORM`, `SNORM`, `SFLOAT`.
397     Float([f32; 4]),
398 
399     /// Value for integer attachments, including `SINT`.
400     Int([i32; 4]),
401 
402     /// Value for unsigned integer attachments, including `UINT`.
403     Uint([u32; 4]),
404 
405     /// Value for depth attachments.
406     Depth(f32),
407 
408     /// Value for stencil attachments.
409     Stencil(u32),
410 
411     /// Value for depth and stencil attachments.
412     DepthStencil((f32, u32)),
413 }
414 
415 impl From<ClearValue> for ash::vk::ClearValue {
416     #[inline]
from(val: ClearValue) -> Self417     fn from(val: ClearValue) -> Self {
418         match val {
419             ClearValue::Float(val) => Self {
420                 color: ash::vk::ClearColorValue { float32: val },
421             },
422             ClearValue::Int(val) => Self {
423                 color: ash::vk::ClearColorValue { int32: val },
424             },
425             ClearValue::Uint(val) => Self {
426                 color: ash::vk::ClearColorValue { uint32: val },
427             },
428             ClearValue::Depth(depth) => Self {
429                 depth_stencil: ash::vk::ClearDepthStencilValue { depth, stencil: 0 },
430             },
431             ClearValue::Stencil(stencil) => Self {
432                 depth_stencil: ash::vk::ClearDepthStencilValue {
433                     depth: 0.0,
434                     stencil,
435                 },
436             },
437             ClearValue::DepthStencil((depth, stencil)) => Self {
438                 depth_stencil: ash::vk::ClearDepthStencilValue { depth, stencil },
439             },
440         }
441     }
442 }
443 
444 impl From<ClearColorValue> for ClearValue {
445     #[inline]
from(val: ClearColorValue) -> Self446     fn from(val: ClearColorValue) -> Self {
447         match val {
448             ClearColorValue::Float(val) => Self::Float(val),
449             ClearColorValue::Int(val) => Self::Int(val),
450             ClearColorValue::Uint(val) => Self::Uint(val),
451         }
452     }
453 }
454 
455 impl From<[f32; 1]> for ClearValue {
456     #[inline]
from(val: [f32; 1]) -> Self457     fn from(val: [f32; 1]) -> Self {
458         Self::Float([val[0], 0.0, 0.0, 1.0])
459     }
460 }
461 
462 impl From<[f32; 2]> for ClearValue {
463     #[inline]
from(val: [f32; 2]) -> Self464     fn from(val: [f32; 2]) -> Self {
465         Self::Float([val[0], val[1], 0.0, 1.0])
466     }
467 }
468 
469 impl From<[f32; 3]> for ClearValue {
470     #[inline]
from(val: [f32; 3]) -> Self471     fn from(val: [f32; 3]) -> Self {
472         Self::Float([val[0], val[1], val[2], 1.0])
473     }
474 }
475 
476 impl From<[f32; 4]> for ClearValue {
477     #[inline]
from(val: [f32; 4]) -> Self478     fn from(val: [f32; 4]) -> Self {
479         Self::Float(val)
480     }
481 }
482 
483 impl From<[u32; 1]> for ClearValue {
484     #[inline]
from(val: [u32; 1]) -> Self485     fn from(val: [u32; 1]) -> Self {
486         Self::Uint([val[0], 0, 0, 0]) // TODO: is alpha value 0 correct?
487     }
488 }
489 
490 impl From<[u32; 2]> for ClearValue {
491     #[inline]
from(val: [u32; 2]) -> Self492     fn from(val: [u32; 2]) -> Self {
493         Self::Uint([val[0], val[1], 0, 0]) // TODO: is alpha value 0 correct?
494     }
495 }
496 
497 impl From<[u32; 3]> for ClearValue {
498     #[inline]
from(val: [u32; 3]) -> Self499     fn from(val: [u32; 3]) -> Self {
500         Self::Uint([val[0], val[1], val[2], 0]) // TODO: is alpha value 0 correct?
501     }
502 }
503 
504 impl From<[u32; 4]> for ClearValue {
505     #[inline]
from(val: [u32; 4]) -> Self506     fn from(val: [u32; 4]) -> Self {
507         Self::Uint(val)
508     }
509 }
510 
511 impl From<[i32; 1]> for ClearValue {
512     #[inline]
from(val: [i32; 1]) -> Self513     fn from(val: [i32; 1]) -> Self {
514         Self::Int([val[0], 0, 0, 0]) // TODO: is alpha value 0 correct?
515     }
516 }
517 
518 impl From<[i32; 2]> for ClearValue {
519     #[inline]
from(val: [i32; 2]) -> Self520     fn from(val: [i32; 2]) -> Self {
521         Self::Int([val[0], val[1], 0, 0]) // TODO: is alpha value 0 correct?
522     }
523 }
524 
525 impl From<[i32; 3]> for ClearValue {
526     #[inline]
from(val: [i32; 3]) -> Self527     fn from(val: [i32; 3]) -> Self {
528         Self::Int([val[0], val[1], val[2], 0]) // TODO: is alpha value 0 correct?
529     }
530 }
531 
532 impl From<[i32; 4]> for ClearValue {
533     #[inline]
from(val: [i32; 4]) -> Self534     fn from(val: [i32; 4]) -> Self {
535         Self::Int(val)
536     }
537 }
538 
539 impl From<f32> for ClearValue {
540     #[inline]
from(val: f32) -> Self541     fn from(val: f32) -> Self {
542         Self::Depth(val)
543     }
544 }
545 
546 impl From<u32> for ClearValue {
547     #[inline]
from(val: u32) -> Self548     fn from(val: u32) -> Self {
549         Self::Stencil(val)
550     }
551 }
552 
553 impl From<(f32, u32)> for ClearValue {
554     #[inline]
from(val: (f32, u32)) -> Self555     fn from(val: (f32, u32)) -> Self {
556         Self::DepthStencil(val)
557     }
558 }
559 
560 /// A value that will be used to clear a color image.
561 #[derive(Clone, Copy, Debug, PartialEq)]
562 pub enum ClearColorValue {
563     /// Value for formats with a numeric type that is not `SINT` or `UINT`.
564     Float([f32; 4]),
565     /// Value for formats with a numeric type of `SINT`.
566     Int([i32; 4]),
567     /// Value for formats with a numeric type of `UINT`.
568     Uint([u32; 4]),
569 }
570 
571 impl From<ClearColorValue> for ash::vk::ClearColorValue {
572     #[inline]
from(val: ClearColorValue) -> Self573     fn from(val: ClearColorValue) -> Self {
574         match val {
575             ClearColorValue::Float(float32) => Self { float32 },
576             ClearColorValue::Int(int32) => Self { int32 },
577             ClearColorValue::Uint(uint32) => Self { uint32 },
578         }
579     }
580 }
581 
582 impl From<[f32; 1]> for ClearColorValue {
583     #[inline]
from(val: [f32; 1]) -> Self584     fn from(val: [f32; 1]) -> Self {
585         Self::Float([val[0], 0.0, 0.0, 1.0])
586     }
587 }
588 
589 impl From<[f32; 2]> for ClearColorValue {
590     #[inline]
from(val: [f32; 2]) -> Self591     fn from(val: [f32; 2]) -> Self {
592         Self::Float([val[0], val[1], 0.0, 1.0])
593     }
594 }
595 
596 impl From<[f32; 3]> for ClearColorValue {
597     #[inline]
from(val: [f32; 3]) -> Self598     fn from(val: [f32; 3]) -> Self {
599         Self::Float([val[0], val[1], val[2], 1.0])
600     }
601 }
602 
603 impl From<[f32; 4]> for ClearColorValue {
604     #[inline]
from(val: [f32; 4]) -> Self605     fn from(val: [f32; 4]) -> Self {
606         Self::Float(val)
607     }
608 }
609 
610 impl From<[i32; 1]> for ClearColorValue {
611     #[inline]
from(val: [i32; 1]) -> Self612     fn from(val: [i32; 1]) -> Self {
613         Self::Int([val[0], 0, 0, 1])
614     }
615 }
616 
617 impl From<[i32; 2]> for ClearColorValue {
618     #[inline]
from(val: [i32; 2]) -> Self619     fn from(val: [i32; 2]) -> Self {
620         Self::Int([val[0], val[1], 0, 1])
621     }
622 }
623 
624 impl From<[i32; 3]> for ClearColorValue {
625     #[inline]
from(val: [i32; 3]) -> Self626     fn from(val: [i32; 3]) -> Self {
627         Self::Int([val[0], val[1], val[2], 1])
628     }
629 }
630 
631 impl From<[i32; 4]> for ClearColorValue {
632     #[inline]
from(val: [i32; 4]) -> Self633     fn from(val: [i32; 4]) -> Self {
634         Self::Int(val)
635     }
636 }
637 
638 impl From<[u32; 1]> for ClearColorValue {
639     #[inline]
from(val: [u32; 1]) -> Self640     fn from(val: [u32; 1]) -> Self {
641         Self::Uint([val[0], 0, 0, 1])
642     }
643 }
644 
645 impl From<[u32; 2]> for ClearColorValue {
646     #[inline]
from(val: [u32; 2]) -> Self647     fn from(val: [u32; 2]) -> Self {
648         Self::Uint([val[0], val[1], 0, 1])
649     }
650 }
651 
652 impl From<[u32; 3]> for ClearColorValue {
653     #[inline]
from(val: [u32; 3]) -> Self654     fn from(val: [u32; 3]) -> Self {
655         Self::Uint([val[0], val[1], val[2], 1])
656     }
657 }
658 
659 impl From<[u32; 4]> for ClearColorValue {
660     #[inline]
from(val: [u32; 4]) -> Self661     fn from(val: [u32; 4]) -> Self {
662         Self::Uint(val)
663     }
664 }
665 
666 /// A value that will be used to clear a depth/stencil image.
667 #[derive(Clone, Copy, Debug, Default, PartialEq)]
668 pub struct ClearDepthStencilValue {
669     /// Value for the depth component.
670     pub depth: f32,
671     /// Value for the stencil component.
672     pub stencil: u32,
673 }
674 
675 impl From<ClearDepthStencilValue> for ash::vk::ClearDepthStencilValue {
676     #[inline]
from(val: ClearDepthStencilValue) -> Self677     fn from(val: ClearDepthStencilValue) -> Self {
678         Self {
679             depth: val.depth,
680             stencil: val.stencil,
681         }
682     }
683 }
684 
685 impl From<f32> for ClearDepthStencilValue {
686     #[inline]
from(depth: f32) -> Self687     fn from(depth: f32) -> Self {
688         Self { depth, stencil: 0 }
689     }
690 }
691 
692 impl From<u32> for ClearDepthStencilValue {
693     #[inline]
from(stencil: u32) -> Self694     fn from(stencil: u32) -> Self {
695         Self {
696             depth: 0.0,
697             stencil,
698         }
699     }
700 }
701 
702 impl From<(f32, u32)> for ClearDepthStencilValue {
703     #[inline]
from((depth, stencil): (f32, u32)) -> Self704     fn from((depth, stencil): (f32, u32)) -> Self {
705         Self { depth, stencil }
706     }
707 }
708 
709 /// The properties of a format that are supported by a physical device.
710 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
711 pub struct FormatProperties {
712     /// Features available for images with linear tiling.
713     pub linear_tiling_features: FormatFeatures,
714 
715     /// Features available for images with optimal tiling.
716     pub optimal_tiling_features: FormatFeatures,
717 
718     /// Features available for buffers.
719     pub buffer_features: FormatFeatures,
720 
721     pub _ne: crate::NonExhaustive,
722 }
723 
724 impl Default for FormatProperties {
725     #[inline]
default() -> Self726     fn default() -> Self {
727         Self {
728             linear_tiling_features: Default::default(),
729             optimal_tiling_features: Default::default(),
730             buffer_features: Default::default(),
731             _ne: crate::NonExhaustive(()),
732         }
733     }
734 }
735 
736 impl FormatProperties {
737     /// Returns the potential format features, following the definition of
738     /// <https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap43.html#potential-format-features>.
739     #[inline]
potential_format_features(&self) -> FormatFeatures740     pub fn potential_format_features(&self) -> FormatFeatures {
741         self.linear_tiling_features | self.optimal_tiling_features
742     }
743 }
744 
745 vulkan_bitflags! {
746     #[non_exhaustive]
747 
748     /// The features supported by a device for an image or buffer with a particular format.
749     FormatFeatures = FormatFeatureFlags2(u64);
750 
751     /* Image usage  */
752 
753     /// Can be used with a sampled image descriptor.
754     SAMPLED_IMAGE = SAMPLED_IMAGE,
755 
756     /// Can be used with a storage image descriptor.
757     STORAGE_IMAGE = STORAGE_IMAGE,
758 
759     /// Can be used with a storage image descriptor with atomic operations in a shader.
760     STORAGE_IMAGE_ATOMIC = STORAGE_IMAGE_ATOMIC,
761 
762     /// Can be used with a storage image descriptor for reading, without specifying a format on the
763     /// image view.
764     STORAGE_READ_WITHOUT_FORMAT = STORAGE_READ_WITHOUT_FORMAT {
765         api_version: V1_3,
766         device_extensions: [khr_format_feature_flags2],
767     },
768 
769     /// Can be used with a storage image descriptor for writing, without specifying a format on the
770     /// image view.
771     STORAGE_WRITE_WITHOUT_FORMAT = STORAGE_WRITE_WITHOUT_FORMAT {
772         api_version: V1_3,
773         device_extensions: [khr_format_feature_flags2],
774     },
775 
776     /// Can be used with a color attachment in a framebuffer, or with an input attachment
777     /// descriptor.
778     COLOR_ATTACHMENT = COLOR_ATTACHMENT,
779 
780     /// Can be used with a color attachment in a framebuffer with blending, or with an input
781     /// attachment descriptor.
782     COLOR_ATTACHMENT_BLEND = COLOR_ATTACHMENT_BLEND,
783 
784     /// Can be used with a depth/stencil attachment in a framebuffer, or with an input attachment
785     /// descriptor.
786     DEPTH_STENCIL_ATTACHMENT = DEPTH_STENCIL_ATTACHMENT,
787 
788     /// Can be used with a fragment density map attachment in a framebuffer.
789     FRAGMENT_DENSITY_MAP = FRAGMENT_DENSITY_MAP_EXT {
790         device_extensions: [ext_fragment_density_map],
791     },
792 
793     /// Can be used with a fragment shading rate attachment in a framebuffer.
794     FRAGMENT_SHADING_RATE_ATTACHMENT = FRAGMENT_SHADING_RATE_ATTACHMENT_KHR {
795         device_extensions: [khr_fragment_shading_rate],
796     },
797 
798     /// Can be used with the source image in a transfer (copy) operation.
799     TRANSFER_SRC = TRANSFER_SRC {
800         api_version: V1_1,
801         device_extensions: [khr_maintenance1],
802     },
803 
804     /// Can be used with the destination image in a transfer (copy) operation.
805     TRANSFER_DST = TRANSFER_DST {
806         api_version: V1_1,
807         device_extensions: [khr_maintenance1],
808     },
809 
810     /// Can be used with the source image in a blit operation.
811     BLIT_SRC = BLIT_SRC,
812 
813     /// Can be used with the destination image in a blit operation.
814     BLIT_DST = BLIT_DST,
815 
816     /* Sampling  */
817 
818     /// Can be used with samplers or as a blit source, using the
819     /// [`Linear`](crate::sampler::Filter::Linear) filter.
820     SAMPLED_IMAGE_FILTER_LINEAR = SAMPLED_IMAGE_FILTER_LINEAR,
821 
822     /// Can be used with samplers or as a blit source, using the
823     /// [`Cubic`](crate::sampler::Filter::Cubic) filter.
824     SAMPLED_IMAGE_FILTER_CUBIC = SAMPLED_IMAGE_FILTER_CUBIC_EXT {
825         device_extensions: [ext_filter_cubic, img_filter_cubic],
826     },
827 
828     /// Can be used with samplers using a reduction mode of
829     /// [`Min`](crate::sampler::SamplerReductionMode::Min) or
830     /// [`Max`](crate::sampler::SamplerReductionMode::Max).
831     SAMPLED_IMAGE_FILTER_MINMAX = SAMPLED_IMAGE_FILTER_MINMAX {
832         api_version: V1_2,
833         device_extensions: [ext_sampler_filter_minmax],
834     },
835 
836     /// Can be used with sampler YCbCr conversions using a chroma offset of
837     /// [`Midpoint`](crate::sampler::ycbcr::ChromaLocation::Midpoint).
838     MIDPOINT_CHROMA_SAMPLES = MIDPOINT_CHROMA_SAMPLES {
839         api_version: V1_1,
840         device_extensions: [khr_sampler_ycbcr_conversion],
841     },
842 
843     /// Can be used with sampler YCbCr conversions using a chroma offset of
844     /// [`CositedEven`](crate::sampler::ycbcr::ChromaLocation::CositedEven).
845     COSITED_CHROMA_SAMPLES = COSITED_CHROMA_SAMPLES {
846         api_version: V1_1,
847         device_extensions: [khr_sampler_ycbcr_conversion],
848     },
849 
850     /// Can be used with sampler YCbCr conversions using the
851     /// [`Linear`](crate::sampler::Filter::Linear) chroma filter.
852     SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER = SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER {
853         api_version: V1_1,
854         device_extensions: [khr_sampler_ycbcr_conversion],
855     },
856 
857     /// Can be used with sampler YCbCr conversions whose chroma filter differs from the filters of
858     /// the base sampler.
859     SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER = SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER {
860         api_version: V1_1,
861         device_extensions: [khr_sampler_ycbcr_conversion],
862     },
863 
864     /// When used with a sampler YCbCr conversion, the implementation will always perform
865     /// explicit chroma reconstruction.
866     SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT = SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT {
867         api_version: V1_1,
868         device_extensions: [khr_sampler_ycbcr_conversion],
869     },
870 
871     /// Can be used with sampler YCbCr conversions with forced explicit reconstruction.
872     SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE = SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE {
873         api_version: V1_1,
874         device_extensions: [khr_sampler_ycbcr_conversion],
875     },
876 
877     /// Can be used with samplers using depth comparison.
878     SAMPLED_IMAGE_DEPTH_COMPARISON = SAMPLED_IMAGE_DEPTH_COMPARISON {
879         api_version: V1_3,
880         device_extensions: [khr_format_feature_flags2],
881     },
882 
883     /* Video */
884 
885     /// Can be used with the output image of a video decode operation.
886     VIDEO_DECODE_OUTPUT = VIDEO_DECODE_OUTPUT_KHR {
887         device_extensions: [khr_video_decode_queue],
888     },
889 
890     /// Can be used with the DPB image of a video decode operation.
891     VIDEO_DECODE_DPB = VIDEO_DECODE_DPB_KHR {
892         device_extensions: [khr_video_decode_queue],
893     },
894 
895     /// Can be used with the input image of a video encode operation.
896     VIDEO_ENCODE_INPUT = VIDEO_ENCODE_INPUT_KHR {
897         device_extensions: [khr_video_encode_queue],
898     },
899 
900     /// Can be used with the DPB image of a video encode operation.
901     VIDEO_ENCODE_DPB = VIDEO_ENCODE_DPB_KHR {
902         device_extensions: [khr_video_encode_queue],
903     },
904 
905     /* Misc image features */
906 
907     /// For multi-planar formats, can be used with images created with the [`DISJOINT`] flag.
908     ///
909     /// [`DISJOINT`]: crate::image::ImageCreateFlags::DISJOINT
910     DISJOINT = DISJOINT {
911         api_version: V1_1,
912         device_extensions: [khr_sampler_ycbcr_conversion],
913     },
914 
915     // TODO: document
916     LINEAR_COLOR_ATTACHMENT = LINEAR_COLOR_ATTACHMENT_NV {
917         device_extensions: [nv_linear_color_attachment],
918     },
919 
920     // TODO: document
921     WEIGHT_IMAGE = WEIGHT_IMAGE_QCOM {
922         device_extensions: [qcom_image_processing],
923     },
924 
925     // TODO: document
926     WEIGHT_SAMPLED_IMAGE = WEIGHT_SAMPLED_IMAGE_QCOM {
927         device_extensions: [qcom_image_processing],
928     },
929 
930     // TODO: document
931     BLOCK_MATCHING = BLOCK_MATCHING_QCOM {
932         device_extensions: [qcom_image_processing],
933     },
934 
935     // TODO: document
936     BOX_FILTER_SAMPLED = BOX_FILTER_SAMPLED_QCOM {
937         device_extensions: [qcom_image_processing],
938     },
939 
940     // TODO: document
941     OPTICAL_FLOW_IMAGE = OPTICAL_FLOW_IMAGE_NV {
942         device_extensions: [nv_optical_flow],
943     },
944 
945     // TODO: document
946     OPTICAL_FLOW_VECTOR = OPTICAL_FLOW_VECTOR_NV {
947         device_extensions: [nv_optical_flow],
948     },
949 
950     // TODO: document
951     OPTICAL_FLOW_COST = OPTICAL_FLOW_COST_NV {
952         device_extensions: [nv_optical_flow],
953     },
954 
955     /* Buffer usage  */
956 
957     /// Can be used with a uniform texel buffer descriptor.
958     UNIFORM_TEXEL_BUFFER = UNIFORM_TEXEL_BUFFER,
959 
960     /// Can be used with a storage texel buffer descriptor.
961     STORAGE_TEXEL_BUFFER = STORAGE_TEXEL_BUFFER,
962 
963     /// Can be used with a storage texel buffer descriptor with atomic operations in a shader.
964     STORAGE_TEXEL_BUFFER_ATOMIC = STORAGE_TEXEL_BUFFER_ATOMIC,
965 
966     /// Can be used as the format of a vertex attribute in the vertex input state of a graphics
967     /// pipeline.
968     VERTEX_BUFFER = VERTEX_BUFFER,
969 
970     /// Can be used with the vertex buffer of an acceleration structure.
971     ACCELERATION_STRUCTURE_VERTEX_BUFFER = ACCELERATION_STRUCTURE_VERTEX_BUFFER_KHR {
972         device_extensions: [khr_acceleration_structure],
973     },
974 }
975 
976 impl From<ash::vk::FormatFeatureFlags> for FormatFeatures {
977     #[inline]
from(val: ash::vk::FormatFeatureFlags) -> Self978     fn from(val: ash::vk::FormatFeatureFlags) -> Self {
979         Self::from(ash::vk::FormatFeatureFlags2::from_raw(val.as_raw() as u64))
980     }
981 }
982