• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 of images supported by Vulkan.
11 //!
12 //! # Formats
13 //!
14 //! List of suffixes:
15 //!
16 //! - `Unorm` means that the values are unsigned integers that are converted into floating points.
17 //!   The maximum possible representable value becomes `1.0`, and the minimum representable value
18 //!   becomes `0.0`. For example the value `255` in a `R8Unorm` will be interpreted as `1.0`.
19 //!
20 //! - `Snorm` is the same as `Unorm`, but the integers are signed and the range is from `-1.0` to
21 //!   `1.0` instead.
22 //!
23 //! - `Uscaled` means that the values are unsigned integers that are converted into floating points.
24 //!   No change in the value is done. For example the value `255` in a `R8Uscaled` will be
25 //!   interpreted as `255.0`.
26 //!
27 //! - `Sscaled` is the same as `Uscaled` expect that the integers are signed.
28 //!
29 //! - `Uint` means that the values are unsigned integers. No conversion is performed.
30 //!
31 //! - `Sint` means that the values are signed integers. No conversion is performed.
32 //!
33 //! - `Ufloat` means that the values are unsigned floating points. No conversion is performed. This
34 //!   format is very unusual.
35 //!
36 //! - `Sfloat` means that the values are regular floating points. No conversion is performed.
37 //!
38 //! - `Srgb` is the same as `Unorm`, except that the value is interpreted as being in the sRGB
39 //!   color space. This means that its value will be converted to fit in the RGB color space when
40 //!   it is read. The fourth channel (usually used for alpha), if present, is not concerned by the
41 //!   conversion.
42 //!
43 //! # Choosing a format
44 //!
45 //! The following formats are guaranteed to be supported for everything that is related to
46 //! texturing (ie. blitting source and sampling them linearly). You should choose one of these
47 //! formats if you have an image that you are going to sample from:
48 //!
49 //! - B4G4R4A4UnormPack16
50 //! - R5G6B5UnormPack16
51 //! - A1R5G5B5UnormPack16
52 //! - R8Unorm
53 //! - R8Snorm
54 //! - R8G8Unorm
55 //! - R8G8Snorm
56 //! - R8G8B8A8Unorm
57 //! - R8G8B8A8Snorm
58 //! - R8G8B8A8Srgb
59 //! - B8G8R8A8Unorm
60 //! - B8G8R8A8Srgb
61 //! - A8B8G8R8UnormPack32
62 //! - A8B8G8R8SnormPack32
63 //! - A8B8G8R8SrgbPack32
64 //! - A2B10G10R10UnormPack32
65 //! - R16Sfloat
66 //! - R16G16Sfloat
67 //! - R16G16B16A16Sfloat
68 //! - B10G11R11UfloatPack32
69 //! - E5B9G9R9UfloatPack32
70 //!
71 //! The following formats are guaranteed to be supported for everything that is related to
72 //! intermediate render targets (ie. blitting destination, color attachment and sampling linearly):
73 //!
74 //! - R5G6B5UnormPack16
75 //! - A1R5G5B5UnormPack16
76 //! - R8Unorm
77 //! - R8G8Unorm
78 //! - R8G8B8A8Unorm
79 //! - R8G8B8A8Srgb
80 //! - B8G8R8A8Unorm
81 //! - B8G8R8A8Srgb
82 //! - A8B8G8R8UnormPack32
83 //! - A8B8G8R8SrgbPack32
84 //! - A2B10G10R10UnormPack32
85 //! - R16Sfloat
86 //! - R16G16Sfloat
87 //! - R16G16B16A16Sfloat
88 //!
89 //! For depth images, only `D16Unorm` is guaranteed to be supported. For depth-stencil images,
90 //! it is guaranteed that either `D24Unorm_S8Uint` or `D32Sfloat_S8Uint` are supported.
91 //!
92 //! // TODO: storage formats
93 //!
94 
95 use crate::device::physical::PhysicalDevice;
96 use crate::image::ImageAspects;
97 use crate::DeviceSize;
98 use crate::VulkanObject;
99 use half::f16;
100 use std::convert::TryFrom;
101 use std::mem::MaybeUninit;
102 use std::vec::IntoIter as VecIntoIter;
103 use std::{error, fmt, mem};
104 
105 macro_rules! formats {
106     ($($name:ident => { vk: $vk:ident, bdim: $bdim:expr, size: $sz:expr, ty: $f_ty:ident$(, planes: $planes:expr)?},)+) => (
107         /// An enumeration of all the possible formats.
108         #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
109         #[repr(i32)]
110         #[allow(missing_docs)]
111         #[allow(non_camel_case_types)]
112         pub enum Format {
113             $($name = ash::vk::Format::$vk.as_raw(),)+
114         }
115 
116         impl Format {
117             /*pub fn is_supported_for_vertex_attributes(&self) -> bool {
118 
119             }
120 
121             .. other functions ..
122             */
123 
124             /// Returns the size in bytes of an element of this format. For block based formats
125             /// this will be the size of a single block. Returns `None` if the
126             /// size is irrelevant.
127             #[inline]
128             pub const fn size(&self) -> Option<DeviceSize> {
129                 match *self {
130                     $(
131                         Format::$name => $sz,
132                     )+
133                 }
134             }
135 
136             /// Returns (width, height) of the dimensions for block based formats. For
137             /// non block formats will return (1,1)
138             #[inline]
139             pub const fn block_dimensions(&self) -> (u32, u32) {
140                 match *self {
141                     $(
142                         Format::$name => $bdim,
143                     )+
144                 }
145             }
146 
147             /// Returns the data type of the format.
148             #[inline]
149             pub const fn ty(&self) -> FormatTy {
150                 match *self {
151                     $(
152                         Format::$name => FormatTy::$f_ty,
153                     )+
154                 }
155             }
156 
157             /// Returns the number of planes that images of this format have.
158             ///
159             /// Returns 0 if the format is not multi-planar.
160             #[inline]
161             pub const fn planes(&self) -> u8 {
162                 match *self {
163                     $(
164                         $(Format::$name => $planes,)?
165                     )+
166                     _ => 0,
167                 }
168             }
169         }
170 
171         impl TryFrom<ash::vk::Format> for Format {
172             type Error = ();
173 
174             #[inline]
175             fn try_from(val: ash::vk::Format) -> Result<Format, ()> {
176                 match val {
177                     $(
178                         ash::vk::Format::$vk => Ok(Format::$name),
179                     )+
180                     _ => Err(()),
181                 }
182             }
183         }
184 
185         impl From<Format> for ash::vk::Format {
186             #[inline]
187             fn from(val: Format) -> Self {
188                 ash::vk::Format::from_raw(val as i32)
189             }
190         }
191     );
192 }
193 
194 formats! {
195     R4G4UnormPack8 => {vk: R4G4_UNORM_PACK8, bdim: (1, 1), size: Some(1), ty: Float},
196     R4G4B4A4UnormPack16 => {vk: R4G4B4A4_UNORM_PACK16, bdim: (1, 1), size: Some(2), ty: Float},
197     B4G4R4A4UnormPack16 => {vk: B4G4R4A4_UNORM_PACK16, bdim: (1, 1), size: Some(2), ty: Float},
198     R5G6B5UnormPack16 => {vk: R5G6B5_UNORM_PACK16, bdim: (1, 1), size: Some(2), ty: Float},
199     B5G6R5UnormPack16 => {vk: B5G6R5_UNORM_PACK16, bdim: (1, 1), size: Some(2), ty: Float},
200     R5G5B5A1UnormPack16 => {vk: R5G5B5A1_UNORM_PACK16, bdim: (1, 1), size: Some(2), ty: Float},
201     B5G5R5A1UnormPack16 => {vk: B5G5R5A1_UNORM_PACK16, bdim: (1, 1), size: Some(2), ty: Float},
202     A1R5G5B5UnormPack16 => {vk: A1R5G5B5_UNORM_PACK16, bdim: (1, 1), size: Some(2), ty: Float},
203     R8Unorm => {vk: R8_UNORM, bdim: (1, 1), size: Some(1), ty: Float},
204     R8Snorm => {vk: R8_SNORM, bdim: (1, 1), size: Some(1), ty: Float},
205     R8Uscaled => {vk: R8_USCALED, bdim: (1, 1), size: Some(1), ty: Float},
206     R8Sscaled => {vk: R8_SSCALED, bdim: (1, 1), size: Some(1), ty: Float},
207     R8Uint => {vk: R8_UINT, bdim: (1, 1), size: Some(1), ty: Uint},
208     R8Sint => {vk: R8_SINT, bdim: (1, 1), size: Some(1), ty: Sint},
209     R8Srgb => {vk: R8_SRGB, bdim: (1, 1), size: Some(1), ty: Float},
210     R8G8Unorm => {vk: R8G8_UNORM, bdim: (1, 1), size: Some(2), ty: Float},
211     R8G8Snorm => {vk: R8G8_SNORM, bdim: (1, 1), size: Some(2), ty: Float},
212     R8G8Uscaled => {vk: R8G8_USCALED, bdim: (1, 1), size: Some(2), ty: Float},
213     R8G8Sscaled => {vk: R8G8_SSCALED, bdim: (1, 1), size: Some(2), ty: Float},
214     R8G8Uint => {vk: R8G8_UINT, bdim: (1, 1), size: Some(2), ty: Uint},
215     R8G8Sint => {vk: R8G8_SINT, bdim: (1, 1), size: Some(2), ty: Sint},
216     R8G8Srgb => {vk: R8G8_SRGB, bdim: (1, 1), size: Some(2), ty: Float},
217     R8G8B8Unorm => {vk: R8G8B8_UNORM, bdim: (1, 1), size: Some(3), ty: Float},
218     R8G8B8Snorm => {vk: R8G8B8_SNORM, bdim: (1, 1), size: Some(3), ty: Float},
219     R8G8B8Uscaled => {vk: R8G8B8_USCALED, bdim: (1, 1), size: Some(3), ty: Float},
220     R8G8B8Sscaled => {vk: R8G8B8_SSCALED, bdim: (1, 1), size: Some(3), ty: Float},
221     R8G8B8Uint => {vk: R8G8B8_UINT, bdim: (1, 1), size: Some(3), ty: Uint},
222     R8G8B8Sint => {vk: R8G8B8_SINT, bdim: (1, 1), size: Some(3), ty: Sint},
223     R8G8B8Srgb => {vk: R8G8B8_SRGB, bdim: (1, 1), size: Some(3), ty: Float},
224     B8G8R8Unorm => {vk: B8G8R8_UNORM, bdim: (1, 1), size: Some(3), ty: Float},
225     B8G8R8Snorm => {vk: B8G8R8_SNORM, bdim: (1, 1), size: Some(3), ty: Float},
226     B8G8R8Uscaled => {vk: B8G8R8_USCALED, bdim: (1, 1), size: Some(3), ty: Float},
227     B8G8R8Sscaled => {vk: B8G8R8_SSCALED, bdim: (1, 1), size: Some(3), ty: Float},
228     B8G8R8Uint => {vk: B8G8R8_UINT, bdim: (1, 1), size: Some(3), ty: Uint},
229     B8G8R8Sint => {vk: B8G8R8_SINT, bdim: (1, 1), size: Some(3), ty: Sint},
230     B8G8R8Srgb => {vk: B8G8R8_SRGB, bdim: (1, 1), size: Some(3), ty: Float},
231     R8G8B8A8Unorm => {vk: R8G8B8A8_UNORM, bdim: (1, 1), size: Some(4), ty: Float},
232     R8G8B8A8Snorm => {vk: R8G8B8A8_SNORM, bdim: (1, 1), size: Some(4), ty: Float},
233     R8G8B8A8Uscaled => {vk: R8G8B8A8_USCALED, bdim: (1, 1), size: Some(4), ty: Float},
234     R8G8B8A8Sscaled => {vk: R8G8B8A8_SSCALED, bdim: (1, 1), size: Some(4), ty: Float},
235     R8G8B8A8Uint => {vk: R8G8B8A8_UINT, bdim: (1, 1), size: Some(4), ty: Uint},
236     R8G8B8A8Sint => {vk: R8G8B8A8_SINT, bdim: (1, 1), size: Some(4), ty: Sint},
237     R8G8B8A8Srgb => {vk: R8G8B8A8_SRGB, bdim: (1, 1), size: Some(4), ty: Float},
238     B8G8R8A8Unorm => {vk: B8G8R8A8_UNORM, bdim: (1, 1), size: Some(4), ty: Float},
239     B8G8R8A8Snorm => {vk: B8G8R8A8_SNORM, bdim: (1, 1), size: Some(4), ty: Float},
240     B8G8R8A8Uscaled => {vk: B8G8R8A8_USCALED, bdim: (1, 1), size: Some(4), ty: Float},
241     B8G8R8A8Sscaled => {vk: B8G8R8A8_SSCALED, bdim: (1, 1), size: Some(4), ty: Float},
242     B8G8R8A8Uint => {vk: B8G8R8A8_UINT, bdim: (1, 1), size: Some(4), ty: Uint},
243     B8G8R8A8Sint => {vk: B8G8R8A8_SINT, bdim: (1, 1), size: Some(4), ty: Sint},
244     B8G8R8A8Srgb => {vk: B8G8R8A8_SRGB, bdim: (1, 1), size: Some(4), ty: Float},
245     A8B8G8R8UnormPack32 => {vk: A8B8G8R8_UNORM_PACK32, bdim: (1, 1), size: Some(4), ty: Float},
246     A8B8G8R8SnormPack32 => {vk: A8B8G8R8_SNORM_PACK32, bdim: (1, 1), size: Some(4), ty: Float},
247     A8B8G8R8UscaledPack32 => {vk: A8B8G8R8_USCALED_PACK32, bdim: (1, 1), size: Some(4), ty: Float},
248     A8B8G8R8SscaledPack32 => {vk: A8B8G8R8_SSCALED_PACK32, bdim: (1, 1), size: Some(4), ty: Float},
249     A8B8G8R8UintPack32 => {vk: A8B8G8R8_UINT_PACK32, bdim: (1, 1), size: Some(4), ty: Uint},
250     A8B8G8R8SintPack32 => {vk: A8B8G8R8_SINT_PACK32, bdim: (1, 1), size: Some(4), ty: Sint},
251     A8B8G8R8SrgbPack32 => {vk: A8B8G8R8_SRGB_PACK32, bdim: (1, 1), size: Some(4), ty: Float},
252     A2R10G10B10UnormPack32 => {vk: A2R10G10B10_UNORM_PACK32, bdim: (1, 1), size: Some(4), ty: Float},
253     A2R10G10B10SnormPack32 => {vk: A2R10G10B10_SNORM_PACK32, bdim: (1, 1), size: Some(4), ty: Float},
254     A2R10G10B10UscaledPack32 => {vk: A2R10G10B10_USCALED_PACK32, bdim: (1, 1), size: Some(4), ty: Float},
255     A2R10G10B10SscaledPack32 => {vk: A2R10G10B10_SSCALED_PACK32, bdim: (1, 1), size: Some(4), ty: Float},
256     A2R10G10B10UintPack32 => {vk: A2R10G10B10_UINT_PACK32, bdim: (1, 1), size: Some(4), ty: Uint},
257     A2R10G10B10SintPack32 => {vk: A2R10G10B10_SINT_PACK32, bdim: (1, 1), size: Some(4), ty: Sint},
258     A2B10G10R10UnormPack32 => {vk: A2B10G10R10_UNORM_PACK32, bdim: (1, 1), size: Some(4), ty: Float},
259     A2B10G10R10SnormPack32 => {vk: A2B10G10R10_SNORM_PACK32, bdim: (1, 1), size: Some(4), ty: Float},
260     A2B10G10R10UscaledPack32 => {vk: A2B10G10R10_USCALED_PACK32, bdim: (1, 1), size: Some(4), ty: Float},
261     A2B10G10R10SscaledPack32 => {vk: A2B10G10R10_SSCALED_PACK32, bdim: (1, 1), size: Some(4), ty: Float},
262     A2B10G10R10UintPack32 => {vk: A2B10G10R10_UINT_PACK32, bdim: (1, 1), size: Some(4), ty: Uint},
263     A2B10G10R10SintPack32 => {vk: A2B10G10R10_SINT_PACK32, bdim: (1, 1), size: Some(4), ty: Sint},
264     R16Unorm => {vk: R16_UNORM, bdim: (1, 1), size: Some(2), ty: Float},
265     R16Snorm => {vk: R16_SNORM, bdim: (1, 1), size: Some(2), ty: Float},
266     R16Uscaled => {vk: R16_USCALED, bdim: (1, 1), size: Some(2), ty: Float},
267     R16Sscaled => {vk: R16_SSCALED, bdim: (1, 1), size: Some(2), ty: Float},
268     R16Uint => {vk: R16_UINT, bdim: (1, 1), size: Some(2), ty: Uint},
269     R16Sint => {vk: R16_SINT, bdim: (1, 1), size: Some(2), ty: Sint},
270     R16Sfloat => {vk: R16_SFLOAT, bdim: (1, 1), size: Some(2), ty: Float},
271     R16G16Unorm => {vk: R16G16_UNORM, bdim: (1, 1), size: Some(4), ty: Float},
272     R16G16Snorm => {vk: R16G16_SNORM, bdim: (1, 1), size: Some(4), ty: Float},
273     R16G16Uscaled => {vk: R16G16_USCALED, bdim: (1, 1), size: Some(4), ty: Float},
274     R16G16Sscaled => {vk: R16G16_SSCALED, bdim: (1, 1), size: Some(4), ty: Float},
275     R16G16Uint => {vk: R16G16_UINT, bdim: (1, 1), size: Some(4), ty: Uint},
276     R16G16Sint => {vk: R16G16_SINT, bdim: (1, 1), size: Some(4), ty: Sint},
277     R16G16Sfloat => {vk: R16G16_SFLOAT, bdim: (1, 1), size: Some(4), ty: Float},
278     R16G16B16Unorm => {vk: R16G16B16_UNORM, bdim: (1, 1), size: Some(6), ty: Float},
279     R16G16B16Snorm => {vk: R16G16B16_SNORM, bdim: (1, 1), size: Some(6), ty: Float},
280     R16G16B16Uscaled => {vk: R16G16B16_USCALED, bdim: (1, 1), size: Some(6), ty: Float},
281     R16G16B16Sscaled => {vk: R16G16B16_SSCALED, bdim: (1, 1), size: Some(6), ty: Float},
282     R16G16B16Uint => {vk: R16G16B16_UINT, bdim: (1, 1), size: Some(6), ty: Uint},
283     R16G16B16Sint => {vk: R16G16B16_SINT, bdim: (1, 1), size: Some(6), ty: Sint},
284     R16G16B16Sfloat => {vk: R16G16B16_SFLOAT, bdim: (1, 1), size: Some(6), ty: Float},
285     R16G16B16A16Unorm => {vk: R16G16B16A16_UNORM, bdim: (1, 1), size: Some(8), ty: Float},
286     R16G16B16A16Snorm => {vk: R16G16B16A16_SNORM, bdim: (1, 1), size: Some(8), ty: Float},
287     R16G16B16A16Uscaled => {vk: R16G16B16A16_USCALED, bdim: (1, 1), size: Some(8), ty: Float},
288     R16G16B16A16Sscaled => {vk: R16G16B16A16_SSCALED, bdim: (1, 1), size: Some(8), ty: Float},
289     R16G16B16A16Uint => {vk: R16G16B16A16_UINT, bdim: (1, 1), size: Some(8), ty: Uint},
290     R16G16B16A16Sint => {vk: R16G16B16A16_SINT, bdim: (1, 1), size: Some(8), ty: Sint},
291     R16G16B16A16Sfloat => {vk: R16G16B16A16_SFLOAT, bdim: (1, 1), size: Some(8), ty: Float},
292     R32Uint => {vk: R32_UINT, bdim: (1, 1), size: Some(4), ty: Uint},
293     R32Sint => {vk: R32_SINT, bdim: (1, 1), size: Some(4), ty: Sint},
294     R32Sfloat => {vk: R32_SFLOAT, bdim: (1, 1), size: Some(4), ty: Float},
295     R32G32Uint => {vk: R32G32_UINT, bdim: (1, 1), size: Some(8), ty: Uint},
296     R32G32Sint => {vk: R32G32_SINT, bdim: (1, 1), size: Some(8), ty: Sint},
297     R32G32Sfloat => {vk: R32G32_SFLOAT, bdim: (1, 1), size: Some(8), ty: Float},
298     R32G32B32Uint => {vk: R32G32B32_UINT, bdim: (1, 1), size: Some(12), ty: Uint},
299     R32G32B32Sint => {vk: R32G32B32_SINT, bdim: (1, 1), size: Some(12), ty: Sint},
300     R32G32B32Sfloat => {vk: R32G32B32_SFLOAT, bdim: (1, 1), size: Some(12), ty: Float},
301     R32G32B32A32Uint => {vk: R32G32B32A32_UINT, bdim: (1, 1), size: Some(16), ty: Uint},
302     R32G32B32A32Sint => {vk: R32G32B32A32_SINT, bdim: (1, 1), size: Some(16), ty: Sint},
303     R32G32B32A32Sfloat => {vk: R32G32B32A32_SFLOAT, bdim: (1, 1), size: Some(16), ty: Float},
304     R64Uint => {vk: R64_UINT, bdim: (1, 1), size: Some(8), ty: Uint},
305     R64Sint => {vk: R64_SINT, bdim: (1, 1), size: Some(8), ty: Sint},
306     R64Sfloat => {vk: R64_SFLOAT, bdim: (1, 1), size: Some(8), ty: Float},
307     R64G64Uint => {vk: R64G64_UINT, bdim: (1, 1), size: Some(16), ty: Uint},
308     R64G64Sint => {vk: R64G64_SINT, bdim: (1, 1), size: Some(16), ty: Sint},
309     R64G64Sfloat => {vk: R64G64_SFLOAT, bdim: (1, 1), size: Some(16), ty: Float},
310     R64G64B64Uint => {vk: R64G64B64_UINT, bdim: (1, 1), size: Some(24), ty: Uint},
311     R64G64B64Sint => {vk: R64G64B64_SINT, bdim: (1, 1), size: Some(24), ty: Sint},
312     R64G64B64Sfloat => {vk: R64G64B64_SFLOAT, bdim: (1, 1), size: Some(24), ty: Float},
313     R64G64B64A64Uint => {vk: R64G64B64A64_UINT, bdim: (1, 1), size: Some(32), ty: Uint},
314     R64G64B64A64Sint => {vk: R64G64B64A64_SINT, bdim: (1, 1), size: Some(32), ty: Sint},
315     R64G64B64A64Sfloat => {vk: R64G64B64A64_SFLOAT, bdim: (1, 1), size: Some(32), ty: Float},
316     B10G11R11UfloatPack32 => {vk: B10G11R11_UFLOAT_PACK32, bdim: (1, 1), size: Some(4), ty: Float},
317     E5B9G9R9UfloatPack32 => {vk: E5B9G9R9_UFLOAT_PACK32, bdim: (1, 1), size: Some(4), ty: Float},
318     D16Unorm => {vk: D16_UNORM, bdim: (1, 1), size: Some(2), ty: Depth},
319     X8_D24UnormPack32 => {vk: X8_D24_UNORM_PACK32, bdim: (1, 1), size: Some(4), ty: Depth},
320     D32Sfloat => {vk: D32_SFLOAT, bdim: (1, 1), size: Some(4), ty: Depth},
321     S8Uint => {vk: S8_UINT, bdim: (1, 1), size: Some(1), ty: Stencil},
322     D16Unorm_S8Uint => {vk: D16_UNORM_S8_UINT, bdim: (1, 1), size: None, ty: DepthStencil},
323     D24Unorm_S8Uint => {vk: D24_UNORM_S8_UINT, bdim: (1, 1), size: None, ty: DepthStencil},
324     D32Sfloat_S8Uint => {vk: D32_SFLOAT_S8_UINT, bdim: (1, 1), size: None, ty: DepthStencil},
325     BC1_RGBUnormBlock => {vk: BC1_RGB_UNORM_BLOCK, bdim: (4, 4), size: Some(8), ty: Compressed},
326     BC1_RGBSrgbBlock => {vk: BC1_RGB_SRGB_BLOCK, bdim: (4, 4), size: Some(8), ty: Compressed},
327     BC1_RGBAUnormBlock => {vk: BC1_RGBA_UNORM_BLOCK, bdim: (4, 4), size: Some(8), ty: Compressed},
328     BC1_RGBASrgbBlock => {vk: BC1_RGBA_SRGB_BLOCK, bdim: (4, 4), size: Some(8), ty: Compressed},
329     BC2UnormBlock => {vk: BC2_UNORM_BLOCK, bdim: (4, 4), size: Some(16), ty: Compressed},
330     BC2SrgbBlock => {vk: BC2_SRGB_BLOCK, bdim: (4, 4), size: Some(16), ty: Compressed},
331     BC3UnormBlock => {vk: BC3_UNORM_BLOCK, bdim: (4, 4), size: Some(16), ty: Compressed},
332     BC3SrgbBlock => {vk: BC3_SRGB_BLOCK, bdim: (4, 4), size: Some(16), ty: Compressed},
333     BC4UnormBlock => {vk: BC4_UNORM_BLOCK, bdim: (4, 4), size: Some(8), ty: Compressed},
334     BC4SnormBlock => {vk: BC4_SNORM_BLOCK, bdim: (4, 4), size: Some(8), ty: Compressed},
335     BC5UnormBlock => {vk: BC5_UNORM_BLOCK, bdim: (4, 4), size: Some(16), ty: Compressed},
336     BC5SnormBlock => {vk: BC5_SNORM_BLOCK, bdim: (4, 4), size: Some(16), ty: Compressed},
337     BC6HUfloatBlock => {vk: BC6H_UFLOAT_BLOCK, bdim: (4, 4), size: Some(16), ty: Compressed},
338     BC6HSfloatBlock => {vk: BC6H_SFLOAT_BLOCK, bdim: (4, 4), size: Some(16), ty: Compressed},
339     BC7UnormBlock => {vk: BC7_UNORM_BLOCK, bdim: (4, 4), size: Some(16), ty: Compressed},
340     BC7SrgbBlock => {vk: BC7_SRGB_BLOCK, bdim: (4, 4), size: Some(16), ty: Compressed},
341     ETC2_R8G8B8UnormBlock => {vk: ETC2_R8G8B8_UNORM_BLOCK, bdim: (4, 4), size: Some(8), ty: Compressed},
342     ETC2_R8G8B8SrgbBlock => {vk: ETC2_R8G8B8_SRGB_BLOCK, bdim: (4, 4), size: Some(8), ty: Compressed},
343     ETC2_R8G8B8A1UnormBlock => {vk: ETC2_R8G8B8A1_UNORM_BLOCK, bdim: (4, 4), size: Some(8), ty: Compressed},
344     ETC2_R8G8B8A1SrgbBlock => {vk: ETC2_R8G8B8A1_SRGB_BLOCK, bdim: (4, 4), size: Some(8), ty: Compressed},
345     ETC2_R8G8B8A8UnormBlock => {vk: ETC2_R8G8B8A8_UNORM_BLOCK, bdim: (4, 4), size: Some(16), ty: Compressed},
346     ETC2_R8G8B8A8SrgbBlock => {vk: ETC2_R8G8B8A8_SRGB_BLOCK, bdim: (4, 4), size: Some(16), ty: Compressed},
347     EAC_R11UnormBlock => {vk: EAC_R11_UNORM_BLOCK, bdim: (4, 4), size: Some(8), ty: Compressed},
348     EAC_R11SnormBlock => {vk: EAC_R11_SNORM_BLOCK, bdim: (4, 4), size: Some(8), ty: Compressed},
349     EAC_R11G11UnormBlock => {vk: EAC_R11G11_UNORM_BLOCK, bdim: (4, 4), size: Some(16), ty: Compressed},
350     EAC_R11G11SnormBlock => {vk: EAC_R11G11_SNORM_BLOCK, bdim: (4, 4), size: Some(16), ty: Compressed},
351     ASTC_4x4UnormBlock => {vk: ASTC_4X4_UNORM_BLOCK, bdim: (4, 4), size: Some(16), ty: Compressed},
352     ASTC_4x4SrgbBlock => {vk: ASTC_4X4_SRGB_BLOCK, bdim: (4, 4), size: Some(16), ty: Compressed},
353     ASTC_5x4UnormBlock => {vk: ASTC_5X4_UNORM_BLOCK, bdim: (5, 4), size: Some(16), ty: Compressed},
354     ASTC_5x4SrgbBlock => {vk: ASTC_5X4_SRGB_BLOCK, bdim: (5, 4), size: Some(16), ty: Compressed},
355     ASTC_5x5UnormBlock => {vk: ASTC_5X5_UNORM_BLOCK, bdim: (5, 5), size: Some(16), ty: Compressed},
356     ASTC_5x5SrgbBlock => {vk: ASTC_5X5_SRGB_BLOCK, bdim: (5, 5), size: Some(16), ty: Compressed},
357     ASTC_6x5UnormBlock => {vk: ASTC_6X5_UNORM_BLOCK, bdim: (6, 5), size: Some(16), ty: Compressed},
358     ASTC_6x5SrgbBlock => {vk: ASTC_6X5_SRGB_BLOCK, bdim: (6, 5), size: Some(16), ty: Compressed},
359     ASTC_6x6UnormBlock => {vk: ASTC_6X6_UNORM_BLOCK, bdim: (6, 6), size: Some(16), ty: Compressed},
360     ASTC_6x6SrgbBlock => {vk: ASTC_6X6_SRGB_BLOCK, bdim: (6, 6), size: Some(16), ty: Compressed},
361     ASTC_8x5UnormBlock => {vk: ASTC_8X5_UNORM_BLOCK, bdim: (8, 5), size: Some(16), ty: Compressed},
362     ASTC_8x5SrgbBlock => {vk: ASTC_8X5_SRGB_BLOCK, bdim: (8, 5), size: Some(16), ty: Compressed},
363     ASTC_8x6UnormBlock => {vk: ASTC_8X6_UNORM_BLOCK, bdim: (8, 6), size: Some(16), ty: Compressed},
364     ASTC_8x6SrgbBlock => {vk: ASTC_8X6_SRGB_BLOCK, bdim: (8, 6), size: Some(16), ty: Compressed},
365     ASTC_8x8UnormBlock => {vk: ASTC_8X8_UNORM_BLOCK, bdim: (8, 8), size: Some(16), ty: Compressed},
366     ASTC_8x8SrgbBlock => {vk: ASTC_8X8_SRGB_BLOCK, bdim: (8, 8), size: Some(16), ty: Compressed},
367     ASTC_10x5UnormBlock => {vk: ASTC_10X5_UNORM_BLOCK, bdim: (10, 5), size: Some(16), ty: Compressed},
368     ASTC_10x5SrgbBlock => {vk: ASTC_10X5_SRGB_BLOCK, bdim: (10, 5), size: Some(16), ty: Compressed},
369     ASTC_10x6UnormBlock => {vk: ASTC_10X6_UNORM_BLOCK, bdim: (10, 6), size: Some(16), ty: Compressed},
370     ASTC_10x6SrgbBlock => {vk: ASTC_10X6_SRGB_BLOCK, bdim: (10, 6), size: Some(16), ty: Compressed},
371     ASTC_10x8UnormBlock => {vk: ASTC_10X8_UNORM_BLOCK, bdim: (10, 8), size: Some(16), ty: Compressed},
372     ASTC_10x8SrgbBlock => {vk: ASTC_10X8_SRGB_BLOCK, bdim: (10, 8), size: Some(16), ty: Compressed},
373     ASTC_10x10UnormBlock => {vk: ASTC_10X10_UNORM_BLOCK, bdim: (10, 10), size: Some(16), ty: Compressed},
374     ASTC_10x10SrgbBlock => {vk: ASTC_10X10_SRGB_BLOCK, bdim: (10, 10), size: Some(16), ty: Compressed},
375     ASTC_12x10UnormBlock => {vk: ASTC_12X10_UNORM_BLOCK, bdim: (12, 10), size: Some(16), ty: Compressed},
376     ASTC_12x10SrgbBlock => {vk: ASTC_12X10_SRGB_BLOCK, bdim: (12, 10), size: Some(16), ty: Compressed},
377     ASTC_12x12UnormBlock => {vk: ASTC_12X12_UNORM_BLOCK, bdim: (12, 12), size: Some(16), ty: Compressed},
378     ASTC_12x12SrgbBlock => {vk: ASTC_12X12_SRGB_BLOCK, bdim: (12, 12), size: Some(16), ty: Compressed},
379     G8B8R8_3PLANE420Unorm => {vk: G8_B8_R8_3PLANE_420_UNORM, bdim: (1, 1), size: None, ty: Ycbcr, planes: 3},
380     G8B8R8_2PLANE420Unorm => {vk: G8_B8R8_2PLANE_420_UNORM, bdim: (1, 1), size: None, ty: Ycbcr, planes: 2},
381 }
382 
383 impl Format {
384     /// Returns the aspects that images of this format have.
385     #[inline]
aspects(&self) -> ImageAspects386     pub const fn aspects(&self) -> ImageAspects {
387         let ty = self.ty();
388         let planes = self.planes();
389         ImageAspects {
390             color: matches!(
391                 ty,
392                 FormatTy::Float | FormatTy::Uint | FormatTy::Sint | FormatTy::Compressed
393             ),
394             depth: matches!(ty, FormatTy::Depth | FormatTy::DepthStencil),
395             stencil: matches!(ty, FormatTy::Stencil | FormatTy::DepthStencil),
396             plane0: planes >= 1,
397             plane1: planes >= 2,
398             plane2: planes >= 3,
399             ..ImageAspects::none()
400         }
401     }
402 
403     /// Retrieves the properties of a format when used by a certain device.
404     #[inline]
properties(&self, physical_device: PhysicalDevice) -> FormatProperties405     pub fn properties(&self, physical_device: PhysicalDevice) -> FormatProperties {
406         let vk_properties = unsafe {
407             let fns_i = physical_device.instance().fns();
408             let mut output = MaybeUninit::uninit();
409             fns_i.v1_0.get_physical_device_format_properties(
410                 physical_device.internal_object(),
411                 (*self).into(),
412                 output.as_mut_ptr(),
413             );
414             output.assume_init()
415         };
416 
417         FormatProperties {
418             linear_tiling_features: vk_properties.linear_tiling_features.into(),
419             optimal_tiling_features: vk_properties.optimal_tiling_features.into(),
420             buffer_features: vk_properties.buffer_features.into(),
421         }
422     }
423 
424     #[inline]
decode_clear_value(&self, value: ClearValue) -> ClearValue425     pub fn decode_clear_value(&self, value: ClearValue) -> ClearValue {
426         match (self.ty(), value) {
427             (FormatTy::Float, f @ ClearValue::Float(_)) => f,
428             (FormatTy::Compressed, f @ ClearValue::Float(_)) => f,
429             (FormatTy::Sint, f @ ClearValue::Int(_)) => f,
430             (FormatTy::Uint, f @ ClearValue::Uint(_)) => f,
431             (FormatTy::Depth, f @ ClearValue::Depth(_)) => f,
432             (FormatTy::Stencil, f @ ClearValue::Stencil(_)) => f,
433             (FormatTy::DepthStencil, f @ ClearValue::DepthStencil(_)) => f,
434             _ => panic!("Wrong clear value"),
435         }
436     }
437 }
438 
439 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
440 pub enum FormatTy {
441     Float,
442     Uint,
443     Sint,
444     Depth,
445     Stencil,
446     DepthStencil,
447     Compressed,
448     Ycbcr,
449 }
450 
451 /// Trait for Rust types that can represent a pixel in an image.
452 pub unsafe trait Pixel {
453     /// Returns an error if `Self` cannot be used as a source of pixels for `format`.
ensure_accepts(format: Format) -> Result<(), IncompatiblePixelsType>454     fn ensure_accepts(format: Format) -> Result<(), IncompatiblePixelsType>;
455 
456     /// The number of `Self`s which make up a single pixel.
457     ///
458     /// # Panics
459     ///
460     /// May panic if `ensure_accepts` would not return `Ok(())`.
rate(format: Format) -> u32461     fn rate(format: Format) -> u32;
462 }
463 
464 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
465 pub struct IncompatiblePixelsType;
466 
467 impl error::Error for IncompatiblePixelsType {}
468 
469 impl fmt::Display for IncompatiblePixelsType {
470     #[inline]
fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error>471     fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
472         write!(
473             fmt,
474             "{}",
475             "supplied pixels' type is incompatible with this format"
476         )
477     }
478 }
479 
480 macro_rules! impl_pixel {
481     {$($ty:ty;)+} => {
482         $(impl_pixel!(inner $ty);)*
483         $(impl_pixel!(inner [$ty; 1]);)*
484         $(impl_pixel!(inner [$ty; 2]);)*
485         $(impl_pixel!(inner [$ty; 3]);)*
486         $(impl_pixel!(inner [$ty; 4]);)*
487         $(impl_pixel!(inner ($ty,));)*
488         $(impl_pixel!(inner ($ty, $ty));)*
489         $(impl_pixel!(inner ($ty, $ty, $ty));)*
490         $(impl_pixel!(inner ($ty, $ty, $ty, $ty));)*
491     };
492     (inner $ty:ty) => {
493         unsafe impl Pixel for $ty {
494             fn ensure_accepts(format: Format) -> Result<(), IncompatiblePixelsType> {
495                 // TODO: Be more strict: accept only if the format has a matching AcceptsPixels impl.
496                 if format.size().map_or(false, |x| x % mem::size_of::<$ty>() as DeviceSize == 0) {
497                     Ok(())
498                 } else {
499                     Err(IncompatiblePixelsType)
500                 }
501             }
502 
503             fn rate(format: Format) -> u32 {
504                 (format.size().expect("this format cannot accept pixels") / mem::size_of::<$ty>() as DeviceSize) as u32
505             }
506         }
507     }
508 }
509 
510 impl_pixel! {
511     u8; i8; u16; i16; u32; i32; u64; i64; f16; f32; f64;
512 }
513 
514 /// Describes a uniform value that will be used to fill an image.
515 // TODO: should have the same layout as `vk::ClearValue` for performance
516 #[derive(Debug, Copy, Clone, PartialEq)]
517 pub enum ClearValue {
518     /// Entry for attachments that aren't cleared.
519     None,
520     /// Value for floating-point attachments, including `Unorm`, `Snorm`, `Sfloat`.
521     Float([f32; 4]),
522     /// Value for integer attachments, including `Int`.
523     Int([i32; 4]),
524     /// Value for unsigned integer attachments, including `Uint`.
525     Uint([u32; 4]),
526     /// Value for depth attachments.
527     Depth(f32),
528     /// Value for stencil attachments.
529     Stencil(u32),
530     /// Value for depth and stencil attachments.
531     DepthStencil((f32, u32)),
532 }
533 
534 // TODO: remove all these From implementations once they are no longer needed
535 
536 impl From<[f32; 1]> for ClearValue {
537     #[inline]
from(val: [f32; 1]) -> ClearValue538     fn from(val: [f32; 1]) -> ClearValue {
539         ClearValue::Float([val[0], 0.0, 0.0, 1.0])
540     }
541 }
542 
543 impl From<[f32; 2]> for ClearValue {
544     #[inline]
from(val: [f32; 2]) -> ClearValue545     fn from(val: [f32; 2]) -> ClearValue {
546         ClearValue::Float([val[0], val[1], 0.0, 1.0])
547     }
548 }
549 
550 impl From<[f32; 3]> for ClearValue {
551     #[inline]
from(val: [f32; 3]) -> ClearValue552     fn from(val: [f32; 3]) -> ClearValue {
553         ClearValue::Float([val[0], val[1], val[2], 1.0])
554     }
555 }
556 
557 impl From<[f32; 4]> for ClearValue {
558     #[inline]
from(val: [f32; 4]) -> ClearValue559     fn from(val: [f32; 4]) -> ClearValue {
560         ClearValue::Float(val)
561     }
562 }
563 
564 impl From<[u32; 1]> for ClearValue {
565     #[inline]
from(val: [u32; 1]) -> ClearValue566     fn from(val: [u32; 1]) -> ClearValue {
567         ClearValue::Uint([val[0], 0, 0, 0]) // TODO: is alpha value 0 correct?
568     }
569 }
570 
571 impl From<[u32; 2]> for ClearValue {
572     #[inline]
from(val: [u32; 2]) -> ClearValue573     fn from(val: [u32; 2]) -> ClearValue {
574         ClearValue::Uint([val[0], val[1], 0, 0]) // TODO: is alpha value 0 correct?
575     }
576 }
577 
578 impl From<[u32; 3]> for ClearValue {
579     #[inline]
from(val: [u32; 3]) -> ClearValue580     fn from(val: [u32; 3]) -> ClearValue {
581         ClearValue::Uint([val[0], val[1], val[2], 0]) // TODO: is alpha value 0 correct?
582     }
583 }
584 
585 impl From<[u32; 4]> for ClearValue {
586     #[inline]
from(val: [u32; 4]) -> ClearValue587     fn from(val: [u32; 4]) -> ClearValue {
588         ClearValue::Uint(val)
589     }
590 }
591 
592 impl From<[i32; 1]> for ClearValue {
593     #[inline]
from(val: [i32; 1]) -> ClearValue594     fn from(val: [i32; 1]) -> ClearValue {
595         ClearValue::Int([val[0], 0, 0, 0]) // TODO: is alpha value 0 correct?
596     }
597 }
598 
599 impl From<[i32; 2]> for ClearValue {
600     #[inline]
from(val: [i32; 2]) -> ClearValue601     fn from(val: [i32; 2]) -> ClearValue {
602         ClearValue::Int([val[0], val[1], 0, 0]) // TODO: is alpha value 0 correct?
603     }
604 }
605 
606 impl From<[i32; 3]> for ClearValue {
607     #[inline]
from(val: [i32; 3]) -> ClearValue608     fn from(val: [i32; 3]) -> ClearValue {
609         ClearValue::Int([val[0], val[1], val[2], 0]) // TODO: is alpha value 0 correct?
610     }
611 }
612 
613 impl From<[i32; 4]> for ClearValue {
614     #[inline]
from(val: [i32; 4]) -> ClearValue615     fn from(val: [i32; 4]) -> ClearValue {
616         ClearValue::Int(val)
617     }
618 }
619 
620 impl From<f32> for ClearValue {
621     #[inline]
from(val: f32) -> ClearValue622     fn from(val: f32) -> ClearValue {
623         ClearValue::Depth(val)
624     }
625 }
626 
627 impl From<u32> for ClearValue {
628     #[inline]
from(val: u32) -> ClearValue629     fn from(val: u32) -> ClearValue {
630         ClearValue::Stencil(val)
631     }
632 }
633 
634 impl From<(f32, u32)> for ClearValue {
635     #[inline]
from(val: (f32, u32)) -> ClearValue636     fn from(val: (f32, u32)) -> ClearValue {
637         ClearValue::DepthStencil(val)
638     }
639 }
640 
641 // TODO: remove once no longer needed
642 pub unsafe trait ClearValuesTuple {
643     type Iter: Iterator<Item = ClearValue>;
iter(self) -> Self::Iter644     fn iter(self) -> Self::Iter;
645 }
646 
647 macro_rules! impl_clear_values_tuple {
648     ($first:ident $($others:ident)+) => (
649         #[allow(non_snake_case)]
650         unsafe impl<$first $(, $others)*> ClearValuesTuple for ($first, $($others,)+)
651             where $first: Into<ClearValue> $(, $others: Into<ClearValue>)*
652         {
653             type Iter = VecIntoIter<ClearValue>;
654             #[inline]
655             fn iter(self) -> VecIntoIter<ClearValue> {
656                 let ($first, $($others,)+) = self;
657                 vec![
658                     $first.into() $(, $others.into())+
659                 ].into_iter()
660             }
661         }
662 
663         impl_clear_values_tuple!($($others)*);
664     );
665 
666     ($first:ident) => (
667         unsafe impl<$first> ClearValuesTuple for ($first,)
668             where $first: Into<ClearValue>
669         {
670             type Iter = VecIntoIter<ClearValue>;
671             #[inline]
672             fn iter(self) -> VecIntoIter<ClearValue> {
673                 vec![self.0.into()].into_iter()
674             }
675         }
676     );
677 }
678 
679 impl_clear_values_tuple!(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z);
680 
681 /// The properties of an image format that are supported by a physical device.
682 #[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
683 pub struct FormatProperties {
684     /// Features available for images with linear tiling.
685     pub linear_tiling_features: FormatFeatures,
686 
687     /// Features available for images with optimal tiling.
688     pub optimal_tiling_features: FormatFeatures,
689 
690     /// Features available for buffers.
691     pub buffer_features: FormatFeatures,
692 }
693 
694 /// The features supported by images with a particular format.
695 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
696 #[allow(missing_docs)]
697 pub struct FormatFeatures {
698     pub sampled_image: bool,
699     pub storage_image: bool,
700     pub storage_image_atomic: bool,
701     pub uniform_texel_buffer: bool,
702     pub storage_texel_buffer: bool,
703     pub storage_texel_buffer_atomic: bool,
704     pub vertex_buffer: bool,
705     pub color_attachment: bool,
706     pub color_attachment_blend: bool,
707     pub depth_stencil_attachment: bool,
708     pub blit_src: bool,
709     pub blit_dst: bool,
710     pub sampled_image_filter_linear: bool,
711     pub transfer_src: bool,
712     pub transfer_dst: bool,
713     pub midpoint_chroma_samples: bool,
714     pub sampled_image_ycbcr_conversion_linear_filter: bool,
715     pub sampled_image_ycbcr_conversion_separate_reconstruction_filter: bool,
716     pub sampled_image_ycbcr_conversion_chroma_reconstruction_explicit: bool,
717     pub sampled_image_ycbcr_conversion_chroma_reconstruction_explicit_forceable: bool,
718     pub disjoint: bool,
719     pub cosited_chroma_samples: bool,
720     pub sampled_image_filter_minmax: bool,
721     pub img_sampled_image_filter_cubic: bool,
722     pub khr_acceleration_structure_vertex_buffer: bool,
723     pub ext_fragment_density_map: bool,
724 }
725 
726 impl From<ash::vk::FormatFeatureFlags> for FormatFeatures {
727     #[inline]
728     #[rustfmt::skip]
from(val: ash::vk::FormatFeatureFlags) -> FormatFeatures729     fn from(val: ash::vk::FormatFeatureFlags) -> FormatFeatures {
730         FormatFeatures {
731             sampled_image: !(val & ash::vk::FormatFeatureFlags::SAMPLED_IMAGE).is_empty(),
732             storage_image: !(val & ash::vk::FormatFeatureFlags::STORAGE_IMAGE).is_empty(),
733             storage_image_atomic: !(val & ash::vk::FormatFeatureFlags::STORAGE_IMAGE_ATOMIC).is_empty(),
734             uniform_texel_buffer: !(val & ash::vk::FormatFeatureFlags::UNIFORM_TEXEL_BUFFER).is_empty(),
735             storage_texel_buffer: !(val & ash::vk::FormatFeatureFlags::STORAGE_TEXEL_BUFFER).is_empty(),
736             storage_texel_buffer_atomic: !(val & ash::vk::FormatFeatureFlags::STORAGE_TEXEL_BUFFER_ATOMIC).is_empty(),
737             vertex_buffer: !(val & ash::vk::FormatFeatureFlags::VERTEX_BUFFER).is_empty(),
738             color_attachment: !(val & ash::vk::FormatFeatureFlags::COLOR_ATTACHMENT).is_empty(),
739             color_attachment_blend: !(val & ash::vk::FormatFeatureFlags::COLOR_ATTACHMENT_BLEND).is_empty(),
740             depth_stencil_attachment: !(val & ash::vk::FormatFeatureFlags::DEPTH_STENCIL_ATTACHMENT).is_empty(),
741             blit_src: !(val & ash::vk::FormatFeatureFlags::BLIT_SRC).is_empty(),
742             blit_dst: !(val & ash::vk::FormatFeatureFlags::BLIT_DST).is_empty(),
743             sampled_image_filter_linear: !(val & ash::vk::FormatFeatureFlags::SAMPLED_IMAGE_FILTER_LINEAR).is_empty(),
744             transfer_src: !(val & ash::vk::FormatFeatureFlags::TRANSFER_SRC).is_empty(),
745             transfer_dst: !(val & ash::vk::FormatFeatureFlags::TRANSFER_DST).is_empty(),
746             midpoint_chroma_samples: !(val & ash::vk::FormatFeatureFlags::MIDPOINT_CHROMA_SAMPLES).is_empty(),
747             sampled_image_ycbcr_conversion_linear_filter: !(val & ash::vk::FormatFeatureFlags::SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER).is_empty(),
748             sampled_image_ycbcr_conversion_separate_reconstruction_filter: !(val & ash::vk::FormatFeatureFlags::SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER).is_empty(),
749             sampled_image_ycbcr_conversion_chroma_reconstruction_explicit: !(val & ash::vk::FormatFeatureFlags::SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT).is_empty(),
750             sampled_image_ycbcr_conversion_chroma_reconstruction_explicit_forceable: !(val & ash::vk::FormatFeatureFlags::SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE).is_empty(),
751             disjoint: !(val & ash::vk::FormatFeatureFlags::DISJOINT).is_empty(),
752             cosited_chroma_samples: !(val & ash::vk::FormatFeatureFlags::COSITED_CHROMA_SAMPLES).is_empty(),
753             sampled_image_filter_minmax: !(val & ash::vk::FormatFeatureFlags::SAMPLED_IMAGE_FILTER_MINMAX).is_empty(),
754             img_sampled_image_filter_cubic: !(val & ash::vk::FormatFeatureFlags::SAMPLED_IMAGE_FILTER_CUBIC_IMG).is_empty(),
755             khr_acceleration_structure_vertex_buffer: !(val & ash::vk::FormatFeatureFlags::ACCELERATION_STRUCTURE_VERTEX_BUFFER_KHR).is_empty(),
756             ext_fragment_density_map: !(val & ash::vk::FormatFeatureFlags::FRAGMENT_DENSITY_MAP_EXT).is_empty(),
757         }
758     }
759 }
760