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