Skip to main content

wgpu_types/texture/
format.rs

1use alloc::vec::Vec;
2
3use crate::{Features, TextureAspect, TextureSampleType, TextureUsages};
4
5#[cfg(any(feature = "serde", test))]
6use serde::{Deserialize, Serialize};
7
8/// ASTC block dimensions
9#[repr(C)]
10#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
11#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
12pub enum AstcBlock {
13    /// 4x4 block compressed texture. 16 bytes per block (8 bit/px).
14    B4x4,
15    /// 5x4 block compressed texture. 16 bytes per block (6.4 bit/px).
16    B5x4,
17    /// 5x5 block compressed texture. 16 bytes per block (5.12 bit/px).
18    B5x5,
19    /// 6x5 block compressed texture. 16 bytes per block (4.27 bit/px).
20    B6x5,
21    /// 6x6 block compressed texture. 16 bytes per block (3.56 bit/px).
22    B6x6,
23    /// 8x5 block compressed texture. 16 bytes per block (3.2 bit/px).
24    B8x5,
25    /// 8x6 block compressed texture. 16 bytes per block (2.67 bit/px).
26    B8x6,
27    /// 8x8 block compressed texture. 16 bytes per block (2 bit/px).
28    B8x8,
29    /// 10x5 block compressed texture. 16 bytes per block (2.56 bit/px).
30    B10x5,
31    /// 10x6 block compressed texture. 16 bytes per block (2.13 bit/px).
32    B10x6,
33    /// 10x8 block compressed texture. 16 bytes per block (1.6 bit/px).
34    B10x8,
35    /// 10x10 block compressed texture. 16 bytes per block (1.28 bit/px).
36    B10x10,
37    /// 12x10 block compressed texture. 16 bytes per block (1.07 bit/px).
38    B12x10,
39    /// 12x12 block compressed texture. 16 bytes per block (0.89 bit/px).
40    B12x12,
41}
42
43/// ASTC RGBA channel
44#[repr(C)]
45#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
46#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
47pub enum AstcChannel {
48    /// 8 bit integer RGBA, [0, 255] converted to/from linear-color float [0, 1] in shader.
49    ///
50    /// [`Features::TEXTURE_COMPRESSION_ASTC`] must be enabled to use this channel.
51    Unorm,
52    /// 8 bit integer RGBA, Srgb-color [0, 255] converted to/from linear-color float [0, 1] in shader.
53    ///
54    /// [`Features::TEXTURE_COMPRESSION_ASTC`] must be enabled to use this channel.
55    UnormSrgb,
56    /// floating-point RGBA, linear-color float can be outside of the [0, 1] range.
57    ///
58    /// [`Features::TEXTURE_COMPRESSION_ASTC_HDR`] must be enabled to use this channel.
59    Hdr,
60}
61
62bitflags::bitflags! {
63    /// Represents the different format channels of a texture format.
64    #[repr(transparent)]
65    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
66    #[cfg_attr(feature = "serde", serde(transparent))]
67    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
68    pub struct TextureChannel: u16 {
69        /// Texture format contains a `red` channel.
70        const RED = 1 << 0;
71        /// Texture format contains a `green` channel.
72        const GREEN = 1 << 1;
73        /// Texture format contains a `blue` channel.
74        const BLUE = 1 << 2;
75        /// Texture format contains an `alpha` channel.
76        const ALPHA = 1 << 3;
77        /// Texture format contains a `stencil` channel.
78        const STENCIL = 1 << 4;
79        /// Texture format contains a `depth` channel.
80        const DEPTH = 1 << 5;
81        /// Texture format contains a `luminance` channel.
82        const LUMINANCE = 1 << 6;
83        /// Texture format contains a `blue-difference` channel.
84        const CHROMINANCE_BLUE = 1 << 7;
85        /// Texture format contains a `red-difference` channel.
86        const CHROMINANCE_RED = 1 << 8;
87
88        /// Texture format contains channels for `red` and `green`.
89        const RG = Self::RED.bits() | Self::GREEN.bits();
90        /// Texture format contains channels for `red`, `green` and `blue`.
91        const RGB = Self::RG.bits() | Self::BLUE.bits();
92        /// Texture format contains channels for `red`, `green`, `blue` and `alpha`.
93        const RGBA = Self::RGB.bits() | Self::ALPHA.bits();
94        /// Texture format contains channels for `depth` and `stencil`.
95        const DEPTH_STENCIL =  Self::DEPTH.bits() | Self::STENCIL.bits();
96        /// Texture format contains a `luminance` (`Y`), `blue-difference` (`Cb`) and `red-difference` (`Cr`) channel.
97        const LUMINANCE_CHROMINANCE = Self::LUMINANCE.bits() | Self::CHROMINANCE_BLUE.bits() | Self::CHROMINANCE_RED.bits();
98    }
99}
100
101/// Format in which a texture’s texels are stored in GPU memory.
102///
103/// Certain formats additionally specify a conversion.
104/// When these formats are used in a shader, the conversion automatically takes place when loading
105/// from or storing to the texture.
106///
107/// * `Unorm` formats linearly scale the integer range of the storage format to a floating-point
108///   range of 0 to 1, inclusive.
109/// * `Snorm` formats linearly scale the integer range of the storage format to a floating-point
110///   range of &minus;1 to 1, inclusive, except that the most negative value
111///   (&minus;128 for 8-bit, &minus;32768 for 16-bit) is excluded; on conversion,
112///   it is treated as identical to the second most negative
113///   (&minus;127 for 8-bit, &minus;32767 for 16-bit),
114///   so that the positive and negative ranges are symmetric.
115/// * `UnormSrgb` formats apply the [sRGB transfer function] so that the storage is sRGB encoded
116///   while the shader works with linear intensity values.
117/// * `Uint`, `Sint`, and `Float` formats perform no conversion.
118///
119/// Corresponds to [WebGPU `GPUTextureFormat`](
120/// https://gpuweb.github.io/gpuweb/#enumdef-gputextureformat).
121///
122/// [sRGB transfer function]: https://en.wikipedia.org/wiki/SRGB#Transfer_function_(%22gamma%22)
123#[repr(C)]
124#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
125pub enum TextureFormat {
126    // Normal 8 bit formats
127    /// Red channel only. 8 bit integer per channel. [0, 255] converted to/from float [0, 1] in shader.
128    R8Unorm,
129    /// Red channel only. 8 bit integer per channel. [&minus;127, 127] converted to/from float [&minus;1, 1] in shader.
130    R8Snorm,
131    /// Red channel only. 8 bit integer per channel. Unsigned in shader.
132    R8Uint,
133    /// Red channel only. 8 bit integer per channel. Signed in shader.
134    R8Sint,
135
136    // Normal 16 bit formats
137    /// Red channel only. 16 bit integer per channel. Unsigned in shader.
138    R16Uint,
139    /// Red channel only. 16 bit integer per channel. Signed in shader.
140    R16Sint,
141    /// Red channel only. 16 bit integer per channel. [0, 65535] converted to/from float [0, 1] in shader.
142    ///
143    /// [`Features::TEXTURE_FORMAT_16BIT_NORM`] must be enabled to use this texture format.
144    R16Unorm,
145    /// Red channel only. 16 bit integer per channel. [&minus;32767, 32767] converted to/from float [&minus;1, 1] in shader.
146    ///
147    /// [`Features::TEXTURE_FORMAT_16BIT_NORM`] must be enabled to use this texture format.
148    R16Snorm,
149    /// Red channel only. 16 bit float per channel. Float in shader.
150    R16Float,
151    /// Red and green channels. 8 bit integer per channel. [0, 255] converted to/from float [0, 1] in shader.
152    Rg8Unorm,
153    /// Red and green channels. 8 bit integer per channel. [&minus;127, 127] converted to/from float [&minus;1, 1] in shader.
154    Rg8Snorm,
155    /// Red and green channels. 8 bit integer per channel. Unsigned in shader.
156    Rg8Uint,
157    /// Red and green channels. 8 bit integer per channel. Signed in shader.
158    Rg8Sint,
159
160    // Normal 32 bit formats
161    /// Red channel only. 32 bit integer per channel. Unsigned in shader.
162    R32Uint,
163    /// Red channel only. 32 bit integer per channel. Signed in shader.
164    R32Sint,
165    /// Red channel only. 32 bit float per channel. Float in shader.
166    R32Float,
167    /// Red and green channels. 16 bit integer per channel. Unsigned in shader.
168    Rg16Uint,
169    /// Red and green channels. 16 bit integer per channel. Signed in shader.
170    Rg16Sint,
171    /// Red and green channels. 16 bit integer per channel. [0, 65535] converted to/from float [0, 1] in shader.
172    ///
173    /// [`Features::TEXTURE_FORMAT_16BIT_NORM`] must be enabled to use this texture format.
174    Rg16Unorm,
175    /// Red and green channels. 16 bit integer per channel. [&minus;32767, 32767] converted to/from float [&minus;1, 1] in shader.
176    ///
177    /// [`Features::TEXTURE_FORMAT_16BIT_NORM`] must be enabled to use this texture format.
178    Rg16Snorm,
179    /// Red and green channels. 16 bit float per channel. Float in shader.
180    Rg16Float,
181    /// Red, green, blue, and alpha channels. 8 bit integer per channel. [0, 255] converted to/from float [0, 1] in shader.
182    Rgba8Unorm,
183    /// Red, green, blue, and alpha channels. 8 bit integer per channel. Srgb-color [0, 255] converted to/from linear-color float [0, 1] in shader.
184    Rgba8UnormSrgb,
185    /// Red, green, blue, and alpha channels. 8 bit integer per channel. [&minus;127, 127] converted to/from float [&minus;1, 1] in shader.
186    Rgba8Snorm,
187    /// Red, green, blue, and alpha channels. 8 bit integer per channel. Unsigned in shader.
188    Rgba8Uint,
189    /// Red, green, blue, and alpha channels. 8 bit integer per channel. Signed in shader.
190    Rgba8Sint,
191    /// Blue, green, red, and alpha channels. 8 bit integer per channel. [0, 255] converted to/from float [0, 1] in shader.
192    Bgra8Unorm,
193    /// Blue, green, red, and alpha channels. 8 bit integer per channel. Srgb-color [0, 255] converted to/from linear-color float [0, 1] in shader.
194    Bgra8UnormSrgb,
195
196    // Packed 32 bit formats
197    /// Packed unsigned float with 9 bits mantisa for each RGB component, then a common 5 bits exponent
198    Rgb9e5Ufloat,
199    /// Red, green, blue, and alpha channels. 10 bit integer for RGB channels, 2 bit integer for alpha channel. Unsigned in shader.
200    Rgb10a2Uint,
201    /// Red, green, blue, and alpha channels. 10 bit integer for RGB channels, 2 bit integer for alpha channel. [0, 1023] ([0, 3] for alpha) converted to/from float [0, 1] in shader.
202    Rgb10a2Unorm,
203    /// Red, green, and blue channels. 11 bit float with no sign bit for RG channels. 10 bit float with no sign bit for blue channel. Float in shader.
204    Rg11b10Ufloat,
205
206    // Normal 64 bit formats
207    /// Red channel only. 64 bit integer per channel. Unsigned in shader.
208    ///
209    /// [`Features::TEXTURE_INT64_ATOMIC`] must be enabled to use this texture format.
210    R64Uint,
211    /// Red and green channels. 32 bit integer per channel. Unsigned in shader.
212    Rg32Uint,
213    /// Red and green channels. 32 bit integer per channel. Signed in shader.
214    Rg32Sint,
215    /// Red and green channels. 32 bit float per channel. Float in shader.
216    Rg32Float,
217    /// Red, green, blue, and alpha channels. 16 bit integer per channel. Unsigned in shader.
218    Rgba16Uint,
219    /// Red, green, blue, and alpha channels. 16 bit integer per channel. Signed in shader.
220    Rgba16Sint,
221    /// Red, green, blue, and alpha channels. 16 bit integer per channel. [0, 65535] converted to/from float [0, 1] in shader.
222    ///
223    /// [`Features::TEXTURE_FORMAT_16BIT_NORM`] must be enabled to use this texture format.
224    Rgba16Unorm,
225    /// Red, green, blue, and alpha. 16 bit integer per channel. [&minus;32767, 32767] converted to/from float [&minus;1, 1] in shader.
226    ///
227    /// [`Features::TEXTURE_FORMAT_16BIT_NORM`] must be enabled to use this texture format.
228    Rgba16Snorm,
229    /// Red, green, blue, and alpha channels. 16 bit float per channel. Float in shader.
230    Rgba16Float,
231
232    // Normal 128 bit formats
233    /// Red, green, blue, and alpha channels. 32 bit integer per channel. Unsigned in shader.
234    Rgba32Uint,
235    /// Red, green, blue, and alpha channels. 32 bit integer per channel. Signed in shader.
236    Rgba32Sint,
237    /// Red, green, blue, and alpha channels. 32 bit float per channel. Float in shader.
238    Rgba32Float,
239
240    // Depth and stencil formats
241    /// Stencil format with 8 bit integer stencil.
242    Stencil8,
243    /// Special depth format with 16 bit integer depth.
244    Depth16Unorm,
245    /// Special depth format with at least 24 bit integer depth.
246    Depth24Plus,
247    /// Special depth/stencil format with at least 24 bit integer depth and 8 bits integer stencil.
248    Depth24PlusStencil8,
249    /// Special depth format with 32 bit floating point depth.
250    Depth32Float,
251    /// Special depth/stencil format with 32 bit floating point depth and 8 bits integer stencil.
252    ///
253    /// [`Features::DEPTH32FLOAT_STENCIL8`] must be enabled to use this texture format.
254    Depth32FloatStencil8,
255
256    /// YUV 4:2:0 chroma subsampled format.
257    ///
258    /// Contains two planes:
259    /// - 0: Single 8 bit channel luminance.
260    /// - 1: Dual 8 bit channel chrominance at half width and half height.
261    ///
262    /// Valid view formats for luminance are [`TextureFormat::R8Unorm`].
263    ///
264    /// Valid view formats for chrominance are [`TextureFormat::Rg8Unorm`].
265    ///
266    /// Width and height must be even.
267    ///
268    /// [`Features::TEXTURE_FORMAT_NV12`] must be enabled to use this texture format.
269    NV12,
270
271    /// YUV 4:2:0 chroma subsampled format.
272    ///
273    /// Contains two planes:
274    /// - 0: Single 16 bit channel luminance, of which only the high 10 bits
275    ///   are used.
276    /// - 1: Dual 16 bit channel chrominance at half width and half height, of
277    ///   which only the high 10 bits are used.
278    ///
279    /// Valid view formats for luminance are [`TextureFormat::R16Unorm`].
280    ///
281    /// Valid view formats for chrominance are [`TextureFormat::Rg16Unorm`].
282    ///
283    /// Width and height must be even.
284    ///
285    /// [`Features::TEXTURE_FORMAT_P010`] must be enabled to use this texture format.
286    P010,
287
288    // Compressed textures usable with `TEXTURE_COMPRESSION_BC` feature. `TEXTURE_COMPRESSION_SLICED_3D` is required to use with 3D textures.
289    /// 4x4 block compressed texture. 8 bytes per block (4 bit/px). 4 color + alpha pallet. 5 bit R + 6 bit G + 5 bit B + 1 bit alpha.
290    /// [0, 63] ([0, 1] for alpha) converted to/from float [0, 1] in shader.
291    ///
292    /// Also known as DXT1.
293    ///
294    /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
295    /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
296    Bc1RgbaUnorm,
297    /// 4x4 block compressed texture. 8 bytes per block (4 bit/px). 4 color + alpha pallet. 5 bit R + 6 bit G + 5 bit B + 1 bit alpha.
298    /// Srgb-color [0, 63] ([0, 1] for alpha) converted to/from linear-color float [0, 1] in shader.
299    ///
300    /// Also known as DXT1.
301    ///
302    /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
303    /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
304    Bc1RgbaUnormSrgb,
305    /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). 4 color pallet. 5 bit R + 6 bit G + 5 bit B + 4 bit alpha.
306    /// [0, 63] ([0, 15] for alpha) converted to/from float [0, 1] in shader.
307    ///
308    /// Also known as DXT3.
309    ///
310    /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
311    /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
312    Bc2RgbaUnorm,
313    /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). 4 color pallet. 5 bit R + 6 bit G + 5 bit B + 4 bit alpha.
314    /// Srgb-color [0, 63] ([0, 255] for alpha) converted to/from linear-color float [0, 1] in shader.
315    ///
316    /// Also known as DXT3.
317    ///
318    /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
319    /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
320    Bc2RgbaUnormSrgb,
321    /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). 4 color pallet + 8 alpha pallet. 5 bit R + 6 bit G + 5 bit B + 8 bit alpha.
322    /// [0, 63] ([0, 255] for alpha) converted to/from float [0, 1] in shader.
323    ///
324    /// Also known as DXT5.
325    ///
326    /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
327    /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
328    Bc3RgbaUnorm,
329    /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). 4 color pallet + 8 alpha pallet. 5 bit R + 6 bit G + 5 bit B + 8 bit alpha.
330    /// Srgb-color [0, 63] ([0, 255] for alpha) converted to/from linear-color float [0, 1] in shader.
331    ///
332    /// Also known as DXT5.
333    ///
334    /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
335    /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
336    Bc3RgbaUnormSrgb,
337    /// 4x4 block compressed texture. 8 bytes per block (4 bit/px). 8 color pallet. 8 bit R.
338    /// [0, 255] converted to/from float [0, 1] in shader.
339    ///
340    /// Also known as RGTC1.
341    ///
342    /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
343    /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
344    Bc4RUnorm,
345    /// 4x4 block compressed texture. 8 bytes per block (4 bit/px). 8 color pallet. 8 bit R.
346    /// [&minus;127, 127] converted to/from float [&minus;1, 1] in shader.
347    ///
348    /// Also known as RGTC1.
349    ///
350    /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
351    /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
352    Bc4RSnorm,
353    /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). 8 color red pallet + 8 color green pallet. 8 bit RG.
354    /// [0, 255] converted to/from float [0, 1] in shader.
355    ///
356    /// Also known as RGTC2.
357    ///
358    /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
359    /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
360    Bc5RgUnorm,
361    /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). 8 color red pallet + 8 color green pallet. 8 bit RG.
362    /// [&minus;127, 127] converted to/from float [&minus;1, 1] in shader.
363    ///
364    /// Also known as RGTC2.
365    ///
366    /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
367    /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
368    Bc5RgSnorm,
369    /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). Variable sized pallet. 16 bit unsigned float RGB. Float in shader.
370    ///
371    /// Also known as BPTC (float).
372    ///
373    /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
374    /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
375    Bc6hRgbUfloat,
376    /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). Variable sized pallet. 16 bit signed float RGB. Float in shader.
377    ///
378    /// Also known as BPTC (float).
379    ///
380    /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
381    /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
382    Bc6hRgbFloat,
383    /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). Variable sized pallet. 8 bit integer RGBA.
384    /// [0, 255] converted to/from float [0, 1] in shader.
385    ///
386    /// Also known as BPTC (unorm).
387    ///
388    /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
389    /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
390    Bc7RgbaUnorm,
391    /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). Variable sized pallet. 8 bit integer RGBA.
392    /// Srgb-color [0, 255] converted to/from linear-color float [0, 1] in shader.
393    ///
394    /// Also known as BPTC (unorm).
395    ///
396    /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
397    /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
398    Bc7RgbaUnormSrgb,
399    /// 4x4 block compressed texture. 8 bytes per block (4 bit/px). Complex pallet. 8 bit integer RGB.
400    /// [0, 255] converted to/from float [0, 1] in shader.
401    ///
402    /// [`Features::TEXTURE_COMPRESSION_ETC2`] must be enabled to use this texture format.
403    Etc2Rgb8Unorm,
404    /// 4x4 block compressed texture. 8 bytes per block (4 bit/px). Complex pallet. 8 bit integer RGB.
405    /// Srgb-color [0, 255] converted to/from linear-color float [0, 1] in shader.
406    ///
407    /// [`Features::TEXTURE_COMPRESSION_ETC2`] must be enabled to use this texture format.
408    Etc2Rgb8UnormSrgb,
409    /// 4x4 block compressed texture. 8 bytes per block (4 bit/px). Complex pallet. 8 bit integer RGB + 1 bit alpha.
410    /// [0, 255] ([0, 1] for alpha) converted to/from float [0, 1] in shader.
411    ///
412    /// [`Features::TEXTURE_COMPRESSION_ETC2`] must be enabled to use this texture format.
413    Etc2Rgb8A1Unorm,
414    /// 4x4 block compressed texture. 8 bytes per block (4 bit/px). Complex pallet. 8 bit integer RGB + 1 bit alpha.
415    /// Srgb-color [0, 255] ([0, 1] for alpha) converted to/from linear-color float [0, 1] in shader.
416    ///
417    /// [`Features::TEXTURE_COMPRESSION_ETC2`] must be enabled to use this texture format.
418    Etc2Rgb8A1UnormSrgb,
419    /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). Complex pallet. 8 bit integer RGB + 8 bit alpha.
420    /// [0, 255] converted to/from float [0, 1] in shader.
421    ///
422    /// [`Features::TEXTURE_COMPRESSION_ETC2`] must be enabled to use this texture format.
423    Etc2Rgba8Unorm,
424    /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). Complex pallet. 8 bit integer RGB + 8 bit alpha.
425    /// Srgb-color [0, 255] converted to/from linear-color float [0, 1] in shader.
426    ///
427    /// [`Features::TEXTURE_COMPRESSION_ETC2`] must be enabled to use this texture format.
428    Etc2Rgba8UnormSrgb,
429    /// 4x4 block compressed texture. 8 bytes per block (4 bit/px). Complex pallet. 11 bit integer R.
430    /// [0, 255] converted to/from float [0, 1] in shader.
431    ///
432    /// [`Features::TEXTURE_COMPRESSION_ETC2`] must be enabled to use this texture format.
433    EacR11Unorm,
434    /// 4x4 block compressed texture. 8 bytes per block (4 bit/px). Complex pallet. 11 bit integer R.
435    /// [&minus;127, 127] converted to/from float [&minus;1, 1] in shader.
436    ///
437    /// [`Features::TEXTURE_COMPRESSION_ETC2`] must be enabled to use this texture format.
438    EacR11Snorm,
439    /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). Complex pallet. 11 bit integer R + 11 bit integer G.
440    /// [0, 255] converted to/from float [0, 1] in shader.
441    ///
442    /// [`Features::TEXTURE_COMPRESSION_ETC2`] must be enabled to use this texture format.
443    EacRg11Unorm,
444    /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). Complex pallet. 11 bit integer R + 11 bit integer G.
445    /// [&minus;127, 127] converted to/from float [&minus;1, 1] in shader.
446    ///
447    /// [`Features::TEXTURE_COMPRESSION_ETC2`] must be enabled to use this texture format.
448    EacRg11Snorm,
449    /// block compressed texture. 16 bytes per block.
450    ///
451    /// Features [`TEXTURE_COMPRESSION_ASTC`] or [`TEXTURE_COMPRESSION_ASTC_HDR`]
452    /// must be enabled to use this texture format.
453    ///
454    /// [`TEXTURE_COMPRESSION_ASTC`]: Features::TEXTURE_COMPRESSION_ASTC
455    /// [`TEXTURE_COMPRESSION_ASTC_HDR`]: Features::TEXTURE_COMPRESSION_ASTC_HDR
456    Astc {
457        /// compressed block dimensions
458        block: AstcBlock,
459        /// ASTC RGBA channel
460        channel: AstcChannel,
461    },
462}
463
464// There are some additional texture format helpers in `wgpu-core/src/conv.rs`,
465// that may need to be modified along with the ones here.
466impl TextureFormat {
467    /// Returns the aspect-specific format of the original format
468    ///
469    /// see <https://gpuweb.github.io/gpuweb/#abstract-opdef-resolving-gputextureaspect>
470    #[must_use]
471    pub fn aspect_specific_format(&self, aspect: TextureAspect) -> Option<Self> {
472        match (*self, aspect) {
473            (Self::Stencil8, TextureAspect::StencilOnly) => Some(*self),
474            (
475                Self::Depth16Unorm | Self::Depth24Plus | Self::Depth32Float,
476                TextureAspect::DepthOnly,
477            ) => Some(*self),
478            (
479                Self::Depth24PlusStencil8 | Self::Depth32FloatStencil8,
480                TextureAspect::StencilOnly,
481            ) => Some(Self::Stencil8),
482            (Self::Depth24PlusStencil8, TextureAspect::DepthOnly) => Some(Self::Depth24Plus),
483            (Self::Depth32FloatStencil8, TextureAspect::DepthOnly) => Some(Self::Depth32Float),
484            (Self::NV12, TextureAspect::Plane0) => Some(Self::R8Unorm),
485            (Self::NV12, TextureAspect::Plane1) => Some(Self::Rg8Unorm),
486            (Self::P010, TextureAspect::Plane0) => Some(Self::R16Unorm),
487            (Self::P010, TextureAspect::Plane1) => Some(Self::Rg16Unorm),
488            // views to multi-planar formats must specify the plane
489            (format, TextureAspect::All) if !format.is_multi_planar_format() => Some(format),
490            _ => None,
491        }
492    }
493
494    /// Returns `true` if `self` is a depth or stencil component of the given
495    /// combined depth-stencil format
496    #[must_use]
497    pub fn is_depth_stencil_component(&self, combined_format: Self) -> bool {
498        match (combined_format, *self) {
499            (Self::Depth24PlusStencil8, Self::Depth24Plus | Self::Stencil8)
500            | (Self::Depth32FloatStencil8, Self::Depth32Float | Self::Stencil8) => true,
501            _ => false,
502        }
503    }
504
505    /// Returns `true` if the format is a depth and/or stencil format
506    ///
507    /// see <https://gpuweb.github.io/gpuweb/#depth-formats>
508    #[must_use]
509    pub fn is_depth_stencil_format(&self) -> bool {
510        self.channels().intersects(TextureChannel::DEPTH_STENCIL)
511    }
512
513    /// Returns `true` if the format is a combined depth-stencil format
514    ///
515    /// see <https://gpuweb.github.io/gpuweb/#combined-depth-stencil-format>
516    #[must_use]
517    pub fn is_combined_depth_stencil_format(&self) -> bool {
518        self.channels().contains(TextureChannel::DEPTH_STENCIL)
519    }
520
521    /// Returns `true` if the format is a multi-planar format
522    #[must_use]
523    pub fn is_multi_planar_format(&self) -> bool {
524        self.planes().is_some()
525    }
526
527    /// Returns the number of planes a multi-planar format has.
528    #[must_use]
529    pub fn planes(&self) -> Option<u32> {
530        match *self {
531            Self::NV12 => Some(2),
532            Self::P010 => Some(2),
533            _ => None,
534        }
535    }
536
537    /// Returns the subsampling factor for the indicated plane of a multi-planar format.
538    #[must_use]
539    pub fn subsampling_factors(&self, plane: Option<u32>) -> (u32, u32) {
540        match *self {
541            Self::NV12 | Self::P010 => match plane {
542                Some(0) => (1, 1),
543                Some(1) => (2, 2),
544                Some(plane) => unreachable!("plane {plane} is not valid for {self:?}"),
545                None => unreachable!("the plane must be specified for multi-planar formats"),
546            },
547            _ => (1, 1),
548        }
549    }
550
551    /// Returns a [TextureChannel] with the bits set where the texture format contains
552    /// the respective channels.
553    ///
554    /// # Example
555    /// ```rust
556    /// # use wgpu_types::{TextureFormat, TextureChannel};
557    ///
558    /// // `Rgba` has a `red`, `green`, `blue` and `alpha` channel!
559    /// assert!(TextureFormat::Rgba8Unorm.channels().contains(TextureChannel::RGBA));
560    ///
561    /// // `Rg` hasn't got an alpha channel...
562    /// assert!(!TextureFormat::Rg8Unorm.channels().contains(TextureChannel::ALPHA));
563    /// // ... but it has a red channel ...
564    /// assert!(TextureFormat::Rg8Unorm.channels().contains(TextureChannel::RED));
565    /// // ... and also a green channel (yay!)
566    /// assert!(TextureFormat::Rg8Unorm.channels().contains(TextureChannel::GREEN));
567    ///
568    /// // A stencil texture has a... stencil channel
569    /// assert!(TextureFormat::Stencil8.channels().contains(TextureChannel::STENCIL));
570    /// // And the `NV12` format should have a `luminance`, `blue-difference` and `red-difference` channel.
571    /// assert!(TextureFormat::NV12.channels().contains(TextureChannel::LUMINANCE_CHROMINANCE));
572    /// ```
573    #[must_use]
574    pub fn channels(&self) -> TextureChannel {
575        match self {
576            Self::R8Unorm
577            | Self::R8Snorm
578            | Self::R8Uint
579            | Self::R8Sint
580            | Self::R16Uint
581            | Self::R16Sint
582            | Self::R16Unorm
583            | Self::R16Snorm
584            | Self::R32Uint
585            | Self::R32Sint
586            | Self::R32Float
587            | Self::R16Float
588            | Self::R64Uint
589            | Self::Bc4RUnorm
590            | Self::Bc4RSnorm
591            | Self::EacR11Unorm
592            | Self::EacR11Snorm => TextureChannel::RED,
593
594            Self::Rg8Unorm
595            | Self::Rg8Snorm
596            | Self::Rg8Uint
597            | Self::Rg8Sint
598            | Self::Rg16Uint
599            | Self::Rg16Sint
600            | Self::Rg16Unorm
601            | Self::Rg16Snorm
602            | Self::Rg16Float
603            | Self::Rg32Uint
604            | Self::Rg32Sint
605            | Self::Rg32Float
606            | Self::Bc5RgUnorm
607            | Self::Bc5RgSnorm
608            | Self::EacRg11Unorm
609            | Self::EacRg11Snorm => TextureChannel::RG,
610
611            Self::Rgb9e5Ufloat
612            | Self::Rg11b10Ufloat
613            | Self::Bc6hRgbUfloat
614            | Self::Bc6hRgbFloat
615            | Self::Etc2Rgb8Unorm
616            | Self::Etc2Rgb8UnormSrgb => TextureChannel::RGB,
617
618            Self::Rgba8Unorm
619            | Self::Rgba8UnormSrgb
620            | Self::Rgba8Snorm
621            | Self::Rgba8Uint
622            | Self::Rgba8Sint
623            | Self::Bgra8Unorm
624            | Self::Bgra8UnormSrgb
625            | Self::Rgb10a2Uint
626            | Self::Rgb10a2Unorm
627            | Self::Rgba16Uint
628            | Self::Rgba16Sint
629            | Self::Rgba16Unorm
630            | Self::Rgba16Snorm
631            | Self::Rgba16Float
632            | Self::Rgba32Uint
633            | Self::Rgba32Sint
634            | Self::Rgba32Float
635            | Self::Bc1RgbaUnorm
636            | Self::Bc1RgbaUnormSrgb
637            | Self::Bc2RgbaUnorm
638            | Self::Bc2RgbaUnormSrgb
639            | Self::Bc3RgbaUnorm
640            | Self::Bc3RgbaUnormSrgb
641            | Self::Bc7RgbaUnorm
642            | Self::Bc7RgbaUnormSrgb
643            | Self::Etc2Rgb8A1Unorm
644            | Self::Etc2Rgb8A1UnormSrgb
645            | Self::Etc2Rgba8Unorm
646            | Self::Etc2Rgba8UnormSrgb
647            | Self::Astc { .. } => TextureChannel::RGBA,
648
649            Self::Stencil8 => TextureChannel::STENCIL,
650            Self::Depth16Unorm | Self::Depth24Plus | Self::Depth32Float => TextureChannel::DEPTH,
651
652            Self::Depth24PlusStencil8 | Self::Depth32FloatStencil8 => TextureChannel::DEPTH_STENCIL,
653
654            Self::NV12 | Self::P010 => TextureChannel::LUMINANCE_CHROMINANCE,
655        }
656    }
657
658    /// Returns `true` if the format has a color aspect
659    #[must_use]
660    pub fn has_color_aspect(&self) -> bool {
661        self.channels().intersects(TextureChannel::RGBA)
662    }
663
664    /// Returns `true` if the format has a depth aspect
665    #[must_use]
666    pub fn has_depth_aspect(&self) -> bool {
667        self.channels().intersects(TextureChannel::DEPTH)
668    }
669
670    /// Returns `true` if the format has a stencil aspect
671    #[must_use]
672    pub fn has_stencil_aspect(&self) -> bool {
673        self.channels().intersects(TextureChannel::STENCIL)
674    }
675
676    /// Returns the size multiple requirement for a texture using this format.
677    ///
678    /// `create_texture` currently enforces a stricter restriction than this for
679    /// mipmapped multi-planar formats.
680    /// TODO(<https://github.com/gfx-rs/wgpu/issues/8491>): Remove this note.
681    #[must_use]
682    pub fn size_multiple_requirement(&self) -> (u32, u32) {
683        match *self {
684            Self::NV12 => (2, 2),
685            Self::P010 => (2, 2),
686            _ => self.block_dimensions(),
687        }
688    }
689
690    /// Returns the dimension of a [block](https://gpuweb.github.io/gpuweb/#texel-block) of texels.
691    ///
692    /// Uncompressed formats have a block dimension of `(1, 1)`.
693    #[must_use]
694    pub fn block_dimensions(&self) -> (u32, u32) {
695        match *self {
696            Self::R8Unorm
697            | Self::R8Snorm
698            | Self::R8Uint
699            | Self::R8Sint
700            | Self::R16Uint
701            | Self::R16Sint
702            | Self::R16Unorm
703            | Self::R16Snorm
704            | Self::R16Float
705            | Self::Rg8Unorm
706            | Self::Rg8Snorm
707            | Self::Rg8Uint
708            | Self::Rg8Sint
709            | Self::R32Uint
710            | Self::R32Sint
711            | Self::R32Float
712            | Self::Rg16Uint
713            | Self::Rg16Sint
714            | Self::Rg16Unorm
715            | Self::Rg16Snorm
716            | Self::Rg16Float
717            | Self::Rgba8Unorm
718            | Self::Rgba8UnormSrgb
719            | Self::Rgba8Snorm
720            | Self::Rgba8Uint
721            | Self::Rgba8Sint
722            | Self::Bgra8Unorm
723            | Self::Bgra8UnormSrgb
724            | Self::Rgb9e5Ufloat
725            | Self::Rgb10a2Uint
726            | Self::Rgb10a2Unorm
727            | Self::Rg11b10Ufloat
728            | Self::R64Uint
729            | Self::Rg32Uint
730            | Self::Rg32Sint
731            | Self::Rg32Float
732            | Self::Rgba16Uint
733            | Self::Rgba16Sint
734            | Self::Rgba16Unorm
735            | Self::Rgba16Snorm
736            | Self::Rgba16Float
737            | Self::Rgba32Uint
738            | Self::Rgba32Sint
739            | Self::Rgba32Float
740            | Self::Stencil8
741            | Self::Depth16Unorm
742            | Self::Depth24Plus
743            | Self::Depth24PlusStencil8
744            | Self::Depth32Float
745            | Self::Depth32FloatStencil8
746            | Self::NV12
747            | Self::P010 => (1, 1),
748
749            Self::Bc1RgbaUnorm
750            | Self::Bc1RgbaUnormSrgb
751            | Self::Bc2RgbaUnorm
752            | Self::Bc2RgbaUnormSrgb
753            | Self::Bc3RgbaUnorm
754            | Self::Bc3RgbaUnormSrgb
755            | Self::Bc4RUnorm
756            | Self::Bc4RSnorm
757            | Self::Bc5RgUnorm
758            | Self::Bc5RgSnorm
759            | Self::Bc6hRgbUfloat
760            | Self::Bc6hRgbFloat
761            | Self::Bc7RgbaUnorm
762            | Self::Bc7RgbaUnormSrgb => (4, 4),
763
764            Self::Etc2Rgb8Unorm
765            | Self::Etc2Rgb8UnormSrgb
766            | Self::Etc2Rgb8A1Unorm
767            | Self::Etc2Rgb8A1UnormSrgb
768            | Self::Etc2Rgba8Unorm
769            | Self::Etc2Rgba8UnormSrgb
770            | Self::EacR11Unorm
771            | Self::EacR11Snorm
772            | Self::EacRg11Unorm
773            | Self::EacRg11Snorm => (4, 4),
774
775            Self::Astc { block, .. } => match block {
776                AstcBlock::B4x4 => (4, 4),
777                AstcBlock::B5x4 => (5, 4),
778                AstcBlock::B5x5 => (5, 5),
779                AstcBlock::B6x5 => (6, 5),
780                AstcBlock::B6x6 => (6, 6),
781                AstcBlock::B8x5 => (8, 5),
782                AstcBlock::B8x6 => (8, 6),
783                AstcBlock::B8x8 => (8, 8),
784                AstcBlock::B10x5 => (10, 5),
785                AstcBlock::B10x6 => (10, 6),
786                AstcBlock::B10x8 => (10, 8),
787                AstcBlock::B10x10 => (10, 10),
788                AstcBlock::B12x10 => (12, 10),
789                AstcBlock::B12x12 => (12, 12),
790            },
791        }
792    }
793
794    /// Returns `true` for compressed formats.
795    #[must_use]
796    pub fn is_compressed(&self) -> bool {
797        self.block_dimensions() != (1, 1)
798    }
799
800    /// Returns `true` for BCn compressed formats.
801    #[must_use]
802    pub fn is_bcn(&self) -> bool {
803        self.required_features() == Features::TEXTURE_COMPRESSION_BC
804    }
805
806    /// Returns `true` for ASTC compressed formats.
807    #[must_use]
808    pub fn is_astc(&self) -> bool {
809        self.required_features() == Features::TEXTURE_COMPRESSION_ASTC
810            || self.required_features() == Features::TEXTURE_COMPRESSION_ASTC_HDR
811    }
812
813    /// Returns the required features (if any) in order to use the texture.
814    #[must_use]
815    pub fn required_features(&self) -> Features {
816        match *self {
817            Self::R8Unorm
818            | Self::R8Snorm
819            | Self::R8Uint
820            | Self::R8Sint
821            | Self::R16Uint
822            | Self::R16Sint
823            | Self::R16Float
824            | Self::Rg8Unorm
825            | Self::Rg8Snorm
826            | Self::Rg8Uint
827            | Self::Rg8Sint
828            | Self::R32Uint
829            | Self::R32Sint
830            | Self::R32Float
831            | Self::Rg16Uint
832            | Self::Rg16Sint
833            | Self::Rg16Float
834            | Self::Rgba8Unorm
835            | Self::Rgba8UnormSrgb
836            | Self::Rgba8Snorm
837            | Self::Rgba8Uint
838            | Self::Rgba8Sint
839            | Self::Bgra8Unorm
840            | Self::Bgra8UnormSrgb
841            | Self::Rgb9e5Ufloat
842            | Self::Rgb10a2Uint
843            | Self::Rgb10a2Unorm
844            | Self::Rg11b10Ufloat
845            | Self::Rg32Uint
846            | Self::Rg32Sint
847            | Self::Rg32Float
848            | Self::Rgba16Uint
849            | Self::Rgba16Sint
850            | Self::Rgba16Float
851            | Self::Rgba32Uint
852            | Self::Rgba32Sint
853            | Self::Rgba32Float
854            | Self::Stencil8
855            | Self::Depth16Unorm
856            | Self::Depth24Plus
857            | Self::Depth24PlusStencil8
858            | Self::Depth32Float => Features::empty(),
859
860            Self::R64Uint => Features::TEXTURE_INT64_ATOMIC,
861
862            Self::Depth32FloatStencil8 => Features::DEPTH32FLOAT_STENCIL8,
863
864            Self::NV12 => Features::TEXTURE_FORMAT_NV12,
865            Self::P010 => Features::TEXTURE_FORMAT_P010,
866
867            Self::R16Unorm
868            | Self::R16Snorm
869            | Self::Rg16Unorm
870            | Self::Rg16Snorm
871            | Self::Rgba16Unorm
872            | Self::Rgba16Snorm => Features::TEXTURE_FORMAT_16BIT_NORM,
873
874            Self::Bc1RgbaUnorm
875            | Self::Bc1RgbaUnormSrgb
876            | Self::Bc2RgbaUnorm
877            | Self::Bc2RgbaUnormSrgb
878            | Self::Bc3RgbaUnorm
879            | Self::Bc3RgbaUnormSrgb
880            | Self::Bc4RUnorm
881            | Self::Bc4RSnorm
882            | Self::Bc5RgUnorm
883            | Self::Bc5RgSnorm
884            | Self::Bc6hRgbUfloat
885            | Self::Bc6hRgbFloat
886            | Self::Bc7RgbaUnorm
887            | Self::Bc7RgbaUnormSrgb => Features::TEXTURE_COMPRESSION_BC,
888
889            Self::Etc2Rgb8Unorm
890            | Self::Etc2Rgb8UnormSrgb
891            | Self::Etc2Rgb8A1Unorm
892            | Self::Etc2Rgb8A1UnormSrgb
893            | Self::Etc2Rgba8Unorm
894            | Self::Etc2Rgba8UnormSrgb
895            | Self::EacR11Unorm
896            | Self::EacR11Snorm
897            | Self::EacRg11Unorm
898            | Self::EacRg11Snorm => Features::TEXTURE_COMPRESSION_ETC2,
899
900            Self::Astc { channel, .. } => match channel {
901                AstcChannel::Hdr => Features::TEXTURE_COMPRESSION_ASTC_HDR,
902                AstcChannel::Unorm | AstcChannel::UnormSrgb => Features::TEXTURE_COMPRESSION_ASTC,
903            },
904        }
905    }
906
907    /// Returns the format features guaranteed by the WebGPU spec.
908    ///
909    /// Additional features are available if `Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES` is enabled.
910    #[must_use]
911    pub fn guaranteed_format_features(&self, device_features: Features) -> TextureFormatFeatures {
912        // Multisampling
913        let none = TextureFormatFeatureFlags::empty();
914        let msaa = TextureFormatFeatureFlags::MULTISAMPLE_X4;
915        let msaa_resolve = msaa | TextureFormatFeatureFlags::MULTISAMPLE_RESOLVE;
916
917        let s_ro_wo = TextureFormatFeatureFlags::STORAGE_READ_ONLY
918            | TextureFormatFeatureFlags::STORAGE_WRITE_ONLY;
919        let s_all = s_ro_wo | TextureFormatFeatureFlags::STORAGE_READ_WRITE;
920
921        // Flags
922        let basic =
923            TextureUsages::COPY_SRC | TextureUsages::COPY_DST | TextureUsages::TEXTURE_BINDING;
924        let attachment = basic | TextureUsages::RENDER_ATTACHMENT | TextureUsages::TRANSIENT;
925        let storage = basic | TextureUsages::STORAGE_BINDING;
926        let binding = TextureUsages::TEXTURE_BINDING;
927        let all_flags = attachment | storage | binding;
928        let atomic_64 = if device_features.contains(Features::TEXTURE_ATOMIC) {
929            storage | binding | TextureUsages::STORAGE_ATOMIC
930        } else {
931            storage | binding
932        };
933        let atomic = attachment | atomic_64;
934        let (rg11b10f_f, rg11b10f_u) =
935            if device_features.contains(Features::RG11B10UFLOAT_RENDERABLE) {
936                (msaa_resolve, attachment)
937            } else {
938                (msaa, basic)
939            };
940        let (bgra8unorm_f, bgra8unorm) = if device_features.contains(Features::BGRA8UNORM_STORAGE) {
941            (
942                msaa_resolve | TextureFormatFeatureFlags::STORAGE_WRITE_ONLY,
943                attachment | TextureUsages::STORAGE_BINDING,
944            )
945        } else {
946            (msaa_resolve, attachment)
947        };
948
949        #[rustfmt::skip] // lets make a nice table
950        let (
951            mut flags,
952            allowed_usages,
953        ) = match *self {
954            Self::R8Unorm =>              (msaa_resolve, attachment),
955            Self::R8Snorm =>              (        none,      basic),
956            Self::R8Uint =>               (        msaa, attachment),
957            Self::R8Sint =>               (        msaa, attachment),
958            Self::R16Uint =>              (        msaa, attachment),
959            Self::R16Sint =>              (        msaa, attachment),
960            Self::R16Float =>             (msaa_resolve, attachment),
961            Self::Rg8Unorm =>             (msaa_resolve, attachment),
962            Self::Rg8Snorm =>             (        none,      basic),
963            Self::Rg8Uint =>              (        msaa, attachment),
964            Self::Rg8Sint =>              (        msaa, attachment),
965            Self::R32Uint =>              (       s_all,     atomic),
966            Self::R32Sint =>              (       s_all,     atomic),
967            Self::R32Float =>             (msaa | s_all,  all_flags),
968            Self::Rg16Uint =>             (        msaa, attachment),
969            Self::Rg16Sint =>             (        msaa, attachment),
970            Self::Rg16Float =>            (msaa_resolve, attachment),
971            Self::Rgba8Unorm =>           (msaa_resolve | s_ro_wo,  all_flags),
972            Self::Rgba8UnormSrgb =>       (msaa_resolve, attachment),
973            Self::Rgba8Snorm =>           (     s_ro_wo,    storage),
974            Self::Rgba8Uint =>            (        msaa | s_ro_wo,  all_flags),
975            Self::Rgba8Sint =>            (        msaa | s_ro_wo,  all_flags),
976            Self::Bgra8Unorm =>           (bgra8unorm_f, bgra8unorm),
977            Self::Bgra8UnormSrgb =>       (msaa_resolve, attachment),
978            Self::Rgb10a2Uint =>          (        msaa, attachment),
979            Self::Rgb10a2Unorm =>         (msaa_resolve, attachment),
980            Self::Rg11b10Ufloat =>        (  rg11b10f_f, rg11b10f_u),
981            Self::R64Uint =>              (     s_ro_wo,  atomic_64),
982            Self::Rg32Uint =>             (     s_ro_wo,  all_flags),
983            Self::Rg32Sint =>             (     s_ro_wo,  all_flags),
984            Self::Rg32Float =>            (     s_ro_wo,  all_flags),
985            Self::Rgba16Uint =>           (        msaa | s_ro_wo,  all_flags),
986            Self::Rgba16Sint =>           (        msaa | s_ro_wo,  all_flags),
987            Self::Rgba16Float =>          (msaa_resolve | s_ro_wo,  all_flags),
988            Self::Rgba32Uint =>           (     s_ro_wo,  all_flags),
989            Self::Rgba32Sint =>           (     s_ro_wo,  all_flags),
990            Self::Rgba32Float =>          (     s_ro_wo,  all_flags),
991
992            Self::Stencil8 =>             (        msaa, attachment),
993            Self::Depth16Unorm =>         (        msaa, attachment),
994            Self::Depth24Plus =>          (        msaa, attachment),
995            Self::Depth24PlusStencil8 =>  (        msaa, attachment),
996            Self::Depth32Float =>         (        msaa, attachment),
997            Self::Depth32FloatStencil8 => (        msaa, attachment),
998
999            // We only support sampling nv12 and p010 textures until we
1000            // implement transfer plane data.
1001            Self::NV12 =>                 (        none,    binding),
1002            Self::P010 =>                 (        none,    binding),
1003
1004            Self::R16Unorm =>             (        msaa | s_ro_wo,    storage),
1005            Self::R16Snorm =>             (        msaa | s_ro_wo,    storage),
1006            Self::Rg16Unorm =>            (        msaa | s_ro_wo,    storage),
1007            Self::Rg16Snorm =>            (        msaa | s_ro_wo,    storage),
1008            Self::Rgba16Unorm =>          (        msaa | s_ro_wo,    storage),
1009            Self::Rgba16Snorm =>          (        msaa | s_ro_wo,    storage),
1010
1011            Self::Rgb9e5Ufloat =>         (        none,      basic),
1012
1013            Self::Bc1RgbaUnorm =>         (        none,      basic),
1014            Self::Bc1RgbaUnormSrgb =>     (        none,      basic),
1015            Self::Bc2RgbaUnorm =>         (        none,      basic),
1016            Self::Bc2RgbaUnormSrgb =>     (        none,      basic),
1017            Self::Bc3RgbaUnorm =>         (        none,      basic),
1018            Self::Bc3RgbaUnormSrgb =>     (        none,      basic),
1019            Self::Bc4RUnorm =>            (        none,      basic),
1020            Self::Bc4RSnorm =>            (        none,      basic),
1021            Self::Bc5RgUnorm =>           (        none,      basic),
1022            Self::Bc5RgSnorm =>           (        none,      basic),
1023            Self::Bc6hRgbUfloat =>        (        none,      basic),
1024            Self::Bc6hRgbFloat =>         (        none,      basic),
1025            Self::Bc7RgbaUnorm =>         (        none,      basic),
1026            Self::Bc7RgbaUnormSrgb =>     (        none,      basic),
1027
1028            Self::Etc2Rgb8Unorm =>        (        none,      basic),
1029            Self::Etc2Rgb8UnormSrgb =>    (        none,      basic),
1030            Self::Etc2Rgb8A1Unorm =>      (        none,      basic),
1031            Self::Etc2Rgb8A1UnormSrgb =>  (        none,      basic),
1032            Self::Etc2Rgba8Unorm =>       (        none,      basic),
1033            Self::Etc2Rgba8UnormSrgb =>   (        none,      basic),
1034            Self::EacR11Unorm =>          (        none,      basic),
1035            Self::EacR11Snorm =>          (        none,      basic),
1036            Self::EacRg11Unorm =>         (        none,      basic),
1037            Self::EacRg11Snorm =>         (        none,      basic),
1038
1039            Self::Astc { .. } =>          (        none,      basic),
1040        };
1041
1042        // Get whether the format is filterable, taking features into account
1043        let sample_type1 = self.sample_type(None, Some(device_features));
1044        let is_filterable = sample_type1 == Some(TextureSampleType::Float { filterable: true });
1045
1046        // Features that enable filtering don't affect blendability
1047        let sample_type2 = self.sample_type(None, None);
1048        let is_blendable = sample_type2 == Some(TextureSampleType::Float { filterable: true })
1049            || device_features.contains(Features::FLOAT32_BLENDABLE)
1050                && matches!(self, Self::R32Float | Self::Rg32Float | Self::Rgba32Float);
1051
1052        flags.set(TextureFormatFeatureFlags::FILTERABLE, is_filterable);
1053        flags.set(TextureFormatFeatureFlags::BLENDABLE, is_blendable);
1054        flags.set(
1055            TextureFormatFeatureFlags::STORAGE_ATOMIC,
1056            allowed_usages.contains(TextureUsages::STORAGE_ATOMIC),
1057        );
1058
1059        TextureFormatFeatures {
1060            allowed_usages,
1061            flags,
1062        }
1063    }
1064
1065    /// Returns the sample type compatible with this format and aspect.
1066    ///
1067    /// Returns `None` only if this is a combined depth-stencil format or a multi-planar format
1068    /// and `TextureAspect::All` or no `aspect` was provided.
1069    #[must_use]
1070    pub fn sample_type(
1071        &self,
1072        aspect: Option<TextureAspect>,
1073        device_features: Option<Features>,
1074    ) -> Option<TextureSampleType> {
1075        let float = TextureSampleType::Float { filterable: true };
1076        let unfilterable_float = TextureSampleType::Float { filterable: false };
1077        let float32_sample_type = TextureSampleType::Float {
1078            filterable: device_features
1079                .unwrap_or(Features::empty())
1080                .contains(Features::FLOAT32_FILTERABLE),
1081        };
1082        let depth = TextureSampleType::Depth;
1083        let uint = TextureSampleType::Uint;
1084        let sint = TextureSampleType::Sint;
1085
1086        match *self {
1087            Self::R8Unorm
1088            | Self::R8Snorm
1089            | Self::Rg8Unorm
1090            | Self::Rg8Snorm
1091            | Self::Rgba8Unorm
1092            | Self::Rgba8UnormSrgb
1093            | Self::Rgba8Snorm
1094            | Self::Bgra8Unorm
1095            | Self::Bgra8UnormSrgb
1096            | Self::R16Float
1097            | Self::Rg16Float
1098            | Self::Rgba16Float
1099            | Self::Rgb10a2Unorm
1100            | Self::Rg11b10Ufloat => Some(float),
1101
1102            Self::R32Float | Self::Rg32Float | Self::Rgba32Float => Some(float32_sample_type),
1103
1104            Self::R8Uint
1105            | Self::Rg8Uint
1106            | Self::Rgba8Uint
1107            | Self::R16Uint
1108            | Self::Rg16Uint
1109            | Self::Rgba16Uint
1110            | Self::R32Uint
1111            | Self::R64Uint
1112            | Self::Rg32Uint
1113            | Self::Rgba32Uint
1114            | Self::Rgb10a2Uint => Some(uint),
1115
1116            Self::R8Sint
1117            | Self::Rg8Sint
1118            | Self::Rgba8Sint
1119            | Self::R16Sint
1120            | Self::Rg16Sint
1121            | Self::Rgba16Sint
1122            | Self::R32Sint
1123            | Self::Rg32Sint
1124            | Self::Rgba32Sint => Some(sint),
1125
1126            Self::Stencil8 => Some(uint),
1127            Self::Depth16Unorm | Self::Depth24Plus | Self::Depth32Float => Some(depth),
1128            Self::Depth24PlusStencil8 | Self::Depth32FloatStencil8 => match aspect {
1129                Some(TextureAspect::DepthOnly) => Some(depth),
1130                Some(TextureAspect::StencilOnly) => Some(uint),
1131                _ => None,
1132            },
1133
1134            Self::NV12 | Self::P010 => match aspect {
1135                Some(TextureAspect::Plane0) | Some(TextureAspect::Plane1) => {
1136                    Some(unfilterable_float)
1137                }
1138                _ => None,
1139            },
1140
1141            Self::R16Unorm
1142            | Self::R16Snorm
1143            | Self::Rg16Unorm
1144            | Self::Rg16Snorm
1145            | Self::Rgba16Unorm
1146            | Self::Rgba16Snorm => Some(float),
1147
1148            Self::Rgb9e5Ufloat => Some(float),
1149
1150            Self::Bc1RgbaUnorm
1151            | Self::Bc1RgbaUnormSrgb
1152            | Self::Bc2RgbaUnorm
1153            | Self::Bc2RgbaUnormSrgb
1154            | Self::Bc3RgbaUnorm
1155            | Self::Bc3RgbaUnormSrgb
1156            | Self::Bc4RUnorm
1157            | Self::Bc4RSnorm
1158            | Self::Bc5RgUnorm
1159            | Self::Bc5RgSnorm
1160            | Self::Bc6hRgbUfloat
1161            | Self::Bc6hRgbFloat
1162            | Self::Bc7RgbaUnorm
1163            | Self::Bc7RgbaUnormSrgb => Some(float),
1164
1165            Self::Etc2Rgb8Unorm
1166            | Self::Etc2Rgb8UnormSrgb
1167            | Self::Etc2Rgb8A1Unorm
1168            | Self::Etc2Rgb8A1UnormSrgb
1169            | Self::Etc2Rgba8Unorm
1170            | Self::Etc2Rgba8UnormSrgb
1171            | Self::EacR11Unorm
1172            | Self::EacR11Snorm
1173            | Self::EacRg11Unorm
1174            | Self::EacRg11Snorm => Some(float),
1175
1176            Self::Astc { .. } => Some(float),
1177        }
1178    }
1179
1180    /// The number of bytes one [texel block](https://gpuweb.github.io/gpuweb/#texel-block) occupies during an image copy, if applicable.
1181    ///
1182    /// Known as the [texel block copy footprint](https://gpuweb.github.io/gpuweb/#texel-block-copy-footprint).
1183    ///
1184    /// Note that for uncompressed formats this is the same as the size of a single texel,
1185    /// since uncompressed formats have a block size of 1x1.
1186    ///
1187    /// Returns `None` if any of the following are true:
1188    ///  - the format is a combined depth-stencil and no `aspect` was provided
1189    ///  - the format is a multi-planar format and no `aspect` was provided
1190    ///  - the format is `Depth24Plus`
1191    ///  - the format is `Depth24PlusStencil8` and `aspect` is depth.
1192    #[deprecated(since = "0.19.0", note = "Use `block_copy_size` instead.")]
1193    #[must_use]
1194    pub fn block_size(&self, aspect: Option<TextureAspect>) -> Option<u32> {
1195        self.block_copy_size(aspect)
1196    }
1197
1198    /// The number of bytes one [texel block](https://gpuweb.github.io/gpuweb/#texel-block) occupies during an image copy, if applicable.
1199    ///
1200    /// Known as the [texel block copy footprint](https://gpuweb.github.io/gpuweb/#texel-block-copy-footprint).
1201    ///
1202    /// Note that for uncompressed formats this is the same as the size of a single texel,
1203    /// since uncompressed formats have a block size of 1x1.
1204    ///
1205    /// Returns `None` if any of the following are true:
1206    ///  - the format is a combined depth-stencil and no `aspect` was provided
1207    ///  - the format is a multi-planar format and no `aspect` was provided
1208    ///  - the format is `Depth24Plus`
1209    ///  - the format is `Depth24PlusStencil8` and `aspect` is depth.
1210    #[must_use]
1211    pub fn block_copy_size(&self, aspect: Option<TextureAspect>) -> Option<u32> {
1212        match *self {
1213            Self::R8Unorm | Self::R8Snorm | Self::R8Uint | Self::R8Sint => Some(1),
1214
1215            Self::Rg8Unorm | Self::Rg8Snorm | Self::Rg8Uint | Self::Rg8Sint => Some(2),
1216            Self::R16Unorm | Self::R16Snorm | Self::R16Uint | Self::R16Sint | Self::R16Float => {
1217                Some(2)
1218            }
1219
1220            Self::Rgba8Unorm
1221            | Self::Rgba8UnormSrgb
1222            | Self::Rgba8Snorm
1223            | Self::Rgba8Uint
1224            | Self::Rgba8Sint
1225            | Self::Bgra8Unorm
1226            | Self::Bgra8UnormSrgb => Some(4),
1227            Self::Rg16Unorm
1228            | Self::Rg16Snorm
1229            | Self::Rg16Uint
1230            | Self::Rg16Sint
1231            | Self::Rg16Float => Some(4),
1232            Self::R32Uint | Self::R32Sint | Self::R32Float => Some(4),
1233            Self::Rgb9e5Ufloat | Self::Rgb10a2Uint | Self::Rgb10a2Unorm | Self::Rg11b10Ufloat => {
1234                Some(4)
1235            }
1236
1237            Self::Rgba16Unorm
1238            | Self::Rgba16Snorm
1239            | Self::Rgba16Uint
1240            | Self::Rgba16Sint
1241            | Self::Rgba16Float => Some(8),
1242            Self::R64Uint | Self::Rg32Uint | Self::Rg32Sint | Self::Rg32Float => Some(8),
1243
1244            Self::Rgba32Uint | Self::Rgba32Sint | Self::Rgba32Float => Some(16),
1245
1246            Self::Stencil8 => Some(1),
1247            Self::Depth16Unorm => Some(2),
1248            Self::Depth32Float => Some(4),
1249            Self::Depth24Plus => None,
1250            Self::Depth24PlusStencil8 => match aspect {
1251                Some(TextureAspect::DepthOnly) => None,
1252                Some(TextureAspect::StencilOnly) => Some(1),
1253                _ => None,
1254            },
1255            Self::Depth32FloatStencil8 => match aspect {
1256                Some(TextureAspect::DepthOnly) => Some(4),
1257                Some(TextureAspect::StencilOnly) => Some(1),
1258                _ => None,
1259            },
1260
1261            Self::NV12 => match aspect {
1262                Some(TextureAspect::Plane0) => Some(1),
1263                Some(TextureAspect::Plane1) => Some(2),
1264                _ => None,
1265            },
1266
1267            Self::P010 => match aspect {
1268                Some(TextureAspect::Plane0) => Some(2),
1269                Some(TextureAspect::Plane1) => Some(4),
1270                _ => None,
1271            },
1272
1273            Self::Bc1RgbaUnorm | Self::Bc1RgbaUnormSrgb | Self::Bc4RUnorm | Self::Bc4RSnorm => {
1274                Some(8)
1275            }
1276            Self::Bc2RgbaUnorm
1277            | Self::Bc2RgbaUnormSrgb
1278            | Self::Bc3RgbaUnorm
1279            | Self::Bc3RgbaUnormSrgb
1280            | Self::Bc5RgUnorm
1281            | Self::Bc5RgSnorm
1282            | Self::Bc6hRgbUfloat
1283            | Self::Bc6hRgbFloat
1284            | Self::Bc7RgbaUnorm
1285            | Self::Bc7RgbaUnormSrgb => Some(16),
1286
1287            Self::Etc2Rgb8Unorm
1288            | Self::Etc2Rgb8UnormSrgb
1289            | Self::Etc2Rgb8A1Unorm
1290            | Self::Etc2Rgb8A1UnormSrgb
1291            | Self::EacR11Unorm
1292            | Self::EacR11Snorm => Some(8),
1293            Self::Etc2Rgba8Unorm
1294            | Self::Etc2Rgba8UnormSrgb
1295            | Self::EacRg11Unorm
1296            | Self::EacRg11Snorm => Some(16),
1297
1298            Self::Astc { .. } => Some(16),
1299        }
1300    }
1301
1302    /// The largest number that can be returned by [`Self::target_pixel_byte_cost`].
1303    pub const MAX_TARGET_PIXEL_BYTE_COST: u32 = 16;
1304
1305    /// The number of bytes occupied per pixel in a color attachment
1306    /// <https://gpuweb.github.io/gpuweb/#render-target-pixel-byte-cost>
1307    #[must_use]
1308    pub fn target_pixel_byte_cost(&self) -> Option<u32> {
1309        match *self {
1310            Self::R8Unorm | Self::R8Snorm | Self::R8Uint | Self::R8Sint => Some(1),
1311            Self::Rg8Unorm
1312            | Self::Rg8Snorm
1313            | Self::Rg8Uint
1314            | Self::Rg8Sint
1315            | Self::R16Uint
1316            | Self::R16Sint
1317            | Self::R16Unorm
1318            | Self::R16Snorm
1319            | Self::R16Float => Some(2),
1320            Self::Rgba8Uint
1321            | Self::Rgba8Sint
1322            | Self::Rg16Uint
1323            | Self::Rg16Sint
1324            | Self::Rg16Unorm
1325            | Self::Rg16Snorm
1326            | Self::Rg16Float
1327            | Self::R32Uint
1328            | Self::R32Sint
1329            | Self::R32Float => Some(4),
1330            // Despite being 4 bytes per pixel, these are 8 bytes per pixel in the table
1331            Self::Rgba8Unorm
1332            | Self::Rgba8UnormSrgb
1333            | Self::Rgba8Snorm
1334            | Self::Bgra8Unorm
1335            | Self::Bgra8UnormSrgb
1336            // ---
1337            | Self::Rgba16Uint
1338            | Self::Rgba16Sint
1339            | Self::Rgba16Unorm
1340            | Self::Rgba16Snorm
1341            | Self::Rgba16Float
1342            | Self::R64Uint
1343            | Self::Rg32Uint
1344            | Self::Rg32Sint
1345            | Self::Rg32Float
1346            | Self::Rgb10a2Uint
1347            | Self::Rgb10a2Unorm
1348            | Self::Rg11b10Ufloat => Some(8),
1349            Self::Rgba32Uint | Self::Rgba32Sint | Self::Rgba32Float => Some(16),
1350            // ⚠️ If you add formats with larger sizes, make sure you change `MAX_TARGET_PIXEL_BYTE_COST`` ⚠️
1351            Self::Stencil8
1352            | Self::Depth16Unorm
1353            | Self::Depth24Plus
1354            | Self::Depth24PlusStencil8
1355            | Self::Depth32Float
1356            | Self::Depth32FloatStencil8
1357            | Self::NV12
1358            | Self::P010
1359            | Self::Rgb9e5Ufloat
1360            | Self::Bc1RgbaUnorm
1361            | Self::Bc1RgbaUnormSrgb
1362            | Self::Bc2RgbaUnorm
1363            | Self::Bc2RgbaUnormSrgb
1364            | Self::Bc3RgbaUnorm
1365            | Self::Bc3RgbaUnormSrgb
1366            | Self::Bc4RUnorm
1367            | Self::Bc4RSnorm
1368            | Self::Bc5RgUnorm
1369            | Self::Bc5RgSnorm
1370            | Self::Bc6hRgbUfloat
1371            | Self::Bc6hRgbFloat
1372            | Self::Bc7RgbaUnorm
1373            | Self::Bc7RgbaUnormSrgb
1374            | Self::Etc2Rgb8Unorm
1375            | Self::Etc2Rgb8UnormSrgb
1376            | Self::Etc2Rgb8A1Unorm
1377            | Self::Etc2Rgb8A1UnormSrgb
1378            | Self::Etc2Rgba8Unorm
1379            | Self::Etc2Rgba8UnormSrgb
1380            | Self::EacR11Unorm
1381            | Self::EacR11Snorm
1382            | Self::EacRg11Unorm
1383            | Self::EacRg11Snorm
1384            | Self::Astc { .. } => None,
1385        }
1386    }
1387
1388    /// See <https://gpuweb.github.io/gpuweb/#render-target-component-alignment>
1389    #[must_use]
1390    pub fn target_component_alignment(&self) -> Option<u32> {
1391        match *self {
1392            Self::R8Unorm
1393            | Self::R8Snorm
1394            | Self::R8Uint
1395            | Self::R8Sint
1396            | Self::Rg8Unorm
1397            | Self::Rg8Snorm
1398            | Self::Rg8Uint
1399            | Self::Rg8Sint
1400            | Self::Rgba8Unorm
1401            | Self::Rgba8UnormSrgb
1402            | Self::Rgba8Snorm
1403            | Self::Rgba8Uint
1404            | Self::Rgba8Sint
1405            | Self::Bgra8Unorm
1406            | Self::Bgra8UnormSrgb => Some(1),
1407            Self::R16Uint
1408            | Self::R16Sint
1409            | Self::R16Unorm
1410            | Self::R16Snorm
1411            | Self::R16Float
1412            | Self::Rg16Uint
1413            | Self::Rg16Sint
1414            | Self::Rg16Unorm
1415            | Self::Rg16Snorm
1416            | Self::Rg16Float
1417            | Self::Rgba16Uint
1418            | Self::Rgba16Sint
1419            | Self::Rgba16Unorm
1420            | Self::Rgba16Snorm
1421            | Self::Rgba16Float => Some(2),
1422            Self::R32Uint
1423            | Self::R32Sint
1424            | Self::R32Float
1425            | Self::R64Uint
1426            | Self::Rg32Uint
1427            | Self::Rg32Sint
1428            | Self::Rg32Float
1429            | Self::Rgba32Uint
1430            | Self::Rgba32Sint
1431            | Self::Rgba32Float
1432            | Self::Rgb10a2Uint
1433            | Self::Rgb10a2Unorm
1434            | Self::Rg11b10Ufloat => Some(4),
1435            Self::Stencil8
1436            | Self::Depth16Unorm
1437            | Self::Depth24Plus
1438            | Self::Depth24PlusStencil8
1439            | Self::Depth32Float
1440            | Self::Depth32FloatStencil8
1441            | Self::NV12
1442            | Self::P010
1443            | Self::Rgb9e5Ufloat
1444            | Self::Bc1RgbaUnorm
1445            | Self::Bc1RgbaUnormSrgb
1446            | Self::Bc2RgbaUnorm
1447            | Self::Bc2RgbaUnormSrgb
1448            | Self::Bc3RgbaUnorm
1449            | Self::Bc3RgbaUnormSrgb
1450            | Self::Bc4RUnorm
1451            | Self::Bc4RSnorm
1452            | Self::Bc5RgUnorm
1453            | Self::Bc5RgSnorm
1454            | Self::Bc6hRgbUfloat
1455            | Self::Bc6hRgbFloat
1456            | Self::Bc7RgbaUnorm
1457            | Self::Bc7RgbaUnormSrgb
1458            | Self::Etc2Rgb8Unorm
1459            | Self::Etc2Rgb8UnormSrgb
1460            | Self::Etc2Rgb8A1Unorm
1461            | Self::Etc2Rgb8A1UnormSrgb
1462            | Self::Etc2Rgba8Unorm
1463            | Self::Etc2Rgba8UnormSrgb
1464            | Self::EacR11Unorm
1465            | Self::EacR11Snorm
1466            | Self::EacRg11Unorm
1467            | Self::EacRg11Snorm
1468            | Self::Astc { .. } => None,
1469        }
1470    }
1471
1472    /// Returns the number of components this format has.
1473    #[must_use]
1474    pub fn components(&self) -> u8 {
1475        self.components_with_aspect(TextureAspect::All)
1476    }
1477
1478    /// Returns the number of components this format has taking into account the `aspect`.
1479    ///
1480    /// The `aspect` is only relevant for combined depth-stencil formats and multi-planar formats.
1481    #[must_use]
1482    pub fn components_with_aspect(&self, aspect: TextureAspect) -> u8 {
1483        match *self {
1484            Self::R8Unorm
1485            | Self::R8Snorm
1486            | Self::R8Uint
1487            | Self::R8Sint
1488            | Self::R16Unorm
1489            | Self::R16Snorm
1490            | Self::R16Uint
1491            | Self::R16Sint
1492            | Self::R16Float
1493            | Self::R32Uint
1494            | Self::R32Sint
1495            | Self::R32Float
1496            | Self::R64Uint => 1,
1497
1498            Self::Rg8Unorm
1499            | Self::Rg8Snorm
1500            | Self::Rg8Uint
1501            | Self::Rg8Sint
1502            | Self::Rg16Unorm
1503            | Self::Rg16Snorm
1504            | Self::Rg16Uint
1505            | Self::Rg16Sint
1506            | Self::Rg16Float
1507            | Self::Rg32Uint
1508            | Self::Rg32Sint
1509            | Self::Rg32Float => 2,
1510
1511            Self::Rgba8Unorm
1512            | Self::Rgba8UnormSrgb
1513            | Self::Rgba8Snorm
1514            | Self::Rgba8Uint
1515            | Self::Rgba8Sint
1516            | Self::Bgra8Unorm
1517            | Self::Bgra8UnormSrgb
1518            | Self::Rgba16Unorm
1519            | Self::Rgba16Snorm
1520            | Self::Rgba16Uint
1521            | Self::Rgba16Sint
1522            | Self::Rgba16Float
1523            | Self::Rgba32Uint
1524            | Self::Rgba32Sint
1525            | Self::Rgba32Float => 4,
1526
1527            Self::Rgb9e5Ufloat | Self::Rg11b10Ufloat => 3,
1528            Self::Rgb10a2Uint | Self::Rgb10a2Unorm => 4,
1529
1530            Self::Stencil8 | Self::Depth16Unorm | Self::Depth24Plus | Self::Depth32Float => 1,
1531
1532            Self::Depth24PlusStencil8 | Self::Depth32FloatStencil8 => match aspect {
1533                TextureAspect::DepthOnly | TextureAspect::StencilOnly => 1,
1534                _ => 2,
1535            },
1536
1537            Self::NV12 | Self::P010 => match aspect {
1538                TextureAspect::Plane0 => 1,
1539                TextureAspect::Plane1 => 2,
1540                _ => 3,
1541            },
1542
1543            Self::Bc4RUnorm | Self::Bc4RSnorm => 1,
1544            Self::Bc5RgUnorm | Self::Bc5RgSnorm => 2,
1545            Self::Bc6hRgbUfloat | Self::Bc6hRgbFloat => 3,
1546            Self::Bc1RgbaUnorm
1547            | Self::Bc1RgbaUnormSrgb
1548            | Self::Bc2RgbaUnorm
1549            | Self::Bc2RgbaUnormSrgb
1550            | Self::Bc3RgbaUnorm
1551            | Self::Bc3RgbaUnormSrgb
1552            | Self::Bc7RgbaUnorm
1553            | Self::Bc7RgbaUnormSrgb => 4,
1554
1555            Self::EacR11Unorm | Self::EacR11Snorm => 1,
1556            Self::EacRg11Unorm | Self::EacRg11Snorm => 2,
1557            Self::Etc2Rgb8Unorm | Self::Etc2Rgb8UnormSrgb => 3,
1558            Self::Etc2Rgb8A1Unorm
1559            | Self::Etc2Rgb8A1UnormSrgb
1560            | Self::Etc2Rgba8Unorm
1561            | Self::Etc2Rgba8UnormSrgb => 4,
1562
1563            Self::Astc { .. } => 4,
1564        }
1565    }
1566
1567    /// Strips the `Srgb` suffix from the given texture format.
1568    #[must_use]
1569    pub fn remove_srgb_suffix(&self) -> TextureFormat {
1570        match *self {
1571            Self::Rgba8UnormSrgb => Self::Rgba8Unorm,
1572            Self::Bgra8UnormSrgb => Self::Bgra8Unorm,
1573            Self::Bc1RgbaUnormSrgb => Self::Bc1RgbaUnorm,
1574            Self::Bc2RgbaUnormSrgb => Self::Bc2RgbaUnorm,
1575            Self::Bc3RgbaUnormSrgb => Self::Bc3RgbaUnorm,
1576            Self::Bc7RgbaUnormSrgb => Self::Bc7RgbaUnorm,
1577            Self::Etc2Rgb8UnormSrgb => Self::Etc2Rgb8Unorm,
1578            Self::Etc2Rgb8A1UnormSrgb => Self::Etc2Rgb8A1Unorm,
1579            Self::Etc2Rgba8UnormSrgb => Self::Etc2Rgba8Unorm,
1580            Self::Astc {
1581                block,
1582                channel: AstcChannel::UnormSrgb,
1583            } => Self::Astc {
1584                block,
1585                channel: AstcChannel::Unorm,
1586            },
1587            _ => *self,
1588        }
1589    }
1590
1591    /// Adds an `Srgb` suffix to the given texture format, if the format supports it.
1592    #[must_use]
1593    pub fn add_srgb_suffix(&self) -> TextureFormat {
1594        match *self {
1595            Self::Rgba8Unorm => Self::Rgba8UnormSrgb,
1596            Self::Bgra8Unorm => Self::Bgra8UnormSrgb,
1597            Self::Bc1RgbaUnorm => Self::Bc1RgbaUnormSrgb,
1598            Self::Bc2RgbaUnorm => Self::Bc2RgbaUnormSrgb,
1599            Self::Bc3RgbaUnorm => Self::Bc3RgbaUnormSrgb,
1600            Self::Bc7RgbaUnorm => Self::Bc7RgbaUnormSrgb,
1601            Self::Etc2Rgb8Unorm => Self::Etc2Rgb8UnormSrgb,
1602            Self::Etc2Rgb8A1Unorm => Self::Etc2Rgb8A1UnormSrgb,
1603            Self::Etc2Rgba8Unorm => Self::Etc2Rgba8UnormSrgb,
1604            Self::Astc {
1605                block,
1606                channel: AstcChannel::Unorm,
1607            } => Self::Astc {
1608                block,
1609                channel: AstcChannel::UnormSrgb,
1610            },
1611            _ => *self,
1612        }
1613    }
1614
1615    /// Returns `true` for srgb formats.
1616    #[must_use]
1617    pub fn is_srgb(&self) -> bool {
1618        *self != self.remove_srgb_suffix()
1619    }
1620
1621    /// Returns the theoretical memory footprint of a texture with the given format and dimensions.
1622    ///
1623    /// Actual memory usage may greatly exceed this value due to alignment and padding.
1624    #[must_use]
1625    pub fn theoretical_memory_footprint(&self, size: crate::Extent3d) -> u64 {
1626        let (block_width, block_height) = self.block_dimensions();
1627
1628        let block_size = self.block_copy_size(None);
1629
1630        let approximate_block_size = match block_size {
1631            Some(size) => size,
1632            None => match self {
1633                // One f16 per pixel
1634                Self::Depth16Unorm => 2,
1635                // One u24 per pixel, padded to 4 bytes
1636                Self::Depth24Plus => 4,
1637                // One u24 per pixel, plus one u8 per pixel
1638                Self::Depth24PlusStencil8 => 4,
1639                // One f32 per pixel
1640                Self::Depth32Float => 4,
1641                // One f32 per pixel, plus one u8 per pixel, with 3 bytes intermediary padding
1642                Self::Depth32FloatStencil8 => 8,
1643                // One u8 per pixel
1644                Self::Stencil8 => 1,
1645                // Two chroma bytes per block, one luma byte per block
1646                Self::NV12 => 3,
1647                // Two chroma u16s and one luma u16 per block
1648                Self::P010 => 6,
1649                f => {
1650                    unimplemented!("Memory footprint for format {f:?} is not implemented");
1651                }
1652            },
1653        };
1654
1655        let width_blocks = size.width.div_ceil(block_width) as u64;
1656        let height_blocks = size.height.div_ceil(block_height) as u64;
1657
1658        let total_blocks = width_blocks * height_blocks * size.depth_or_array_layers as u64;
1659
1660        total_blocks * approximate_block_size as u64
1661    }
1662}
1663
1664#[cfg(any(feature = "serde", test))]
1665impl<'de> Deserialize<'de> for TextureFormat {
1666    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1667    where
1668        D: serde::Deserializer<'de>,
1669    {
1670        use serde::de::{self, Error, Unexpected};
1671
1672        struct TextureFormatVisitor;
1673
1674        impl de::Visitor<'_> for TextureFormatVisitor {
1675            type Value = TextureFormat;
1676
1677            fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
1678                formatter.write_str("a valid texture format")
1679            }
1680
1681            fn visit_str<E: Error>(self, s: &str) -> Result<Self::Value, E> {
1682                let format = match s {
1683                    "r8unorm" => TextureFormat::R8Unorm,
1684                    "r8snorm" => TextureFormat::R8Snorm,
1685                    "r8uint" => TextureFormat::R8Uint,
1686                    "r8sint" => TextureFormat::R8Sint,
1687                    "r16uint" => TextureFormat::R16Uint,
1688                    "r16sint" => TextureFormat::R16Sint,
1689                    "r16unorm" => TextureFormat::R16Unorm,
1690                    "r16snorm" => TextureFormat::R16Snorm,
1691                    "r16float" => TextureFormat::R16Float,
1692                    "rg8unorm" => TextureFormat::Rg8Unorm,
1693                    "rg8snorm" => TextureFormat::Rg8Snorm,
1694                    "rg8uint" => TextureFormat::Rg8Uint,
1695                    "rg8sint" => TextureFormat::Rg8Sint,
1696                    "r32uint" => TextureFormat::R32Uint,
1697                    "r32sint" => TextureFormat::R32Sint,
1698                    "r32float" => TextureFormat::R32Float,
1699                    "rg16uint" => TextureFormat::Rg16Uint,
1700                    "rg16sint" => TextureFormat::Rg16Sint,
1701                    "rg16unorm" => TextureFormat::Rg16Unorm,
1702                    "rg16snorm" => TextureFormat::Rg16Snorm,
1703                    "rg16float" => TextureFormat::Rg16Float,
1704                    "rgba8unorm" => TextureFormat::Rgba8Unorm,
1705                    "rgba8unorm-srgb" => TextureFormat::Rgba8UnormSrgb,
1706                    "rgba8snorm" => TextureFormat::Rgba8Snorm,
1707                    "rgba8uint" => TextureFormat::Rgba8Uint,
1708                    "rgba8sint" => TextureFormat::Rgba8Sint,
1709                    "bgra8unorm" => TextureFormat::Bgra8Unorm,
1710                    "bgra8unorm-srgb" => TextureFormat::Bgra8UnormSrgb,
1711                    "rgb10a2uint" => TextureFormat::Rgb10a2Uint,
1712                    "rgb10a2unorm" => TextureFormat::Rgb10a2Unorm,
1713                    "rg11b10ufloat" => TextureFormat::Rg11b10Ufloat,
1714                    "r64uint" => TextureFormat::R64Uint,
1715                    "rg32uint" => TextureFormat::Rg32Uint,
1716                    "rg32sint" => TextureFormat::Rg32Sint,
1717                    "rg32float" => TextureFormat::Rg32Float,
1718                    "rgba16uint" => TextureFormat::Rgba16Uint,
1719                    "rgba16sint" => TextureFormat::Rgba16Sint,
1720                    "rgba16unorm" => TextureFormat::Rgba16Unorm,
1721                    "rgba16snorm" => TextureFormat::Rgba16Snorm,
1722                    "rgba16float" => TextureFormat::Rgba16Float,
1723                    "rgba32uint" => TextureFormat::Rgba32Uint,
1724                    "rgba32sint" => TextureFormat::Rgba32Sint,
1725                    "rgba32float" => TextureFormat::Rgba32Float,
1726                    "stencil8" => TextureFormat::Stencil8,
1727                    "depth32float" => TextureFormat::Depth32Float,
1728                    "depth32float-stencil8" => TextureFormat::Depth32FloatStencil8,
1729                    "depth16unorm" => TextureFormat::Depth16Unorm,
1730                    "depth24plus" => TextureFormat::Depth24Plus,
1731                    "depth24plus-stencil8" => TextureFormat::Depth24PlusStencil8,
1732                    "nv12" => TextureFormat::NV12,
1733                    "p010" => TextureFormat::P010,
1734                    "rgb9e5ufloat" => TextureFormat::Rgb9e5Ufloat,
1735                    "bc1-rgba-unorm" => TextureFormat::Bc1RgbaUnorm,
1736                    "bc1-rgba-unorm-srgb" => TextureFormat::Bc1RgbaUnormSrgb,
1737                    "bc2-rgba-unorm" => TextureFormat::Bc2RgbaUnorm,
1738                    "bc2-rgba-unorm-srgb" => TextureFormat::Bc2RgbaUnormSrgb,
1739                    "bc3-rgba-unorm" => TextureFormat::Bc3RgbaUnorm,
1740                    "bc3-rgba-unorm-srgb" => TextureFormat::Bc3RgbaUnormSrgb,
1741                    "bc4-r-unorm" => TextureFormat::Bc4RUnorm,
1742                    "bc4-r-snorm" => TextureFormat::Bc4RSnorm,
1743                    "bc5-rg-unorm" => TextureFormat::Bc5RgUnorm,
1744                    "bc5-rg-snorm" => TextureFormat::Bc5RgSnorm,
1745                    "bc6h-rgb-ufloat" => TextureFormat::Bc6hRgbUfloat,
1746                    "bc6h-rgb-float" => TextureFormat::Bc6hRgbFloat,
1747                    "bc7-rgba-unorm" => TextureFormat::Bc7RgbaUnorm,
1748                    "bc7-rgba-unorm-srgb" => TextureFormat::Bc7RgbaUnormSrgb,
1749                    "etc2-rgb8unorm" => TextureFormat::Etc2Rgb8Unorm,
1750                    "etc2-rgb8unorm-srgb" => TextureFormat::Etc2Rgb8UnormSrgb,
1751                    "etc2-rgb8a1unorm" => TextureFormat::Etc2Rgb8A1Unorm,
1752                    "etc2-rgb8a1unorm-srgb" => TextureFormat::Etc2Rgb8A1UnormSrgb,
1753                    "etc2-rgba8unorm" => TextureFormat::Etc2Rgba8Unorm,
1754                    "etc2-rgba8unorm-srgb" => TextureFormat::Etc2Rgba8UnormSrgb,
1755                    "eac-r11unorm" => TextureFormat::EacR11Unorm,
1756                    "eac-r11snorm" => TextureFormat::EacR11Snorm,
1757                    "eac-rg11unorm" => TextureFormat::EacRg11Unorm,
1758                    "eac-rg11snorm" => TextureFormat::EacRg11Snorm,
1759                    other => {
1760                        if let Some(parts) = other.strip_prefix("astc-") {
1761                            let (block, channel) = parts
1762                                .split_once('-')
1763                                .ok_or_else(|| E::invalid_value(Unexpected::Str(s), &self))?;
1764
1765                            let block = match block {
1766                                "4x4" => AstcBlock::B4x4,
1767                                "5x4" => AstcBlock::B5x4,
1768                                "5x5" => AstcBlock::B5x5,
1769                                "6x5" => AstcBlock::B6x5,
1770                                "6x6" => AstcBlock::B6x6,
1771                                "8x5" => AstcBlock::B8x5,
1772                                "8x6" => AstcBlock::B8x6,
1773                                "8x8" => AstcBlock::B8x8,
1774                                "10x5" => AstcBlock::B10x5,
1775                                "10x6" => AstcBlock::B10x6,
1776                                "10x8" => AstcBlock::B10x8,
1777                                "10x10" => AstcBlock::B10x10,
1778                                "12x10" => AstcBlock::B12x10,
1779                                "12x12" => AstcBlock::B12x12,
1780                                _ => return Err(E::invalid_value(Unexpected::Str(s), &self)),
1781                            };
1782
1783                            let channel = match channel {
1784                                "unorm" => AstcChannel::Unorm,
1785                                "unorm-srgb" => AstcChannel::UnormSrgb,
1786                                "hdr" => AstcChannel::Hdr,
1787                                _ => return Err(E::invalid_value(Unexpected::Str(s), &self)),
1788                            };
1789
1790                            TextureFormat::Astc { block, channel }
1791                        } else {
1792                            return Err(E::invalid_value(Unexpected::Str(s), &self));
1793                        }
1794                    }
1795                };
1796
1797                Ok(format)
1798            }
1799        }
1800
1801        deserializer.deserialize_str(TextureFormatVisitor)
1802    }
1803}
1804
1805#[cfg(any(feature = "serde", test))]
1806impl Serialize for TextureFormat {
1807    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1808    where
1809        S: serde::Serializer,
1810    {
1811        let s: alloc::string::String;
1812        let name = match *self {
1813            TextureFormat::R8Unorm => "r8unorm",
1814            TextureFormat::R8Snorm => "r8snorm",
1815            TextureFormat::R8Uint => "r8uint",
1816            TextureFormat::R8Sint => "r8sint",
1817            TextureFormat::R16Uint => "r16uint",
1818            TextureFormat::R16Sint => "r16sint",
1819            TextureFormat::R16Unorm => "r16unorm",
1820            TextureFormat::R16Snorm => "r16snorm",
1821            TextureFormat::R16Float => "r16float",
1822            TextureFormat::Rg8Unorm => "rg8unorm",
1823            TextureFormat::Rg8Snorm => "rg8snorm",
1824            TextureFormat::Rg8Uint => "rg8uint",
1825            TextureFormat::Rg8Sint => "rg8sint",
1826            TextureFormat::R32Uint => "r32uint",
1827            TextureFormat::R32Sint => "r32sint",
1828            TextureFormat::R32Float => "r32float",
1829            TextureFormat::Rg16Uint => "rg16uint",
1830            TextureFormat::Rg16Sint => "rg16sint",
1831            TextureFormat::Rg16Unorm => "rg16unorm",
1832            TextureFormat::Rg16Snorm => "rg16snorm",
1833            TextureFormat::Rg16Float => "rg16float",
1834            TextureFormat::Rgba8Unorm => "rgba8unorm",
1835            TextureFormat::Rgba8UnormSrgb => "rgba8unorm-srgb",
1836            TextureFormat::Rgba8Snorm => "rgba8snorm",
1837            TextureFormat::Rgba8Uint => "rgba8uint",
1838            TextureFormat::Rgba8Sint => "rgba8sint",
1839            TextureFormat::Bgra8Unorm => "bgra8unorm",
1840            TextureFormat::Bgra8UnormSrgb => "bgra8unorm-srgb",
1841            TextureFormat::Rgb10a2Uint => "rgb10a2uint",
1842            TextureFormat::Rgb10a2Unorm => "rgb10a2unorm",
1843            TextureFormat::Rg11b10Ufloat => "rg11b10ufloat",
1844            TextureFormat::R64Uint => "r64uint",
1845            TextureFormat::Rg32Uint => "rg32uint",
1846            TextureFormat::Rg32Sint => "rg32sint",
1847            TextureFormat::Rg32Float => "rg32float",
1848            TextureFormat::Rgba16Uint => "rgba16uint",
1849            TextureFormat::Rgba16Sint => "rgba16sint",
1850            TextureFormat::Rgba16Unorm => "rgba16unorm",
1851            TextureFormat::Rgba16Snorm => "rgba16snorm",
1852            TextureFormat::Rgba16Float => "rgba16float",
1853            TextureFormat::Rgba32Uint => "rgba32uint",
1854            TextureFormat::Rgba32Sint => "rgba32sint",
1855            TextureFormat::Rgba32Float => "rgba32float",
1856            TextureFormat::Stencil8 => "stencil8",
1857            TextureFormat::Depth32Float => "depth32float",
1858            TextureFormat::Depth16Unorm => "depth16unorm",
1859            TextureFormat::Depth32FloatStencil8 => "depth32float-stencil8",
1860            TextureFormat::Depth24Plus => "depth24plus",
1861            TextureFormat::Depth24PlusStencil8 => "depth24plus-stencil8",
1862            TextureFormat::NV12 => "nv12",
1863            TextureFormat::P010 => "p010",
1864            TextureFormat::Rgb9e5Ufloat => "rgb9e5ufloat",
1865            TextureFormat::Bc1RgbaUnorm => "bc1-rgba-unorm",
1866            TextureFormat::Bc1RgbaUnormSrgb => "bc1-rgba-unorm-srgb",
1867            TextureFormat::Bc2RgbaUnorm => "bc2-rgba-unorm",
1868            TextureFormat::Bc2RgbaUnormSrgb => "bc2-rgba-unorm-srgb",
1869            TextureFormat::Bc3RgbaUnorm => "bc3-rgba-unorm",
1870            TextureFormat::Bc3RgbaUnormSrgb => "bc3-rgba-unorm-srgb",
1871            TextureFormat::Bc4RUnorm => "bc4-r-unorm",
1872            TextureFormat::Bc4RSnorm => "bc4-r-snorm",
1873            TextureFormat::Bc5RgUnorm => "bc5-rg-unorm",
1874            TextureFormat::Bc5RgSnorm => "bc5-rg-snorm",
1875            TextureFormat::Bc6hRgbUfloat => "bc6h-rgb-ufloat",
1876            TextureFormat::Bc6hRgbFloat => "bc6h-rgb-float",
1877            TextureFormat::Bc7RgbaUnorm => "bc7-rgba-unorm",
1878            TextureFormat::Bc7RgbaUnormSrgb => "bc7-rgba-unorm-srgb",
1879            TextureFormat::Etc2Rgb8Unorm => "etc2-rgb8unorm",
1880            TextureFormat::Etc2Rgb8UnormSrgb => "etc2-rgb8unorm-srgb",
1881            TextureFormat::Etc2Rgb8A1Unorm => "etc2-rgb8a1unorm",
1882            TextureFormat::Etc2Rgb8A1UnormSrgb => "etc2-rgb8a1unorm-srgb",
1883            TextureFormat::Etc2Rgba8Unorm => "etc2-rgba8unorm",
1884            TextureFormat::Etc2Rgba8UnormSrgb => "etc2-rgba8unorm-srgb",
1885            TextureFormat::EacR11Unorm => "eac-r11unorm",
1886            TextureFormat::EacR11Snorm => "eac-r11snorm",
1887            TextureFormat::EacRg11Unorm => "eac-rg11unorm",
1888            TextureFormat::EacRg11Snorm => "eac-rg11snorm",
1889            TextureFormat::Astc { block, channel } => {
1890                let block = match block {
1891                    AstcBlock::B4x4 => "4x4",
1892                    AstcBlock::B5x4 => "5x4",
1893                    AstcBlock::B5x5 => "5x5",
1894                    AstcBlock::B6x5 => "6x5",
1895                    AstcBlock::B6x6 => "6x6",
1896                    AstcBlock::B8x5 => "8x5",
1897                    AstcBlock::B8x6 => "8x6",
1898                    AstcBlock::B8x8 => "8x8",
1899                    AstcBlock::B10x5 => "10x5",
1900                    AstcBlock::B10x6 => "10x6",
1901                    AstcBlock::B10x8 => "10x8",
1902                    AstcBlock::B10x10 => "10x10",
1903                    AstcBlock::B12x10 => "12x10",
1904                    AstcBlock::B12x12 => "12x12",
1905                };
1906
1907                let channel = match channel {
1908                    AstcChannel::Unorm => "unorm",
1909                    AstcChannel::UnormSrgb => "unorm-srgb",
1910                    AstcChannel::Hdr => "hdr",
1911                };
1912
1913                s = alloc::format!("astc-{block}-{channel}");
1914                &s
1915            }
1916        };
1917        serializer.serialize_str(name)
1918    }
1919}
1920
1921bitflags::bitflags! {
1922    /// Feature flags for a texture format.
1923    #[repr(transparent)]
1924    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1925    #[cfg_attr(feature = "serde", serde(transparent))]
1926    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1927    pub struct TextureFormatFeatureFlags: u32 {
1928        /// If not present, the texture can't be sampled with a filtering sampler.
1929        /// This may overwrite TextureSampleType::Float.filterable
1930        const FILTERABLE = 1 << 0;
1931        /// Allows [`TextureDescriptor::sample_count`] to be `2`.
1932        const MULTISAMPLE_X2 = 1 << 1;
1933        /// Allows [`TextureDescriptor::sample_count`] to be `4`.
1934        const MULTISAMPLE_X4 = 1 << 2 ;
1935        /// Allows [`TextureDescriptor::sample_count`] to be `8`.
1936        const MULTISAMPLE_X8 = 1 << 3 ;
1937        /// Allows [`TextureDescriptor::sample_count`] to be `16`.
1938        const MULTISAMPLE_X16 = 1 << 4;
1939        /// Allows a texture of this format to back a view passed as `resolve_target`
1940        /// to a render pass for an automatic driver-implemented resolve.
1941        const MULTISAMPLE_RESOLVE = 1 << 5;
1942        /// When used as a STORAGE texture, then a texture with this format can be bound with
1943        /// [`StorageTextureAccess::ReadOnly`].
1944        const STORAGE_READ_ONLY = 1 << 6;
1945        /// When used as a STORAGE texture, then a texture with this format can be bound with
1946        /// [`StorageTextureAccess::WriteOnly`].
1947        const STORAGE_WRITE_ONLY = 1 << 7;
1948        /// When used as a STORAGE texture, then a texture with this format can be bound with
1949        /// [`StorageTextureAccess::ReadWrite`].
1950        const STORAGE_READ_WRITE = 1 << 8;
1951        /// When used as a STORAGE texture, then a texture with this format can be bound with
1952        /// [`StorageTextureAccess::Atomic`].
1953        const STORAGE_ATOMIC = 1 << 9;
1954        /// If not present, the texture can't be blended into the render target.
1955        const BLENDABLE = 1 << 10;
1956    }
1957}
1958
1959impl TextureFormatFeatureFlags {
1960    /// Sample count supported by a given texture format.
1961    ///
1962    /// returns `true` if `count` is a supported sample count.
1963    #[must_use]
1964    pub fn sample_count_supported(&self, count: u32) -> bool {
1965        use TextureFormatFeatureFlags as tfsc;
1966
1967        match count {
1968            1 => true,
1969            2 => self.contains(tfsc::MULTISAMPLE_X2),
1970            4 => self.contains(tfsc::MULTISAMPLE_X4),
1971            8 => self.contains(tfsc::MULTISAMPLE_X8),
1972            16 => self.contains(tfsc::MULTISAMPLE_X16),
1973            _ => false,
1974        }
1975    }
1976
1977    /// A `Vec` of supported sample counts.
1978    #[must_use]
1979    pub fn supported_sample_counts(&self) -> Vec<u32> {
1980        let all_possible_sample_counts: [u32; 5] = [1, 2, 4, 8, 16];
1981        all_possible_sample_counts
1982            .into_iter()
1983            .filter(|&sc| self.sample_count_supported(sc))
1984            .collect()
1985    }
1986}
1987
1988/// Features supported by a given texture format
1989///
1990/// Features are defined by WebGPU specification unless [`Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES`] is enabled.
1991#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
1992#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1993pub struct TextureFormatFeatures {
1994    /// Valid bits for `TextureDescriptor::Usage` provided for format creation.
1995    pub allowed_usages: TextureUsages,
1996    /// Additional property flags for the format.
1997    pub flags: TextureFormatFeatureFlags,
1998}
1999
2000#[cfg(test)]
2001mod tests {
2002    use super::*;
2003
2004    #[test]
2005    fn texture_format_serialize() {
2006        use alloc::string::ToString;
2007
2008        assert_eq!(
2009            serde_json::to_string(&TextureFormat::R8Unorm).unwrap(),
2010            "\"r8unorm\"".to_string()
2011        );
2012        assert_eq!(
2013            serde_json::to_string(&TextureFormat::R8Snorm).unwrap(),
2014            "\"r8snorm\"".to_string()
2015        );
2016        assert_eq!(
2017            serde_json::to_string(&TextureFormat::R8Uint).unwrap(),
2018            "\"r8uint\"".to_string()
2019        );
2020        assert_eq!(
2021            serde_json::to_string(&TextureFormat::R8Sint).unwrap(),
2022            "\"r8sint\"".to_string()
2023        );
2024        assert_eq!(
2025            serde_json::to_string(&TextureFormat::R16Uint).unwrap(),
2026            "\"r16uint\"".to_string()
2027        );
2028        assert_eq!(
2029            serde_json::to_string(&TextureFormat::R16Sint).unwrap(),
2030            "\"r16sint\"".to_string()
2031        );
2032        assert_eq!(
2033            serde_json::to_string(&TextureFormat::R16Unorm).unwrap(),
2034            "\"r16unorm\"".to_string()
2035        );
2036        assert_eq!(
2037            serde_json::to_string(&TextureFormat::R16Snorm).unwrap(),
2038            "\"r16snorm\"".to_string()
2039        );
2040        assert_eq!(
2041            serde_json::to_string(&TextureFormat::R16Float).unwrap(),
2042            "\"r16float\"".to_string()
2043        );
2044        assert_eq!(
2045            serde_json::to_string(&TextureFormat::Rg8Unorm).unwrap(),
2046            "\"rg8unorm\"".to_string()
2047        );
2048        assert_eq!(
2049            serde_json::to_string(&TextureFormat::Rg8Snorm).unwrap(),
2050            "\"rg8snorm\"".to_string()
2051        );
2052        assert_eq!(
2053            serde_json::to_string(&TextureFormat::Rg8Uint).unwrap(),
2054            "\"rg8uint\"".to_string()
2055        );
2056        assert_eq!(
2057            serde_json::to_string(&TextureFormat::Rg8Sint).unwrap(),
2058            "\"rg8sint\"".to_string()
2059        );
2060        assert_eq!(
2061            serde_json::to_string(&TextureFormat::R32Uint).unwrap(),
2062            "\"r32uint\"".to_string()
2063        );
2064        assert_eq!(
2065            serde_json::to_string(&TextureFormat::R32Sint).unwrap(),
2066            "\"r32sint\"".to_string()
2067        );
2068        assert_eq!(
2069            serde_json::to_string(&TextureFormat::R32Float).unwrap(),
2070            "\"r32float\"".to_string()
2071        );
2072        assert_eq!(
2073            serde_json::to_string(&TextureFormat::Rg16Uint).unwrap(),
2074            "\"rg16uint\"".to_string()
2075        );
2076        assert_eq!(
2077            serde_json::to_string(&TextureFormat::Rg16Sint).unwrap(),
2078            "\"rg16sint\"".to_string()
2079        );
2080        assert_eq!(
2081            serde_json::to_string(&TextureFormat::Rg16Unorm).unwrap(),
2082            "\"rg16unorm\"".to_string()
2083        );
2084        assert_eq!(
2085            serde_json::to_string(&TextureFormat::Rg16Snorm).unwrap(),
2086            "\"rg16snorm\"".to_string()
2087        );
2088        assert_eq!(
2089            serde_json::to_string(&TextureFormat::Rg16Float).unwrap(),
2090            "\"rg16float\"".to_string()
2091        );
2092        assert_eq!(
2093            serde_json::to_string(&TextureFormat::Rgba8Unorm).unwrap(),
2094            "\"rgba8unorm\"".to_string()
2095        );
2096        assert_eq!(
2097            serde_json::to_string(&TextureFormat::Rgba8UnormSrgb).unwrap(),
2098            "\"rgba8unorm-srgb\"".to_string()
2099        );
2100        assert_eq!(
2101            serde_json::to_string(&TextureFormat::Rgba8Snorm).unwrap(),
2102            "\"rgba8snorm\"".to_string()
2103        );
2104        assert_eq!(
2105            serde_json::to_string(&TextureFormat::Rgba8Uint).unwrap(),
2106            "\"rgba8uint\"".to_string()
2107        );
2108        assert_eq!(
2109            serde_json::to_string(&TextureFormat::Rgba8Sint).unwrap(),
2110            "\"rgba8sint\"".to_string()
2111        );
2112        assert_eq!(
2113            serde_json::to_string(&TextureFormat::Bgra8Unorm).unwrap(),
2114            "\"bgra8unorm\"".to_string()
2115        );
2116        assert_eq!(
2117            serde_json::to_string(&TextureFormat::Bgra8UnormSrgb).unwrap(),
2118            "\"bgra8unorm-srgb\"".to_string()
2119        );
2120        assert_eq!(
2121            serde_json::to_string(&TextureFormat::Rgb10a2Uint).unwrap(),
2122            "\"rgb10a2uint\"".to_string()
2123        );
2124        assert_eq!(
2125            serde_json::to_string(&TextureFormat::Rgb10a2Unorm).unwrap(),
2126            "\"rgb10a2unorm\"".to_string()
2127        );
2128        assert_eq!(
2129            serde_json::to_string(&TextureFormat::Rg11b10Ufloat).unwrap(),
2130            "\"rg11b10ufloat\"".to_string()
2131        );
2132        assert_eq!(
2133            serde_json::to_string(&TextureFormat::R64Uint).unwrap(),
2134            "\"r64uint\"".to_string()
2135        );
2136        assert_eq!(
2137            serde_json::to_string(&TextureFormat::Rg32Uint).unwrap(),
2138            "\"rg32uint\"".to_string()
2139        );
2140        assert_eq!(
2141            serde_json::to_string(&TextureFormat::Rg32Sint).unwrap(),
2142            "\"rg32sint\"".to_string()
2143        );
2144        assert_eq!(
2145            serde_json::to_string(&TextureFormat::Rg32Float).unwrap(),
2146            "\"rg32float\"".to_string()
2147        );
2148        assert_eq!(
2149            serde_json::to_string(&TextureFormat::Rgba16Uint).unwrap(),
2150            "\"rgba16uint\"".to_string()
2151        );
2152        assert_eq!(
2153            serde_json::to_string(&TextureFormat::Rgba16Sint).unwrap(),
2154            "\"rgba16sint\"".to_string()
2155        );
2156        assert_eq!(
2157            serde_json::to_string(&TextureFormat::Rgba16Unorm).unwrap(),
2158            "\"rgba16unorm\"".to_string()
2159        );
2160        assert_eq!(
2161            serde_json::to_string(&TextureFormat::Rgba16Snorm).unwrap(),
2162            "\"rgba16snorm\"".to_string()
2163        );
2164        assert_eq!(
2165            serde_json::to_string(&TextureFormat::Rgba16Float).unwrap(),
2166            "\"rgba16float\"".to_string()
2167        );
2168        assert_eq!(
2169            serde_json::to_string(&TextureFormat::Rgba32Uint).unwrap(),
2170            "\"rgba32uint\"".to_string()
2171        );
2172        assert_eq!(
2173            serde_json::to_string(&TextureFormat::Rgba32Sint).unwrap(),
2174            "\"rgba32sint\"".to_string()
2175        );
2176        assert_eq!(
2177            serde_json::to_string(&TextureFormat::Rgba32Float).unwrap(),
2178            "\"rgba32float\"".to_string()
2179        );
2180        assert_eq!(
2181            serde_json::to_string(&TextureFormat::Stencil8).unwrap(),
2182            "\"stencil8\"".to_string()
2183        );
2184        assert_eq!(
2185            serde_json::to_string(&TextureFormat::Depth32Float).unwrap(),
2186            "\"depth32float\"".to_string()
2187        );
2188        assert_eq!(
2189            serde_json::to_string(&TextureFormat::Depth16Unorm).unwrap(),
2190            "\"depth16unorm\"".to_string()
2191        );
2192        assert_eq!(
2193            serde_json::to_string(&TextureFormat::Depth32FloatStencil8).unwrap(),
2194            "\"depth32float-stencil8\"".to_string()
2195        );
2196        assert_eq!(
2197            serde_json::to_string(&TextureFormat::Depth24Plus).unwrap(),
2198            "\"depth24plus\"".to_string()
2199        );
2200        assert_eq!(
2201            serde_json::to_string(&TextureFormat::Depth24PlusStencil8).unwrap(),
2202            "\"depth24plus-stencil8\"".to_string()
2203        );
2204        assert_eq!(
2205            serde_json::to_string(&TextureFormat::Rgb9e5Ufloat).unwrap(),
2206            "\"rgb9e5ufloat\"".to_string()
2207        );
2208        assert_eq!(
2209            serde_json::to_string(&TextureFormat::Bc1RgbaUnorm).unwrap(),
2210            "\"bc1-rgba-unorm\"".to_string()
2211        );
2212        assert_eq!(
2213            serde_json::to_string(&TextureFormat::Bc1RgbaUnormSrgb).unwrap(),
2214            "\"bc1-rgba-unorm-srgb\"".to_string()
2215        );
2216        assert_eq!(
2217            serde_json::to_string(&TextureFormat::Bc2RgbaUnorm).unwrap(),
2218            "\"bc2-rgba-unorm\"".to_string()
2219        );
2220        assert_eq!(
2221            serde_json::to_string(&TextureFormat::Bc2RgbaUnormSrgb).unwrap(),
2222            "\"bc2-rgba-unorm-srgb\"".to_string()
2223        );
2224        assert_eq!(
2225            serde_json::to_string(&TextureFormat::Bc3RgbaUnorm).unwrap(),
2226            "\"bc3-rgba-unorm\"".to_string()
2227        );
2228        assert_eq!(
2229            serde_json::to_string(&TextureFormat::Bc3RgbaUnormSrgb).unwrap(),
2230            "\"bc3-rgba-unorm-srgb\"".to_string()
2231        );
2232        assert_eq!(
2233            serde_json::to_string(&TextureFormat::Bc4RUnorm).unwrap(),
2234            "\"bc4-r-unorm\"".to_string()
2235        );
2236        assert_eq!(
2237            serde_json::to_string(&TextureFormat::Bc4RSnorm).unwrap(),
2238            "\"bc4-r-snorm\"".to_string()
2239        );
2240        assert_eq!(
2241            serde_json::to_string(&TextureFormat::Bc5RgUnorm).unwrap(),
2242            "\"bc5-rg-unorm\"".to_string()
2243        );
2244        assert_eq!(
2245            serde_json::to_string(&TextureFormat::Bc5RgSnorm).unwrap(),
2246            "\"bc5-rg-snorm\"".to_string()
2247        );
2248        assert_eq!(
2249            serde_json::to_string(&TextureFormat::Bc6hRgbUfloat).unwrap(),
2250            "\"bc6h-rgb-ufloat\"".to_string()
2251        );
2252        assert_eq!(
2253            serde_json::to_string(&TextureFormat::Bc6hRgbFloat).unwrap(),
2254            "\"bc6h-rgb-float\"".to_string()
2255        );
2256        assert_eq!(
2257            serde_json::to_string(&TextureFormat::Bc7RgbaUnorm).unwrap(),
2258            "\"bc7-rgba-unorm\"".to_string()
2259        );
2260        assert_eq!(
2261            serde_json::to_string(&TextureFormat::Bc7RgbaUnormSrgb).unwrap(),
2262            "\"bc7-rgba-unorm-srgb\"".to_string()
2263        );
2264        assert_eq!(
2265            serde_json::to_string(&TextureFormat::Etc2Rgb8Unorm).unwrap(),
2266            "\"etc2-rgb8unorm\"".to_string()
2267        );
2268        assert_eq!(
2269            serde_json::to_string(&TextureFormat::Etc2Rgb8UnormSrgb).unwrap(),
2270            "\"etc2-rgb8unorm-srgb\"".to_string()
2271        );
2272        assert_eq!(
2273            serde_json::to_string(&TextureFormat::Etc2Rgb8A1Unorm).unwrap(),
2274            "\"etc2-rgb8a1unorm\"".to_string()
2275        );
2276        assert_eq!(
2277            serde_json::to_string(&TextureFormat::Etc2Rgb8A1UnormSrgb).unwrap(),
2278            "\"etc2-rgb8a1unorm-srgb\"".to_string()
2279        );
2280        assert_eq!(
2281            serde_json::to_string(&TextureFormat::Etc2Rgba8Unorm).unwrap(),
2282            "\"etc2-rgba8unorm\"".to_string()
2283        );
2284        assert_eq!(
2285            serde_json::to_string(&TextureFormat::Etc2Rgba8UnormSrgb).unwrap(),
2286            "\"etc2-rgba8unorm-srgb\"".to_string()
2287        );
2288        assert_eq!(
2289            serde_json::to_string(&TextureFormat::EacR11Unorm).unwrap(),
2290            "\"eac-r11unorm\"".to_string()
2291        );
2292        assert_eq!(
2293            serde_json::to_string(&TextureFormat::EacR11Snorm).unwrap(),
2294            "\"eac-r11snorm\"".to_string()
2295        );
2296        assert_eq!(
2297            serde_json::to_string(&TextureFormat::EacRg11Unorm).unwrap(),
2298            "\"eac-rg11unorm\"".to_string()
2299        );
2300        assert_eq!(
2301            serde_json::to_string(&TextureFormat::EacRg11Snorm).unwrap(),
2302            "\"eac-rg11snorm\"".to_string()
2303        );
2304    }
2305
2306    #[test]
2307    fn texture_format_deserialize() {
2308        assert_eq!(
2309            serde_json::from_str::<TextureFormat>("\"r8unorm\"").unwrap(),
2310            TextureFormat::R8Unorm
2311        );
2312        assert_eq!(
2313            serde_json::from_str::<TextureFormat>("\"r8snorm\"").unwrap(),
2314            TextureFormat::R8Snorm
2315        );
2316        assert_eq!(
2317            serde_json::from_str::<TextureFormat>("\"r8uint\"").unwrap(),
2318            TextureFormat::R8Uint
2319        );
2320        assert_eq!(
2321            serde_json::from_str::<TextureFormat>("\"r8sint\"").unwrap(),
2322            TextureFormat::R8Sint
2323        );
2324        assert_eq!(
2325            serde_json::from_str::<TextureFormat>("\"r16uint\"").unwrap(),
2326            TextureFormat::R16Uint
2327        );
2328        assert_eq!(
2329            serde_json::from_str::<TextureFormat>("\"r16sint\"").unwrap(),
2330            TextureFormat::R16Sint
2331        );
2332        assert_eq!(
2333            serde_json::from_str::<TextureFormat>("\"r16unorm\"").unwrap(),
2334            TextureFormat::R16Unorm
2335        );
2336        assert_eq!(
2337            serde_json::from_str::<TextureFormat>("\"r16snorm\"").unwrap(),
2338            TextureFormat::R16Snorm
2339        );
2340        assert_eq!(
2341            serde_json::from_str::<TextureFormat>("\"r16float\"").unwrap(),
2342            TextureFormat::R16Float
2343        );
2344        assert_eq!(
2345            serde_json::from_str::<TextureFormat>("\"rg8unorm\"").unwrap(),
2346            TextureFormat::Rg8Unorm
2347        );
2348        assert_eq!(
2349            serde_json::from_str::<TextureFormat>("\"rg8snorm\"").unwrap(),
2350            TextureFormat::Rg8Snorm
2351        );
2352        assert_eq!(
2353            serde_json::from_str::<TextureFormat>("\"rg8uint\"").unwrap(),
2354            TextureFormat::Rg8Uint
2355        );
2356        assert_eq!(
2357            serde_json::from_str::<TextureFormat>("\"rg8sint\"").unwrap(),
2358            TextureFormat::Rg8Sint
2359        );
2360        assert_eq!(
2361            serde_json::from_str::<TextureFormat>("\"r32uint\"").unwrap(),
2362            TextureFormat::R32Uint
2363        );
2364        assert_eq!(
2365            serde_json::from_str::<TextureFormat>("\"r32sint\"").unwrap(),
2366            TextureFormat::R32Sint
2367        );
2368        assert_eq!(
2369            serde_json::from_str::<TextureFormat>("\"r32float\"").unwrap(),
2370            TextureFormat::R32Float
2371        );
2372        assert_eq!(
2373            serde_json::from_str::<TextureFormat>("\"rg16uint\"").unwrap(),
2374            TextureFormat::Rg16Uint
2375        );
2376        assert_eq!(
2377            serde_json::from_str::<TextureFormat>("\"rg16sint\"").unwrap(),
2378            TextureFormat::Rg16Sint
2379        );
2380        assert_eq!(
2381            serde_json::from_str::<TextureFormat>("\"rg16unorm\"").unwrap(),
2382            TextureFormat::Rg16Unorm
2383        );
2384        assert_eq!(
2385            serde_json::from_str::<TextureFormat>("\"rg16snorm\"").unwrap(),
2386            TextureFormat::Rg16Snorm
2387        );
2388        assert_eq!(
2389            serde_json::from_str::<TextureFormat>("\"rg16float\"").unwrap(),
2390            TextureFormat::Rg16Float
2391        );
2392        assert_eq!(
2393            serde_json::from_str::<TextureFormat>("\"rgba8unorm\"").unwrap(),
2394            TextureFormat::Rgba8Unorm
2395        );
2396        assert_eq!(
2397            serde_json::from_str::<TextureFormat>("\"rgba8unorm-srgb\"").unwrap(),
2398            TextureFormat::Rgba8UnormSrgb
2399        );
2400        assert_eq!(
2401            serde_json::from_str::<TextureFormat>("\"rgba8snorm\"").unwrap(),
2402            TextureFormat::Rgba8Snorm
2403        );
2404        assert_eq!(
2405            serde_json::from_str::<TextureFormat>("\"rgba8uint\"").unwrap(),
2406            TextureFormat::Rgba8Uint
2407        );
2408        assert_eq!(
2409            serde_json::from_str::<TextureFormat>("\"rgba8sint\"").unwrap(),
2410            TextureFormat::Rgba8Sint
2411        );
2412        assert_eq!(
2413            serde_json::from_str::<TextureFormat>("\"bgra8unorm\"").unwrap(),
2414            TextureFormat::Bgra8Unorm
2415        );
2416        assert_eq!(
2417            serde_json::from_str::<TextureFormat>("\"bgra8unorm-srgb\"").unwrap(),
2418            TextureFormat::Bgra8UnormSrgb
2419        );
2420        assert_eq!(
2421            serde_json::from_str::<TextureFormat>("\"rgb10a2uint\"").unwrap(),
2422            TextureFormat::Rgb10a2Uint
2423        );
2424        assert_eq!(
2425            serde_json::from_str::<TextureFormat>("\"rgb10a2unorm\"").unwrap(),
2426            TextureFormat::Rgb10a2Unorm
2427        );
2428        assert_eq!(
2429            serde_json::from_str::<TextureFormat>("\"rg11b10ufloat\"").unwrap(),
2430            TextureFormat::Rg11b10Ufloat
2431        );
2432        assert_eq!(
2433            serde_json::from_str::<TextureFormat>("\"r64uint\"").unwrap(),
2434            TextureFormat::R64Uint
2435        );
2436        assert_eq!(
2437            serde_json::from_str::<TextureFormat>("\"rg32uint\"").unwrap(),
2438            TextureFormat::Rg32Uint
2439        );
2440        assert_eq!(
2441            serde_json::from_str::<TextureFormat>("\"rg32sint\"").unwrap(),
2442            TextureFormat::Rg32Sint
2443        );
2444        assert_eq!(
2445            serde_json::from_str::<TextureFormat>("\"rg32float\"").unwrap(),
2446            TextureFormat::Rg32Float
2447        );
2448        assert_eq!(
2449            serde_json::from_str::<TextureFormat>("\"rgba16uint\"").unwrap(),
2450            TextureFormat::Rgba16Uint
2451        );
2452        assert_eq!(
2453            serde_json::from_str::<TextureFormat>("\"rgba16sint\"").unwrap(),
2454            TextureFormat::Rgba16Sint
2455        );
2456        assert_eq!(
2457            serde_json::from_str::<TextureFormat>("\"rgba16unorm\"").unwrap(),
2458            TextureFormat::Rgba16Unorm
2459        );
2460        assert_eq!(
2461            serde_json::from_str::<TextureFormat>("\"rgba16snorm\"").unwrap(),
2462            TextureFormat::Rgba16Snorm
2463        );
2464        assert_eq!(
2465            serde_json::from_str::<TextureFormat>("\"rgba16float\"").unwrap(),
2466            TextureFormat::Rgba16Float
2467        );
2468        assert_eq!(
2469            serde_json::from_str::<TextureFormat>("\"rgba32uint\"").unwrap(),
2470            TextureFormat::Rgba32Uint
2471        );
2472        assert_eq!(
2473            serde_json::from_str::<TextureFormat>("\"rgba32sint\"").unwrap(),
2474            TextureFormat::Rgba32Sint
2475        );
2476        assert_eq!(
2477            serde_json::from_str::<TextureFormat>("\"rgba32float\"").unwrap(),
2478            TextureFormat::Rgba32Float
2479        );
2480        assert_eq!(
2481            serde_json::from_str::<TextureFormat>("\"stencil8\"").unwrap(),
2482            TextureFormat::Stencil8
2483        );
2484        assert_eq!(
2485            serde_json::from_str::<TextureFormat>("\"depth32float\"").unwrap(),
2486            TextureFormat::Depth32Float
2487        );
2488        assert_eq!(
2489            serde_json::from_str::<TextureFormat>("\"depth16unorm\"").unwrap(),
2490            TextureFormat::Depth16Unorm
2491        );
2492        assert_eq!(
2493            serde_json::from_str::<TextureFormat>("\"depth32float-stencil8\"").unwrap(),
2494            TextureFormat::Depth32FloatStencil8
2495        );
2496        assert_eq!(
2497            serde_json::from_str::<TextureFormat>("\"depth24plus\"").unwrap(),
2498            TextureFormat::Depth24Plus
2499        );
2500        assert_eq!(
2501            serde_json::from_str::<TextureFormat>("\"depth24plus-stencil8\"").unwrap(),
2502            TextureFormat::Depth24PlusStencil8
2503        );
2504        assert_eq!(
2505            serde_json::from_str::<TextureFormat>("\"rgb9e5ufloat\"").unwrap(),
2506            TextureFormat::Rgb9e5Ufloat
2507        );
2508        assert_eq!(
2509            serde_json::from_str::<TextureFormat>("\"bc1-rgba-unorm\"").unwrap(),
2510            TextureFormat::Bc1RgbaUnorm
2511        );
2512        assert_eq!(
2513            serde_json::from_str::<TextureFormat>("\"bc1-rgba-unorm-srgb\"").unwrap(),
2514            TextureFormat::Bc1RgbaUnormSrgb
2515        );
2516        assert_eq!(
2517            serde_json::from_str::<TextureFormat>("\"bc2-rgba-unorm\"").unwrap(),
2518            TextureFormat::Bc2RgbaUnorm
2519        );
2520        assert_eq!(
2521            serde_json::from_str::<TextureFormat>("\"bc2-rgba-unorm-srgb\"").unwrap(),
2522            TextureFormat::Bc2RgbaUnormSrgb
2523        );
2524        assert_eq!(
2525            serde_json::from_str::<TextureFormat>("\"bc3-rgba-unorm\"").unwrap(),
2526            TextureFormat::Bc3RgbaUnorm
2527        );
2528        assert_eq!(
2529            serde_json::from_str::<TextureFormat>("\"bc3-rgba-unorm-srgb\"").unwrap(),
2530            TextureFormat::Bc3RgbaUnormSrgb
2531        );
2532        assert_eq!(
2533            serde_json::from_str::<TextureFormat>("\"bc4-r-unorm\"").unwrap(),
2534            TextureFormat::Bc4RUnorm
2535        );
2536        assert_eq!(
2537            serde_json::from_str::<TextureFormat>("\"bc4-r-snorm\"").unwrap(),
2538            TextureFormat::Bc4RSnorm
2539        );
2540        assert_eq!(
2541            serde_json::from_str::<TextureFormat>("\"bc5-rg-unorm\"").unwrap(),
2542            TextureFormat::Bc5RgUnorm
2543        );
2544        assert_eq!(
2545            serde_json::from_str::<TextureFormat>("\"bc5-rg-snorm\"").unwrap(),
2546            TextureFormat::Bc5RgSnorm
2547        );
2548        assert_eq!(
2549            serde_json::from_str::<TextureFormat>("\"bc6h-rgb-ufloat\"").unwrap(),
2550            TextureFormat::Bc6hRgbUfloat
2551        );
2552        assert_eq!(
2553            serde_json::from_str::<TextureFormat>("\"bc6h-rgb-float\"").unwrap(),
2554            TextureFormat::Bc6hRgbFloat
2555        );
2556        assert_eq!(
2557            serde_json::from_str::<TextureFormat>("\"bc7-rgba-unorm\"").unwrap(),
2558            TextureFormat::Bc7RgbaUnorm
2559        );
2560        assert_eq!(
2561            serde_json::from_str::<TextureFormat>("\"bc7-rgba-unorm-srgb\"").unwrap(),
2562            TextureFormat::Bc7RgbaUnormSrgb
2563        );
2564        assert_eq!(
2565            serde_json::from_str::<TextureFormat>("\"etc2-rgb8unorm\"").unwrap(),
2566            TextureFormat::Etc2Rgb8Unorm
2567        );
2568        assert_eq!(
2569            serde_json::from_str::<TextureFormat>("\"etc2-rgb8unorm-srgb\"").unwrap(),
2570            TextureFormat::Etc2Rgb8UnormSrgb
2571        );
2572        assert_eq!(
2573            serde_json::from_str::<TextureFormat>("\"etc2-rgb8a1unorm\"").unwrap(),
2574            TextureFormat::Etc2Rgb8A1Unorm
2575        );
2576        assert_eq!(
2577            serde_json::from_str::<TextureFormat>("\"etc2-rgb8a1unorm-srgb\"").unwrap(),
2578            TextureFormat::Etc2Rgb8A1UnormSrgb
2579        );
2580        assert_eq!(
2581            serde_json::from_str::<TextureFormat>("\"etc2-rgba8unorm\"").unwrap(),
2582            TextureFormat::Etc2Rgba8Unorm
2583        );
2584        assert_eq!(
2585            serde_json::from_str::<TextureFormat>("\"etc2-rgba8unorm-srgb\"").unwrap(),
2586            TextureFormat::Etc2Rgba8UnormSrgb
2587        );
2588        assert_eq!(
2589            serde_json::from_str::<TextureFormat>("\"eac-r11unorm\"").unwrap(),
2590            TextureFormat::EacR11Unorm
2591        );
2592        assert_eq!(
2593            serde_json::from_str::<TextureFormat>("\"eac-r11snorm\"").unwrap(),
2594            TextureFormat::EacR11Snorm
2595        );
2596        assert_eq!(
2597            serde_json::from_str::<TextureFormat>("\"eac-rg11unorm\"").unwrap(),
2598            TextureFormat::EacRg11Unorm
2599        );
2600        assert_eq!(
2601            serde_json::from_str::<TextureFormat>("\"eac-rg11snorm\"").unwrap(),
2602            TextureFormat::EacRg11Snorm
2603        );
2604    }
2605
2606    /// test if `TextureFormat::is_depth_stencil_format` is behaving correctly
2607    #[test]
2608    fn is_depth_stencil_format() {
2609        let depth_stencil_formats = [
2610            TextureFormat::Stencil8,
2611            TextureFormat::Depth16Unorm,
2612            TextureFormat::Depth24Plus,
2613            TextureFormat::Depth24PlusStencil8,
2614            TextureFormat::Depth32Float,
2615            TextureFormat::Depth32FloatStencil8,
2616        ];
2617
2618        for format in depth_stencil_formats {
2619            assert!(format.is_depth_stencil_format());
2620        }
2621
2622        // some non-depth-stencil-formats shouldn't be accepted
2623        let non_depth_stencil_formats = [
2624            TextureFormat::R8Unorm,
2625            TextureFormat::Rgba8Unorm,
2626            TextureFormat::Rg16Uint,
2627            TextureFormat::NV12,
2628        ];
2629
2630        for format in non_depth_stencil_formats {
2631            assert!(!format.is_depth_stencil_format());
2632        }
2633    }
2634
2635    /// test if `TextureFormat::is_combined_depth_stencil_format` is behaving correctly
2636    #[test]
2637    fn is_combined_depth_stencil_format() {
2638        let valid_formats = [
2639            TextureFormat::Depth24PlusStencil8,
2640            TextureFormat::Depth32FloatStencil8,
2641        ];
2642
2643        for format in valid_formats {
2644            assert!(format.is_combined_depth_stencil_format());
2645        }
2646
2647        let some_invalid_formats = [
2648            TextureFormat::Depth16Unorm,
2649            TextureFormat::Depth24Plus,
2650            TextureFormat::Stencil8,
2651            TextureFormat::Rgba8UnormSrgb,
2652            TextureFormat::Rgba8Unorm,
2653        ];
2654
2655        for format in some_invalid_formats {
2656            assert!(!format.is_combined_depth_stencil_format());
2657        }
2658    }
2659
2660    /// test if `TextureFormat::has_color_aspect` is behaving correctly
2661    #[test]
2662    fn has_color_aspect() {
2663        let some_valid_formats = [
2664            TextureFormat::R8Unorm,
2665            TextureFormat::Rg8Unorm,
2666            TextureFormat::Bc7RgbaUnorm,
2667            TextureFormat::Rgba8Unorm,
2668        ];
2669
2670        for format in some_valid_formats {
2671            assert!(format.has_color_aspect());
2672        }
2673
2674        let some_invalid_formats = [
2675            TextureFormat::NV12,
2676            TextureFormat::Stencil8,
2677            TextureFormat::Depth24PlusStencil8,
2678        ];
2679
2680        for format in some_invalid_formats {
2681            assert!(!format.has_color_aspect());
2682        }
2683    }
2684
2685    /// test if `TextureFormat::has_depth_aspect` is behaving correctly
2686    #[test]
2687    fn has_depth_aspect() {
2688        let valid_formats = [
2689            TextureFormat::Depth16Unorm,
2690            TextureFormat::Depth24Plus,
2691            TextureFormat::Depth24PlusStencil8,
2692            TextureFormat::Depth32Float,
2693            TextureFormat::Depth32FloatStencil8,
2694        ];
2695
2696        for format in valid_formats {
2697            assert!(format.has_depth_aspect());
2698        }
2699
2700        let some_invalid_formats = [
2701            TextureFormat::Rgba8Unorm,
2702            TextureFormat::Bc7RgbaUnorm,
2703            TextureFormat::Stencil8,
2704        ];
2705
2706        for format in some_invalid_formats {
2707            assert!(!format.has_depth_aspect());
2708        }
2709    }
2710
2711    /// test if `TextureFormat::has_stencil_aspect` is behaving correctly
2712    #[test]
2713    fn has_stencil_aspect() {
2714        let valid_formats = [
2715            TextureFormat::Stencil8,
2716            TextureFormat::Depth24PlusStencil8,
2717            TextureFormat::Depth32FloatStencil8,
2718        ];
2719
2720        for format in valid_formats {
2721            assert!(format.has_stencil_aspect());
2722        }
2723
2724        let some_invalid_formats = [
2725            TextureFormat::R8Unorm,
2726            TextureFormat::Depth16Unorm,
2727            TextureFormat::NV12,
2728        ];
2729
2730        for format in some_invalid_formats {
2731            assert!(!format.has_stencil_aspect());
2732        }
2733    }
2734}