wgpu_types/texture/
format.rs

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