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
925        flags.set(TextureFormatFeatureFlags::FILTERABLE, is_filterable);
926        flags.set(TextureFormatFeatureFlags::BLENDABLE, is_blendable);
927        flags.set(
928            TextureFormatFeatureFlags::STORAGE_ATOMIC,
929            allowed_usages.contains(TextureUsages::STORAGE_ATOMIC),
930        );
931
932        TextureFormatFeatures {
933            allowed_usages,
934            flags,
935        }
936    }
937
938    /// Returns the sample type compatible with this format and aspect.
939    ///
940    /// Returns `None` only if this is a combined depth-stencil format or a multi-planar format
941    /// and `TextureAspect::All` or no `aspect` was provided.
942    #[must_use]
943    pub fn sample_type(
944        &self,
945        aspect: Option<TextureAspect>,
946        device_features: Option<Features>,
947    ) -> Option<TextureSampleType> {
948        let float = TextureSampleType::Float { filterable: true };
949        let unfilterable_float = TextureSampleType::Float { filterable: false };
950        let float32_sample_type = TextureSampleType::Float {
951            filterable: device_features
952                .unwrap_or(Features::empty())
953                .contains(Features::FLOAT32_FILTERABLE),
954        };
955        let depth = TextureSampleType::Depth;
956        let uint = TextureSampleType::Uint;
957        let sint = TextureSampleType::Sint;
958
959        match *self {
960            Self::R8Unorm
961            | Self::R8Snorm
962            | Self::Rg8Unorm
963            | Self::Rg8Snorm
964            | Self::Rgba8Unorm
965            | Self::Rgba8UnormSrgb
966            | Self::Rgba8Snorm
967            | Self::Bgra8Unorm
968            | Self::Bgra8UnormSrgb
969            | Self::R16Float
970            | Self::Rg16Float
971            | Self::Rgba16Float
972            | Self::Rgb10a2Unorm
973            | Self::Rg11b10Ufloat => Some(float),
974
975            Self::R32Float | Self::Rg32Float | Self::Rgba32Float => Some(float32_sample_type),
976
977            Self::R8Uint
978            | Self::Rg8Uint
979            | Self::Rgba8Uint
980            | Self::R16Uint
981            | Self::Rg16Uint
982            | Self::Rgba16Uint
983            | Self::R32Uint
984            | Self::R64Uint
985            | Self::Rg32Uint
986            | Self::Rgba32Uint
987            | Self::Rgb10a2Uint => Some(uint),
988
989            Self::R8Sint
990            | Self::Rg8Sint
991            | Self::Rgba8Sint
992            | Self::R16Sint
993            | Self::Rg16Sint
994            | Self::Rgba16Sint
995            | Self::R32Sint
996            | Self::Rg32Sint
997            | Self::Rgba32Sint => Some(sint),
998
999            Self::Stencil8 => Some(uint),
1000            Self::Depth16Unorm | Self::Depth24Plus | Self::Depth32Float => Some(depth),
1001            Self::Depth24PlusStencil8 | Self::Depth32FloatStencil8 => match aspect {
1002                Some(TextureAspect::DepthOnly) => Some(depth),
1003                Some(TextureAspect::StencilOnly) => Some(uint),
1004                _ => None,
1005            },
1006
1007            Self::NV12 | Self::P010 => match aspect {
1008                Some(TextureAspect::Plane0) | Some(TextureAspect::Plane1) => {
1009                    Some(unfilterable_float)
1010                }
1011                _ => None,
1012            },
1013
1014            Self::R16Unorm
1015            | Self::R16Snorm
1016            | Self::Rg16Unorm
1017            | Self::Rg16Snorm
1018            | Self::Rgba16Unorm
1019            | Self::Rgba16Snorm => Some(float),
1020
1021            Self::Rgb9e5Ufloat => Some(float),
1022
1023            Self::Bc1RgbaUnorm
1024            | Self::Bc1RgbaUnormSrgb
1025            | Self::Bc2RgbaUnorm
1026            | Self::Bc2RgbaUnormSrgb
1027            | Self::Bc3RgbaUnorm
1028            | Self::Bc3RgbaUnormSrgb
1029            | Self::Bc4RUnorm
1030            | Self::Bc4RSnorm
1031            | Self::Bc5RgUnorm
1032            | Self::Bc5RgSnorm
1033            | Self::Bc6hRgbUfloat
1034            | Self::Bc6hRgbFloat
1035            | Self::Bc7RgbaUnorm
1036            | Self::Bc7RgbaUnormSrgb => Some(float),
1037
1038            Self::Etc2Rgb8Unorm
1039            | Self::Etc2Rgb8UnormSrgb
1040            | Self::Etc2Rgb8A1Unorm
1041            | Self::Etc2Rgb8A1UnormSrgb
1042            | Self::Etc2Rgba8Unorm
1043            | Self::Etc2Rgba8UnormSrgb
1044            | Self::EacR11Unorm
1045            | Self::EacR11Snorm
1046            | Self::EacRg11Unorm
1047            | Self::EacRg11Snorm => Some(float),
1048
1049            Self::Astc { .. } => Some(float),
1050        }
1051    }
1052
1053    /// The number of bytes one [texel block](https://gpuweb.github.io/gpuweb/#texel-block) occupies during an image copy, if applicable.
1054    ///
1055    /// Known as the [texel block copy footprint](https://gpuweb.github.io/gpuweb/#texel-block-copy-footprint).
1056    ///
1057    /// Note that for uncompressed formats this is the same as the size of a single texel,
1058    /// since uncompressed formats have a block size of 1x1.
1059    ///
1060    /// Returns `None` if any of the following are true:
1061    ///  - the format is a combined depth-stencil and no `aspect` was provided
1062    ///  - the format is a multi-planar format and no `aspect` was provided
1063    ///  - the format is `Depth24Plus`
1064    ///  - the format is `Depth24PlusStencil8` and `aspect` is depth.
1065    #[deprecated(since = "0.19.0", note = "Use `block_copy_size` instead.")]
1066    #[must_use]
1067    pub fn block_size(&self, aspect: Option<TextureAspect>) -> Option<u32> {
1068        self.block_copy_size(aspect)
1069    }
1070
1071    /// The number of bytes one [texel block](https://gpuweb.github.io/gpuweb/#texel-block) occupies during an image copy, if applicable.
1072    ///
1073    /// Known as the [texel block copy footprint](https://gpuweb.github.io/gpuweb/#texel-block-copy-footprint).
1074    ///
1075    /// Note that for uncompressed formats this is the same as the size of a single texel,
1076    /// since uncompressed formats have a block size of 1x1.
1077    ///
1078    /// Returns `None` if any of the following are true:
1079    ///  - the format is a combined depth-stencil and no `aspect` was provided
1080    ///  - the format is a multi-planar format and no `aspect` was provided
1081    ///  - the format is `Depth24Plus`
1082    ///  - the format is `Depth24PlusStencil8` and `aspect` is depth.
1083    #[must_use]
1084    pub fn block_copy_size(&self, aspect: Option<TextureAspect>) -> Option<u32> {
1085        match *self {
1086            Self::R8Unorm | Self::R8Snorm | Self::R8Uint | Self::R8Sint => Some(1),
1087
1088            Self::Rg8Unorm | Self::Rg8Snorm | Self::Rg8Uint | Self::Rg8Sint => Some(2),
1089            Self::R16Unorm | Self::R16Snorm | Self::R16Uint | Self::R16Sint | Self::R16Float => {
1090                Some(2)
1091            }
1092
1093            Self::Rgba8Unorm
1094            | Self::Rgba8UnormSrgb
1095            | Self::Rgba8Snorm
1096            | Self::Rgba8Uint
1097            | Self::Rgba8Sint
1098            | Self::Bgra8Unorm
1099            | Self::Bgra8UnormSrgb => Some(4),
1100            Self::Rg16Unorm
1101            | Self::Rg16Snorm
1102            | Self::Rg16Uint
1103            | Self::Rg16Sint
1104            | Self::Rg16Float => Some(4),
1105            Self::R32Uint | Self::R32Sint | Self::R32Float => Some(4),
1106            Self::Rgb9e5Ufloat | Self::Rgb10a2Uint | Self::Rgb10a2Unorm | Self::Rg11b10Ufloat => {
1107                Some(4)
1108            }
1109
1110            Self::Rgba16Unorm
1111            | Self::Rgba16Snorm
1112            | Self::Rgba16Uint
1113            | Self::Rgba16Sint
1114            | Self::Rgba16Float => Some(8),
1115            Self::R64Uint | Self::Rg32Uint | Self::Rg32Sint | Self::Rg32Float => Some(8),
1116
1117            Self::Rgba32Uint | Self::Rgba32Sint | Self::Rgba32Float => Some(16),
1118
1119            Self::Stencil8 => Some(1),
1120            Self::Depth16Unorm => Some(2),
1121            Self::Depth32Float => Some(4),
1122            Self::Depth24Plus => None,
1123            Self::Depth24PlusStencil8 => match aspect {
1124                Some(TextureAspect::DepthOnly) => None,
1125                Some(TextureAspect::StencilOnly) => Some(1),
1126                _ => None,
1127            },
1128            Self::Depth32FloatStencil8 => match aspect {
1129                Some(TextureAspect::DepthOnly) => Some(4),
1130                Some(TextureAspect::StencilOnly) => Some(1),
1131                _ => None,
1132            },
1133
1134            Self::NV12 => match aspect {
1135                Some(TextureAspect::Plane0) => Some(1),
1136                Some(TextureAspect::Plane1) => Some(2),
1137                _ => None,
1138            },
1139
1140            Self::P010 => match aspect {
1141                Some(TextureAspect::Plane0) => Some(2),
1142                Some(TextureAspect::Plane1) => Some(4),
1143                _ => None,
1144            },
1145
1146            Self::Bc1RgbaUnorm | Self::Bc1RgbaUnormSrgb | Self::Bc4RUnorm | Self::Bc4RSnorm => {
1147                Some(8)
1148            }
1149            Self::Bc2RgbaUnorm
1150            | Self::Bc2RgbaUnormSrgb
1151            | Self::Bc3RgbaUnorm
1152            | Self::Bc3RgbaUnormSrgb
1153            | Self::Bc5RgUnorm
1154            | Self::Bc5RgSnorm
1155            | Self::Bc6hRgbUfloat
1156            | Self::Bc6hRgbFloat
1157            | Self::Bc7RgbaUnorm
1158            | Self::Bc7RgbaUnormSrgb => Some(16),
1159
1160            Self::Etc2Rgb8Unorm
1161            | Self::Etc2Rgb8UnormSrgb
1162            | Self::Etc2Rgb8A1Unorm
1163            | Self::Etc2Rgb8A1UnormSrgb
1164            | Self::EacR11Unorm
1165            | Self::EacR11Snorm => Some(8),
1166            Self::Etc2Rgba8Unorm
1167            | Self::Etc2Rgba8UnormSrgb
1168            | Self::EacRg11Unorm
1169            | Self::EacRg11Snorm => Some(16),
1170
1171            Self::Astc { .. } => Some(16),
1172        }
1173    }
1174
1175    /// The largest number that can be returned by [`Self::target_pixel_byte_cost`].
1176    pub const MAX_TARGET_PIXEL_BYTE_COST: u32 = 16;
1177
1178    /// The number of bytes occupied per pixel in a color attachment
1179    /// <https://gpuweb.github.io/gpuweb/#render-target-pixel-byte-cost>
1180    #[must_use]
1181    pub fn target_pixel_byte_cost(&self) -> Option<u32> {
1182        match *self {
1183            Self::R8Unorm | Self::R8Snorm | Self::R8Uint | Self::R8Sint => Some(1),
1184            Self::Rg8Unorm
1185            | Self::Rg8Snorm
1186            | Self::Rg8Uint
1187            | Self::Rg8Sint
1188            | Self::R16Uint
1189            | Self::R16Sint
1190            | Self::R16Unorm
1191            | Self::R16Snorm
1192            | Self::R16Float => Some(2),
1193            Self::Rgba8Uint
1194            | Self::Rgba8Sint
1195            | Self::Rg16Uint
1196            | Self::Rg16Sint
1197            | Self::Rg16Unorm
1198            | Self::Rg16Snorm
1199            | Self::Rg16Float
1200            | Self::R32Uint
1201            | Self::R32Sint
1202            | Self::R32Float => Some(4),
1203            // Despite being 4 bytes per pixel, these are 8 bytes per pixel in the table
1204            Self::Rgba8Unorm
1205            | Self::Rgba8UnormSrgb
1206            | Self::Rgba8Snorm
1207            | Self::Bgra8Unorm
1208            | Self::Bgra8UnormSrgb
1209            // ---
1210            | Self::Rgba16Uint
1211            | Self::Rgba16Sint
1212            | Self::Rgba16Unorm
1213            | Self::Rgba16Snorm
1214            | Self::Rgba16Float
1215            | Self::R64Uint
1216            | Self::Rg32Uint
1217            | Self::Rg32Sint
1218            | Self::Rg32Float
1219            | Self::Rgb10a2Uint
1220            | Self::Rgb10a2Unorm
1221            | Self::Rg11b10Ufloat => Some(8),
1222            Self::Rgba32Uint | Self::Rgba32Sint | Self::Rgba32Float => Some(16),
1223            // ⚠️ If you add formats with larger sizes, make sure you change `MAX_TARGET_PIXEL_BYTE_COST`` ⚠️
1224            Self::Stencil8
1225            | Self::Depth16Unorm
1226            | Self::Depth24Plus
1227            | Self::Depth24PlusStencil8
1228            | Self::Depth32Float
1229            | Self::Depth32FloatStencil8
1230            | Self::NV12
1231            | Self::P010
1232            | Self::Rgb9e5Ufloat
1233            | Self::Bc1RgbaUnorm
1234            | Self::Bc1RgbaUnormSrgb
1235            | Self::Bc2RgbaUnorm
1236            | Self::Bc2RgbaUnormSrgb
1237            | Self::Bc3RgbaUnorm
1238            | Self::Bc3RgbaUnormSrgb
1239            | Self::Bc4RUnorm
1240            | Self::Bc4RSnorm
1241            | Self::Bc5RgUnorm
1242            | Self::Bc5RgSnorm
1243            | Self::Bc6hRgbUfloat
1244            | Self::Bc6hRgbFloat
1245            | Self::Bc7RgbaUnorm
1246            | Self::Bc7RgbaUnormSrgb
1247            | Self::Etc2Rgb8Unorm
1248            | Self::Etc2Rgb8UnormSrgb
1249            | Self::Etc2Rgb8A1Unorm
1250            | Self::Etc2Rgb8A1UnormSrgb
1251            | Self::Etc2Rgba8Unorm
1252            | Self::Etc2Rgba8UnormSrgb
1253            | Self::EacR11Unorm
1254            | Self::EacR11Snorm
1255            | Self::EacRg11Unorm
1256            | Self::EacRg11Snorm
1257            | Self::Astc { .. } => None,
1258        }
1259    }
1260
1261    /// See <https://gpuweb.github.io/gpuweb/#render-target-component-alignment>
1262    #[must_use]
1263    pub fn target_component_alignment(&self) -> Option<u32> {
1264        match *self {
1265            Self::R8Unorm
1266            | Self::R8Snorm
1267            | Self::R8Uint
1268            | Self::R8Sint
1269            | Self::Rg8Unorm
1270            | Self::Rg8Snorm
1271            | Self::Rg8Uint
1272            | Self::Rg8Sint
1273            | Self::Rgba8Unorm
1274            | Self::Rgba8UnormSrgb
1275            | Self::Rgba8Snorm
1276            | Self::Rgba8Uint
1277            | Self::Rgba8Sint
1278            | Self::Bgra8Unorm
1279            | Self::Bgra8UnormSrgb => Some(1),
1280            Self::R16Uint
1281            | Self::R16Sint
1282            | Self::R16Unorm
1283            | Self::R16Snorm
1284            | Self::R16Float
1285            | Self::Rg16Uint
1286            | Self::Rg16Sint
1287            | Self::Rg16Unorm
1288            | Self::Rg16Snorm
1289            | Self::Rg16Float
1290            | Self::Rgba16Uint
1291            | Self::Rgba16Sint
1292            | Self::Rgba16Unorm
1293            | Self::Rgba16Snorm
1294            | Self::Rgba16Float => Some(2),
1295            Self::R32Uint
1296            | Self::R32Sint
1297            | Self::R32Float
1298            | Self::R64Uint
1299            | Self::Rg32Uint
1300            | Self::Rg32Sint
1301            | Self::Rg32Float
1302            | Self::Rgba32Uint
1303            | Self::Rgba32Sint
1304            | Self::Rgba32Float
1305            | Self::Rgb10a2Uint
1306            | Self::Rgb10a2Unorm
1307            | Self::Rg11b10Ufloat => Some(4),
1308            Self::Stencil8
1309            | Self::Depth16Unorm
1310            | Self::Depth24Plus
1311            | Self::Depth24PlusStencil8
1312            | Self::Depth32Float
1313            | Self::Depth32FloatStencil8
1314            | Self::NV12
1315            | Self::P010
1316            | Self::Rgb9e5Ufloat
1317            | Self::Bc1RgbaUnorm
1318            | Self::Bc1RgbaUnormSrgb
1319            | Self::Bc2RgbaUnorm
1320            | Self::Bc2RgbaUnormSrgb
1321            | Self::Bc3RgbaUnorm
1322            | Self::Bc3RgbaUnormSrgb
1323            | Self::Bc4RUnorm
1324            | Self::Bc4RSnorm
1325            | Self::Bc5RgUnorm
1326            | Self::Bc5RgSnorm
1327            | Self::Bc6hRgbUfloat
1328            | Self::Bc6hRgbFloat
1329            | Self::Bc7RgbaUnorm
1330            | Self::Bc7RgbaUnormSrgb
1331            | Self::Etc2Rgb8Unorm
1332            | Self::Etc2Rgb8UnormSrgb
1333            | Self::Etc2Rgb8A1Unorm
1334            | Self::Etc2Rgb8A1UnormSrgb
1335            | Self::Etc2Rgba8Unorm
1336            | Self::Etc2Rgba8UnormSrgb
1337            | Self::EacR11Unorm
1338            | Self::EacR11Snorm
1339            | Self::EacRg11Unorm
1340            | Self::EacRg11Snorm
1341            | Self::Astc { .. } => None,
1342        }
1343    }
1344
1345    /// Returns the number of components this format has.
1346    #[must_use]
1347    pub fn components(&self) -> u8 {
1348        self.components_with_aspect(TextureAspect::All)
1349    }
1350
1351    /// Returns the number of components this format has taking into account the `aspect`.
1352    ///
1353    /// The `aspect` is only relevant for combined depth-stencil formats and multi-planar formats.
1354    #[must_use]
1355    pub fn components_with_aspect(&self, aspect: TextureAspect) -> u8 {
1356        match *self {
1357            Self::R8Unorm
1358            | Self::R8Snorm
1359            | Self::R8Uint
1360            | Self::R8Sint
1361            | Self::R16Unorm
1362            | Self::R16Snorm
1363            | Self::R16Uint
1364            | Self::R16Sint
1365            | Self::R16Float
1366            | Self::R32Uint
1367            | Self::R32Sint
1368            | Self::R32Float
1369            | Self::R64Uint => 1,
1370
1371            Self::Rg8Unorm
1372            | Self::Rg8Snorm
1373            | Self::Rg8Uint
1374            | Self::Rg8Sint
1375            | Self::Rg16Unorm
1376            | Self::Rg16Snorm
1377            | Self::Rg16Uint
1378            | Self::Rg16Sint
1379            | Self::Rg16Float
1380            | Self::Rg32Uint
1381            | Self::Rg32Sint
1382            | Self::Rg32Float => 2,
1383
1384            Self::Rgba8Unorm
1385            | Self::Rgba8UnormSrgb
1386            | Self::Rgba8Snorm
1387            | Self::Rgba8Uint
1388            | Self::Rgba8Sint
1389            | Self::Bgra8Unorm
1390            | Self::Bgra8UnormSrgb
1391            | Self::Rgba16Unorm
1392            | Self::Rgba16Snorm
1393            | Self::Rgba16Uint
1394            | Self::Rgba16Sint
1395            | Self::Rgba16Float
1396            | Self::Rgba32Uint
1397            | Self::Rgba32Sint
1398            | Self::Rgba32Float => 4,
1399
1400            Self::Rgb9e5Ufloat | Self::Rg11b10Ufloat => 3,
1401            Self::Rgb10a2Uint | Self::Rgb10a2Unorm => 4,
1402
1403            Self::Stencil8 | Self::Depth16Unorm | Self::Depth24Plus | Self::Depth32Float => 1,
1404
1405            Self::Depth24PlusStencil8 | Self::Depth32FloatStencil8 => match aspect {
1406                TextureAspect::DepthOnly | TextureAspect::StencilOnly => 1,
1407                _ => 2,
1408            },
1409
1410            Self::NV12 | Self::P010 => match aspect {
1411                TextureAspect::Plane0 => 1,
1412                TextureAspect::Plane1 => 2,
1413                _ => 3,
1414            },
1415
1416            Self::Bc4RUnorm | Self::Bc4RSnorm => 1,
1417            Self::Bc5RgUnorm | Self::Bc5RgSnorm => 2,
1418            Self::Bc6hRgbUfloat | Self::Bc6hRgbFloat => 3,
1419            Self::Bc1RgbaUnorm
1420            | Self::Bc1RgbaUnormSrgb
1421            | Self::Bc2RgbaUnorm
1422            | Self::Bc2RgbaUnormSrgb
1423            | Self::Bc3RgbaUnorm
1424            | Self::Bc3RgbaUnormSrgb
1425            | Self::Bc7RgbaUnorm
1426            | Self::Bc7RgbaUnormSrgb => 4,
1427
1428            Self::EacR11Unorm | Self::EacR11Snorm => 1,
1429            Self::EacRg11Unorm | Self::EacRg11Snorm => 2,
1430            Self::Etc2Rgb8Unorm | Self::Etc2Rgb8UnormSrgb => 3,
1431            Self::Etc2Rgb8A1Unorm
1432            | Self::Etc2Rgb8A1UnormSrgb
1433            | Self::Etc2Rgba8Unorm
1434            | Self::Etc2Rgba8UnormSrgb => 4,
1435
1436            Self::Astc { .. } => 4,
1437        }
1438    }
1439
1440    /// Strips the `Srgb` suffix from the given texture format.
1441    #[must_use]
1442    pub fn remove_srgb_suffix(&self) -> TextureFormat {
1443        match *self {
1444            Self::Rgba8UnormSrgb => Self::Rgba8Unorm,
1445            Self::Bgra8UnormSrgb => Self::Bgra8Unorm,
1446            Self::Bc1RgbaUnormSrgb => Self::Bc1RgbaUnorm,
1447            Self::Bc2RgbaUnormSrgb => Self::Bc2RgbaUnorm,
1448            Self::Bc3RgbaUnormSrgb => Self::Bc3RgbaUnorm,
1449            Self::Bc7RgbaUnormSrgb => Self::Bc7RgbaUnorm,
1450            Self::Etc2Rgb8UnormSrgb => Self::Etc2Rgb8Unorm,
1451            Self::Etc2Rgb8A1UnormSrgb => Self::Etc2Rgb8A1Unorm,
1452            Self::Etc2Rgba8UnormSrgb => Self::Etc2Rgba8Unorm,
1453            Self::Astc {
1454                block,
1455                channel: AstcChannel::UnormSrgb,
1456            } => Self::Astc {
1457                block,
1458                channel: AstcChannel::Unorm,
1459            },
1460            _ => *self,
1461        }
1462    }
1463
1464    /// Adds an `Srgb` suffix to the given texture format, if the format supports it.
1465    #[must_use]
1466    pub fn add_srgb_suffix(&self) -> TextureFormat {
1467        match *self {
1468            Self::Rgba8Unorm => Self::Rgba8UnormSrgb,
1469            Self::Bgra8Unorm => Self::Bgra8UnormSrgb,
1470            Self::Bc1RgbaUnorm => Self::Bc1RgbaUnormSrgb,
1471            Self::Bc2RgbaUnorm => Self::Bc2RgbaUnormSrgb,
1472            Self::Bc3RgbaUnorm => Self::Bc3RgbaUnormSrgb,
1473            Self::Bc7RgbaUnorm => Self::Bc7RgbaUnormSrgb,
1474            Self::Etc2Rgb8Unorm => Self::Etc2Rgb8UnormSrgb,
1475            Self::Etc2Rgb8A1Unorm => Self::Etc2Rgb8A1UnormSrgb,
1476            Self::Etc2Rgba8Unorm => Self::Etc2Rgba8UnormSrgb,
1477            Self::Astc {
1478                block,
1479                channel: AstcChannel::Unorm,
1480            } => Self::Astc {
1481                block,
1482                channel: AstcChannel::UnormSrgb,
1483            },
1484            _ => *self,
1485        }
1486    }
1487
1488    /// Returns `true` for srgb formats.
1489    #[must_use]
1490    pub fn is_srgb(&self) -> bool {
1491        *self != self.remove_srgb_suffix()
1492    }
1493
1494    /// Returns the theoretical memory footprint of a texture with the given format and dimensions.
1495    ///
1496    /// Actual memory usage may greatly exceed this value due to alignment and padding.
1497    #[must_use]
1498    pub fn theoretical_memory_footprint(&self, size: crate::Extent3d) -> u64 {
1499        let (block_width, block_height) = self.block_dimensions();
1500
1501        let block_size = self.block_copy_size(None);
1502
1503        let approximate_block_size = match block_size {
1504            Some(size) => size,
1505            None => match self {
1506                // One f16 per pixel
1507                Self::Depth16Unorm => 2,
1508                // One u24 per pixel, padded to 4 bytes
1509                Self::Depth24Plus => 4,
1510                // One u24 per pixel, plus one u8 per pixel
1511                Self::Depth24PlusStencil8 => 4,
1512                // One f32 per pixel
1513                Self::Depth32Float => 4,
1514                // One f32 per pixel, plus one u8 per pixel, with 3 bytes intermediary padding
1515                Self::Depth32FloatStencil8 => 8,
1516                // One u8 per pixel
1517                Self::Stencil8 => 1,
1518                // Two chroma bytes per block, one luma byte per block
1519                Self::NV12 => 3,
1520                // Two chroma u16s and one luma u16 per block
1521                Self::P010 => 6,
1522                f => {
1523                    unimplemented!("Memory footprint for format {f:?} is not implemented");
1524                }
1525            },
1526        };
1527
1528        let width_blocks = size.width.div_ceil(block_width) as u64;
1529        let height_blocks = size.height.div_ceil(block_height) as u64;
1530
1531        let total_blocks = width_blocks * height_blocks * size.depth_or_array_layers as u64;
1532
1533        total_blocks * approximate_block_size as u64
1534    }
1535}
1536
1537#[cfg(any(feature = "serde", test))]
1538impl<'de> Deserialize<'de> for TextureFormat {
1539    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1540    where
1541        D: serde::Deserializer<'de>,
1542    {
1543        use serde::de::{self, Error, Unexpected};
1544
1545        struct TextureFormatVisitor;
1546
1547        impl de::Visitor<'_> for TextureFormatVisitor {
1548            type Value = TextureFormat;
1549
1550            fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
1551                formatter.write_str("a valid texture format")
1552            }
1553
1554            fn visit_str<E: Error>(self, s: &str) -> Result<Self::Value, E> {
1555                let format = match s {
1556                    "r8unorm" => TextureFormat::R8Unorm,
1557                    "r8snorm" => TextureFormat::R8Snorm,
1558                    "r8uint" => TextureFormat::R8Uint,
1559                    "r8sint" => TextureFormat::R8Sint,
1560                    "r16uint" => TextureFormat::R16Uint,
1561                    "r16sint" => TextureFormat::R16Sint,
1562                    "r16unorm" => TextureFormat::R16Unorm,
1563                    "r16snorm" => TextureFormat::R16Snorm,
1564                    "r16float" => TextureFormat::R16Float,
1565                    "rg8unorm" => TextureFormat::Rg8Unorm,
1566                    "rg8snorm" => TextureFormat::Rg8Snorm,
1567                    "rg8uint" => TextureFormat::Rg8Uint,
1568                    "rg8sint" => TextureFormat::Rg8Sint,
1569                    "r32uint" => TextureFormat::R32Uint,
1570                    "r32sint" => TextureFormat::R32Sint,
1571                    "r32float" => TextureFormat::R32Float,
1572                    "rg16uint" => TextureFormat::Rg16Uint,
1573                    "rg16sint" => TextureFormat::Rg16Sint,
1574                    "rg16unorm" => TextureFormat::Rg16Unorm,
1575                    "rg16snorm" => TextureFormat::Rg16Snorm,
1576                    "rg16float" => TextureFormat::Rg16Float,
1577                    "rgba8unorm" => TextureFormat::Rgba8Unorm,
1578                    "rgba8unorm-srgb" => TextureFormat::Rgba8UnormSrgb,
1579                    "rgba8snorm" => TextureFormat::Rgba8Snorm,
1580                    "rgba8uint" => TextureFormat::Rgba8Uint,
1581                    "rgba8sint" => TextureFormat::Rgba8Sint,
1582                    "bgra8unorm" => TextureFormat::Bgra8Unorm,
1583                    "bgra8unorm-srgb" => TextureFormat::Bgra8UnormSrgb,
1584                    "rgb10a2uint" => TextureFormat::Rgb10a2Uint,
1585                    "rgb10a2unorm" => TextureFormat::Rgb10a2Unorm,
1586                    "rg11b10ufloat" => TextureFormat::Rg11b10Ufloat,
1587                    "r64uint" => TextureFormat::R64Uint,
1588                    "rg32uint" => TextureFormat::Rg32Uint,
1589                    "rg32sint" => TextureFormat::Rg32Sint,
1590                    "rg32float" => TextureFormat::Rg32Float,
1591                    "rgba16uint" => TextureFormat::Rgba16Uint,
1592                    "rgba16sint" => TextureFormat::Rgba16Sint,
1593                    "rgba16unorm" => TextureFormat::Rgba16Unorm,
1594                    "rgba16snorm" => TextureFormat::Rgba16Snorm,
1595                    "rgba16float" => TextureFormat::Rgba16Float,
1596                    "rgba32uint" => TextureFormat::Rgba32Uint,
1597                    "rgba32sint" => TextureFormat::Rgba32Sint,
1598                    "rgba32float" => TextureFormat::Rgba32Float,
1599                    "stencil8" => TextureFormat::Stencil8,
1600                    "depth32float" => TextureFormat::Depth32Float,
1601                    "depth32float-stencil8" => TextureFormat::Depth32FloatStencil8,
1602                    "depth16unorm" => TextureFormat::Depth16Unorm,
1603                    "depth24plus" => TextureFormat::Depth24Plus,
1604                    "depth24plus-stencil8" => TextureFormat::Depth24PlusStencil8,
1605                    "nv12" => TextureFormat::NV12,
1606                    "p010" => TextureFormat::P010,
1607                    "rgb9e5ufloat" => TextureFormat::Rgb9e5Ufloat,
1608                    "bc1-rgba-unorm" => TextureFormat::Bc1RgbaUnorm,
1609                    "bc1-rgba-unorm-srgb" => TextureFormat::Bc1RgbaUnormSrgb,
1610                    "bc2-rgba-unorm" => TextureFormat::Bc2RgbaUnorm,
1611                    "bc2-rgba-unorm-srgb" => TextureFormat::Bc2RgbaUnormSrgb,
1612                    "bc3-rgba-unorm" => TextureFormat::Bc3RgbaUnorm,
1613                    "bc3-rgba-unorm-srgb" => TextureFormat::Bc3RgbaUnormSrgb,
1614                    "bc4-r-unorm" => TextureFormat::Bc4RUnorm,
1615                    "bc4-r-snorm" => TextureFormat::Bc4RSnorm,
1616                    "bc5-rg-unorm" => TextureFormat::Bc5RgUnorm,
1617                    "bc5-rg-snorm" => TextureFormat::Bc5RgSnorm,
1618                    "bc6h-rgb-ufloat" => TextureFormat::Bc6hRgbUfloat,
1619                    "bc6h-rgb-float" => TextureFormat::Bc6hRgbFloat,
1620                    "bc7-rgba-unorm" => TextureFormat::Bc7RgbaUnorm,
1621                    "bc7-rgba-unorm-srgb" => TextureFormat::Bc7RgbaUnormSrgb,
1622                    "etc2-rgb8unorm" => TextureFormat::Etc2Rgb8Unorm,
1623                    "etc2-rgb8unorm-srgb" => TextureFormat::Etc2Rgb8UnormSrgb,
1624                    "etc2-rgb8a1unorm" => TextureFormat::Etc2Rgb8A1Unorm,
1625                    "etc2-rgb8a1unorm-srgb" => TextureFormat::Etc2Rgb8A1UnormSrgb,
1626                    "etc2-rgba8unorm" => TextureFormat::Etc2Rgba8Unorm,
1627                    "etc2-rgba8unorm-srgb" => TextureFormat::Etc2Rgba8UnormSrgb,
1628                    "eac-r11unorm" => TextureFormat::EacR11Unorm,
1629                    "eac-r11snorm" => TextureFormat::EacR11Snorm,
1630                    "eac-rg11unorm" => TextureFormat::EacRg11Unorm,
1631                    "eac-rg11snorm" => TextureFormat::EacRg11Snorm,
1632                    other => {
1633                        if let Some(parts) = other.strip_prefix("astc-") {
1634                            let (block, channel) = parts
1635                                .split_once('-')
1636                                .ok_or_else(|| E::invalid_value(Unexpected::Str(s), &self))?;
1637
1638                            let block = match block {
1639                                "4x4" => AstcBlock::B4x4,
1640                                "5x4" => AstcBlock::B5x4,
1641                                "5x5" => AstcBlock::B5x5,
1642                                "6x5" => AstcBlock::B6x5,
1643                                "6x6" => AstcBlock::B6x6,
1644                                "8x5" => AstcBlock::B8x5,
1645                                "8x6" => AstcBlock::B8x6,
1646                                "8x8" => AstcBlock::B8x8,
1647                                "10x5" => AstcBlock::B10x5,
1648                                "10x6" => AstcBlock::B10x6,
1649                                "10x8" => AstcBlock::B10x8,
1650                                "10x10" => AstcBlock::B10x10,
1651                                "12x10" => AstcBlock::B12x10,
1652                                "12x12" => AstcBlock::B12x12,
1653                                _ => return Err(E::invalid_value(Unexpected::Str(s), &self)),
1654                            };
1655
1656                            let channel = match channel {
1657                                "unorm" => AstcChannel::Unorm,
1658                                "unorm-srgb" => AstcChannel::UnormSrgb,
1659                                "hdr" => AstcChannel::Hdr,
1660                                _ => return Err(E::invalid_value(Unexpected::Str(s), &self)),
1661                            };
1662
1663                            TextureFormat::Astc { block, channel }
1664                        } else {
1665                            return Err(E::invalid_value(Unexpected::Str(s), &self));
1666                        }
1667                    }
1668                };
1669
1670                Ok(format)
1671            }
1672        }
1673
1674        deserializer.deserialize_str(TextureFormatVisitor)
1675    }
1676}
1677
1678#[cfg(any(feature = "serde", test))]
1679impl Serialize for TextureFormat {
1680    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1681    where
1682        S: serde::Serializer,
1683    {
1684        let s: alloc::string::String;
1685        let name = match *self {
1686            TextureFormat::R8Unorm => "r8unorm",
1687            TextureFormat::R8Snorm => "r8snorm",
1688            TextureFormat::R8Uint => "r8uint",
1689            TextureFormat::R8Sint => "r8sint",
1690            TextureFormat::R16Uint => "r16uint",
1691            TextureFormat::R16Sint => "r16sint",
1692            TextureFormat::R16Unorm => "r16unorm",
1693            TextureFormat::R16Snorm => "r16snorm",
1694            TextureFormat::R16Float => "r16float",
1695            TextureFormat::Rg8Unorm => "rg8unorm",
1696            TextureFormat::Rg8Snorm => "rg8snorm",
1697            TextureFormat::Rg8Uint => "rg8uint",
1698            TextureFormat::Rg8Sint => "rg8sint",
1699            TextureFormat::R32Uint => "r32uint",
1700            TextureFormat::R32Sint => "r32sint",
1701            TextureFormat::R32Float => "r32float",
1702            TextureFormat::Rg16Uint => "rg16uint",
1703            TextureFormat::Rg16Sint => "rg16sint",
1704            TextureFormat::Rg16Unorm => "rg16unorm",
1705            TextureFormat::Rg16Snorm => "rg16snorm",
1706            TextureFormat::Rg16Float => "rg16float",
1707            TextureFormat::Rgba8Unorm => "rgba8unorm",
1708            TextureFormat::Rgba8UnormSrgb => "rgba8unorm-srgb",
1709            TextureFormat::Rgba8Snorm => "rgba8snorm",
1710            TextureFormat::Rgba8Uint => "rgba8uint",
1711            TextureFormat::Rgba8Sint => "rgba8sint",
1712            TextureFormat::Bgra8Unorm => "bgra8unorm",
1713            TextureFormat::Bgra8UnormSrgb => "bgra8unorm-srgb",
1714            TextureFormat::Rgb10a2Uint => "rgb10a2uint",
1715            TextureFormat::Rgb10a2Unorm => "rgb10a2unorm",
1716            TextureFormat::Rg11b10Ufloat => "rg11b10ufloat",
1717            TextureFormat::R64Uint => "r64uint",
1718            TextureFormat::Rg32Uint => "rg32uint",
1719            TextureFormat::Rg32Sint => "rg32sint",
1720            TextureFormat::Rg32Float => "rg32float",
1721            TextureFormat::Rgba16Uint => "rgba16uint",
1722            TextureFormat::Rgba16Sint => "rgba16sint",
1723            TextureFormat::Rgba16Unorm => "rgba16unorm",
1724            TextureFormat::Rgba16Snorm => "rgba16snorm",
1725            TextureFormat::Rgba16Float => "rgba16float",
1726            TextureFormat::Rgba32Uint => "rgba32uint",
1727            TextureFormat::Rgba32Sint => "rgba32sint",
1728            TextureFormat::Rgba32Float => "rgba32float",
1729            TextureFormat::Stencil8 => "stencil8",
1730            TextureFormat::Depth32Float => "depth32float",
1731            TextureFormat::Depth16Unorm => "depth16unorm",
1732            TextureFormat::Depth32FloatStencil8 => "depth32float-stencil8",
1733            TextureFormat::Depth24Plus => "depth24plus",
1734            TextureFormat::Depth24PlusStencil8 => "depth24plus-stencil8",
1735            TextureFormat::NV12 => "nv12",
1736            TextureFormat::P010 => "p010",
1737            TextureFormat::Rgb9e5Ufloat => "rgb9e5ufloat",
1738            TextureFormat::Bc1RgbaUnorm => "bc1-rgba-unorm",
1739            TextureFormat::Bc1RgbaUnormSrgb => "bc1-rgba-unorm-srgb",
1740            TextureFormat::Bc2RgbaUnorm => "bc2-rgba-unorm",
1741            TextureFormat::Bc2RgbaUnormSrgb => "bc2-rgba-unorm-srgb",
1742            TextureFormat::Bc3RgbaUnorm => "bc3-rgba-unorm",
1743            TextureFormat::Bc3RgbaUnormSrgb => "bc3-rgba-unorm-srgb",
1744            TextureFormat::Bc4RUnorm => "bc4-r-unorm",
1745            TextureFormat::Bc4RSnorm => "bc4-r-snorm",
1746            TextureFormat::Bc5RgUnorm => "bc5-rg-unorm",
1747            TextureFormat::Bc5RgSnorm => "bc5-rg-snorm",
1748            TextureFormat::Bc6hRgbUfloat => "bc6h-rgb-ufloat",
1749            TextureFormat::Bc6hRgbFloat => "bc6h-rgb-float",
1750            TextureFormat::Bc7RgbaUnorm => "bc7-rgba-unorm",
1751            TextureFormat::Bc7RgbaUnormSrgb => "bc7-rgba-unorm-srgb",
1752            TextureFormat::Etc2Rgb8Unorm => "etc2-rgb8unorm",
1753            TextureFormat::Etc2Rgb8UnormSrgb => "etc2-rgb8unorm-srgb",
1754            TextureFormat::Etc2Rgb8A1Unorm => "etc2-rgb8a1unorm",
1755            TextureFormat::Etc2Rgb8A1UnormSrgb => "etc2-rgb8a1unorm-srgb",
1756            TextureFormat::Etc2Rgba8Unorm => "etc2-rgba8unorm",
1757            TextureFormat::Etc2Rgba8UnormSrgb => "etc2-rgba8unorm-srgb",
1758            TextureFormat::EacR11Unorm => "eac-r11unorm",
1759            TextureFormat::EacR11Snorm => "eac-r11snorm",
1760            TextureFormat::EacRg11Unorm => "eac-rg11unorm",
1761            TextureFormat::EacRg11Snorm => "eac-rg11snorm",
1762            TextureFormat::Astc { block, channel } => {
1763                let block = match block {
1764                    AstcBlock::B4x4 => "4x4",
1765                    AstcBlock::B5x4 => "5x4",
1766                    AstcBlock::B5x5 => "5x5",
1767                    AstcBlock::B6x5 => "6x5",
1768                    AstcBlock::B6x6 => "6x6",
1769                    AstcBlock::B8x5 => "8x5",
1770                    AstcBlock::B8x6 => "8x6",
1771                    AstcBlock::B8x8 => "8x8",
1772                    AstcBlock::B10x5 => "10x5",
1773                    AstcBlock::B10x6 => "10x6",
1774                    AstcBlock::B10x8 => "10x8",
1775                    AstcBlock::B10x10 => "10x10",
1776                    AstcBlock::B12x10 => "12x10",
1777                    AstcBlock::B12x12 => "12x12",
1778                };
1779
1780                let channel = match channel {
1781                    AstcChannel::Unorm => "unorm",
1782                    AstcChannel::UnormSrgb => "unorm-srgb",
1783                    AstcChannel::Hdr => "hdr",
1784                };
1785
1786                s = alloc::format!("astc-{block}-{channel}");
1787                &s
1788            }
1789        };
1790        serializer.serialize_str(name)
1791    }
1792}
1793
1794bitflags::bitflags! {
1795    /// Feature flags for a texture format.
1796    #[repr(transparent)]
1797    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1798    #[cfg_attr(feature = "serde", serde(transparent))]
1799    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1800    pub struct TextureFormatFeatureFlags: u32 {
1801        /// If not present, the texture can't be sampled with a filtering sampler.
1802        /// This may overwrite TextureSampleType::Float.filterable
1803        const FILTERABLE = 1 << 0;
1804        /// Allows [`TextureDescriptor::sample_count`] to be `2`.
1805        const MULTISAMPLE_X2 = 1 << 1;
1806        /// Allows [`TextureDescriptor::sample_count`] to be `4`.
1807        const MULTISAMPLE_X4 = 1 << 2 ;
1808        /// Allows [`TextureDescriptor::sample_count`] to be `8`.
1809        const MULTISAMPLE_X8 = 1 << 3 ;
1810        /// Allows [`TextureDescriptor::sample_count`] to be `16`.
1811        const MULTISAMPLE_X16 = 1 << 4;
1812        /// Allows a texture of this format to back a view passed as `resolve_target`
1813        /// to a render pass for an automatic driver-implemented resolve.
1814        const MULTISAMPLE_RESOLVE = 1 << 5;
1815        /// When used as a STORAGE texture, then a texture with this format can be bound with
1816        /// [`StorageTextureAccess::ReadOnly`].
1817        const STORAGE_READ_ONLY = 1 << 6;
1818        /// When used as a STORAGE texture, then a texture with this format can be bound with
1819        /// [`StorageTextureAccess::WriteOnly`].
1820        const STORAGE_WRITE_ONLY = 1 << 7;
1821        /// When used as a STORAGE texture, then a texture with this format can be bound with
1822        /// [`StorageTextureAccess::ReadWrite`].
1823        const STORAGE_READ_WRITE = 1 << 8;
1824        /// When used as a STORAGE texture, then a texture with this format can be bound with
1825        /// [`StorageTextureAccess::Atomic`].
1826        const STORAGE_ATOMIC = 1 << 9;
1827        /// If not present, the texture can't be blended into the render target.
1828        const BLENDABLE = 1 << 10;
1829    }
1830}
1831
1832impl TextureFormatFeatureFlags {
1833    /// Sample count supported by a given texture format.
1834    ///
1835    /// returns `true` if `count` is a supported sample count.
1836    #[must_use]
1837    pub fn sample_count_supported(&self, count: u32) -> bool {
1838        use TextureFormatFeatureFlags as tfsc;
1839
1840        match count {
1841            1 => true,
1842            2 => self.contains(tfsc::MULTISAMPLE_X2),
1843            4 => self.contains(tfsc::MULTISAMPLE_X4),
1844            8 => self.contains(tfsc::MULTISAMPLE_X8),
1845            16 => self.contains(tfsc::MULTISAMPLE_X16),
1846            _ => false,
1847        }
1848    }
1849
1850    /// A `Vec` of supported sample counts.
1851    #[must_use]
1852    pub fn supported_sample_counts(&self) -> Vec<u32> {
1853        let all_possible_sample_counts: [u32; 5] = [1, 2, 4, 8, 16];
1854        all_possible_sample_counts
1855            .into_iter()
1856            .filter(|&sc| self.sample_count_supported(sc))
1857            .collect()
1858    }
1859}
1860
1861/// Features supported by a given texture format
1862///
1863/// Features are defined by WebGPU specification unless [`Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES`] is enabled.
1864#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
1865#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1866pub struct TextureFormatFeatures {
1867    /// Valid bits for `TextureDescriptor::Usage` provided for format creation.
1868    pub allowed_usages: TextureUsages,
1869    /// Additional property flags for the format.
1870    pub flags: TextureFormatFeatureFlags,
1871}
1872
1873#[cfg(test)]
1874mod tests {
1875    use super::*;
1876
1877    #[test]
1878    fn texture_format_serialize() {
1879        use alloc::string::ToString;
1880
1881        assert_eq!(
1882            serde_json::to_string(&TextureFormat::R8Unorm).unwrap(),
1883            "\"r8unorm\"".to_string()
1884        );
1885        assert_eq!(
1886            serde_json::to_string(&TextureFormat::R8Snorm).unwrap(),
1887            "\"r8snorm\"".to_string()
1888        );
1889        assert_eq!(
1890            serde_json::to_string(&TextureFormat::R8Uint).unwrap(),
1891            "\"r8uint\"".to_string()
1892        );
1893        assert_eq!(
1894            serde_json::to_string(&TextureFormat::R8Sint).unwrap(),
1895            "\"r8sint\"".to_string()
1896        );
1897        assert_eq!(
1898            serde_json::to_string(&TextureFormat::R16Uint).unwrap(),
1899            "\"r16uint\"".to_string()
1900        );
1901        assert_eq!(
1902            serde_json::to_string(&TextureFormat::R16Sint).unwrap(),
1903            "\"r16sint\"".to_string()
1904        );
1905        assert_eq!(
1906            serde_json::to_string(&TextureFormat::R16Unorm).unwrap(),
1907            "\"r16unorm\"".to_string()
1908        );
1909        assert_eq!(
1910            serde_json::to_string(&TextureFormat::R16Snorm).unwrap(),
1911            "\"r16snorm\"".to_string()
1912        );
1913        assert_eq!(
1914            serde_json::to_string(&TextureFormat::R16Float).unwrap(),
1915            "\"r16float\"".to_string()
1916        );
1917        assert_eq!(
1918            serde_json::to_string(&TextureFormat::Rg8Unorm).unwrap(),
1919            "\"rg8unorm\"".to_string()
1920        );
1921        assert_eq!(
1922            serde_json::to_string(&TextureFormat::Rg8Snorm).unwrap(),
1923            "\"rg8snorm\"".to_string()
1924        );
1925        assert_eq!(
1926            serde_json::to_string(&TextureFormat::Rg8Uint).unwrap(),
1927            "\"rg8uint\"".to_string()
1928        );
1929        assert_eq!(
1930            serde_json::to_string(&TextureFormat::Rg8Sint).unwrap(),
1931            "\"rg8sint\"".to_string()
1932        );
1933        assert_eq!(
1934            serde_json::to_string(&TextureFormat::R32Uint).unwrap(),
1935            "\"r32uint\"".to_string()
1936        );
1937        assert_eq!(
1938            serde_json::to_string(&TextureFormat::R32Sint).unwrap(),
1939            "\"r32sint\"".to_string()
1940        );
1941        assert_eq!(
1942            serde_json::to_string(&TextureFormat::R32Float).unwrap(),
1943            "\"r32float\"".to_string()
1944        );
1945        assert_eq!(
1946            serde_json::to_string(&TextureFormat::Rg16Uint).unwrap(),
1947            "\"rg16uint\"".to_string()
1948        );
1949        assert_eq!(
1950            serde_json::to_string(&TextureFormat::Rg16Sint).unwrap(),
1951            "\"rg16sint\"".to_string()
1952        );
1953        assert_eq!(
1954            serde_json::to_string(&TextureFormat::Rg16Unorm).unwrap(),
1955            "\"rg16unorm\"".to_string()
1956        );
1957        assert_eq!(
1958            serde_json::to_string(&TextureFormat::Rg16Snorm).unwrap(),
1959            "\"rg16snorm\"".to_string()
1960        );
1961        assert_eq!(
1962            serde_json::to_string(&TextureFormat::Rg16Float).unwrap(),
1963            "\"rg16float\"".to_string()
1964        );
1965        assert_eq!(
1966            serde_json::to_string(&TextureFormat::Rgba8Unorm).unwrap(),
1967            "\"rgba8unorm\"".to_string()
1968        );
1969        assert_eq!(
1970            serde_json::to_string(&TextureFormat::Rgba8UnormSrgb).unwrap(),
1971            "\"rgba8unorm-srgb\"".to_string()
1972        );
1973        assert_eq!(
1974            serde_json::to_string(&TextureFormat::Rgba8Snorm).unwrap(),
1975            "\"rgba8snorm\"".to_string()
1976        );
1977        assert_eq!(
1978            serde_json::to_string(&TextureFormat::Rgba8Uint).unwrap(),
1979            "\"rgba8uint\"".to_string()
1980        );
1981        assert_eq!(
1982            serde_json::to_string(&TextureFormat::Rgba8Sint).unwrap(),
1983            "\"rgba8sint\"".to_string()
1984        );
1985        assert_eq!(
1986            serde_json::to_string(&TextureFormat::Bgra8Unorm).unwrap(),
1987            "\"bgra8unorm\"".to_string()
1988        );
1989        assert_eq!(
1990            serde_json::to_string(&TextureFormat::Bgra8UnormSrgb).unwrap(),
1991            "\"bgra8unorm-srgb\"".to_string()
1992        );
1993        assert_eq!(
1994            serde_json::to_string(&TextureFormat::Rgb10a2Uint).unwrap(),
1995            "\"rgb10a2uint\"".to_string()
1996        );
1997        assert_eq!(
1998            serde_json::to_string(&TextureFormat::Rgb10a2Unorm).unwrap(),
1999            "\"rgb10a2unorm\"".to_string()
2000        );
2001        assert_eq!(
2002            serde_json::to_string(&TextureFormat::Rg11b10Ufloat).unwrap(),
2003            "\"rg11b10ufloat\"".to_string()
2004        );
2005        assert_eq!(
2006            serde_json::to_string(&TextureFormat::R64Uint).unwrap(),
2007            "\"r64uint\"".to_string()
2008        );
2009        assert_eq!(
2010            serde_json::to_string(&TextureFormat::Rg32Uint).unwrap(),
2011            "\"rg32uint\"".to_string()
2012        );
2013        assert_eq!(
2014            serde_json::to_string(&TextureFormat::Rg32Sint).unwrap(),
2015            "\"rg32sint\"".to_string()
2016        );
2017        assert_eq!(
2018            serde_json::to_string(&TextureFormat::Rg32Float).unwrap(),
2019            "\"rg32float\"".to_string()
2020        );
2021        assert_eq!(
2022            serde_json::to_string(&TextureFormat::Rgba16Uint).unwrap(),
2023            "\"rgba16uint\"".to_string()
2024        );
2025        assert_eq!(
2026            serde_json::to_string(&TextureFormat::Rgba16Sint).unwrap(),
2027            "\"rgba16sint\"".to_string()
2028        );
2029        assert_eq!(
2030            serde_json::to_string(&TextureFormat::Rgba16Unorm).unwrap(),
2031            "\"rgba16unorm\"".to_string()
2032        );
2033        assert_eq!(
2034            serde_json::to_string(&TextureFormat::Rgba16Snorm).unwrap(),
2035            "\"rgba16snorm\"".to_string()
2036        );
2037        assert_eq!(
2038            serde_json::to_string(&TextureFormat::Rgba16Float).unwrap(),
2039            "\"rgba16float\"".to_string()
2040        );
2041        assert_eq!(
2042            serde_json::to_string(&TextureFormat::Rgba32Uint).unwrap(),
2043            "\"rgba32uint\"".to_string()
2044        );
2045        assert_eq!(
2046            serde_json::to_string(&TextureFormat::Rgba32Sint).unwrap(),
2047            "\"rgba32sint\"".to_string()
2048        );
2049        assert_eq!(
2050            serde_json::to_string(&TextureFormat::Rgba32Float).unwrap(),
2051            "\"rgba32float\"".to_string()
2052        );
2053        assert_eq!(
2054            serde_json::to_string(&TextureFormat::Stencil8).unwrap(),
2055            "\"stencil8\"".to_string()
2056        );
2057        assert_eq!(
2058            serde_json::to_string(&TextureFormat::Depth32Float).unwrap(),
2059            "\"depth32float\"".to_string()
2060        );
2061        assert_eq!(
2062            serde_json::to_string(&TextureFormat::Depth16Unorm).unwrap(),
2063            "\"depth16unorm\"".to_string()
2064        );
2065        assert_eq!(
2066            serde_json::to_string(&TextureFormat::Depth32FloatStencil8).unwrap(),
2067            "\"depth32float-stencil8\"".to_string()
2068        );
2069        assert_eq!(
2070            serde_json::to_string(&TextureFormat::Depth24Plus).unwrap(),
2071            "\"depth24plus\"".to_string()
2072        );
2073        assert_eq!(
2074            serde_json::to_string(&TextureFormat::Depth24PlusStencil8).unwrap(),
2075            "\"depth24plus-stencil8\"".to_string()
2076        );
2077        assert_eq!(
2078            serde_json::to_string(&TextureFormat::Rgb9e5Ufloat).unwrap(),
2079            "\"rgb9e5ufloat\"".to_string()
2080        );
2081        assert_eq!(
2082            serde_json::to_string(&TextureFormat::Bc1RgbaUnorm).unwrap(),
2083            "\"bc1-rgba-unorm\"".to_string()
2084        );
2085        assert_eq!(
2086            serde_json::to_string(&TextureFormat::Bc1RgbaUnormSrgb).unwrap(),
2087            "\"bc1-rgba-unorm-srgb\"".to_string()
2088        );
2089        assert_eq!(
2090            serde_json::to_string(&TextureFormat::Bc2RgbaUnorm).unwrap(),
2091            "\"bc2-rgba-unorm\"".to_string()
2092        );
2093        assert_eq!(
2094            serde_json::to_string(&TextureFormat::Bc2RgbaUnormSrgb).unwrap(),
2095            "\"bc2-rgba-unorm-srgb\"".to_string()
2096        );
2097        assert_eq!(
2098            serde_json::to_string(&TextureFormat::Bc3RgbaUnorm).unwrap(),
2099            "\"bc3-rgba-unorm\"".to_string()
2100        );
2101        assert_eq!(
2102            serde_json::to_string(&TextureFormat::Bc3RgbaUnormSrgb).unwrap(),
2103            "\"bc3-rgba-unorm-srgb\"".to_string()
2104        );
2105        assert_eq!(
2106            serde_json::to_string(&TextureFormat::Bc4RUnorm).unwrap(),
2107            "\"bc4-r-unorm\"".to_string()
2108        );
2109        assert_eq!(
2110            serde_json::to_string(&TextureFormat::Bc4RSnorm).unwrap(),
2111            "\"bc4-r-snorm\"".to_string()
2112        );
2113        assert_eq!(
2114            serde_json::to_string(&TextureFormat::Bc5RgUnorm).unwrap(),
2115            "\"bc5-rg-unorm\"".to_string()
2116        );
2117        assert_eq!(
2118            serde_json::to_string(&TextureFormat::Bc5RgSnorm).unwrap(),
2119            "\"bc5-rg-snorm\"".to_string()
2120        );
2121        assert_eq!(
2122            serde_json::to_string(&TextureFormat::Bc6hRgbUfloat).unwrap(),
2123            "\"bc6h-rgb-ufloat\"".to_string()
2124        );
2125        assert_eq!(
2126            serde_json::to_string(&TextureFormat::Bc6hRgbFloat).unwrap(),
2127            "\"bc6h-rgb-float\"".to_string()
2128        );
2129        assert_eq!(
2130            serde_json::to_string(&TextureFormat::Bc7RgbaUnorm).unwrap(),
2131            "\"bc7-rgba-unorm\"".to_string()
2132        );
2133        assert_eq!(
2134            serde_json::to_string(&TextureFormat::Bc7RgbaUnormSrgb).unwrap(),
2135            "\"bc7-rgba-unorm-srgb\"".to_string()
2136        );
2137        assert_eq!(
2138            serde_json::to_string(&TextureFormat::Etc2Rgb8Unorm).unwrap(),
2139            "\"etc2-rgb8unorm\"".to_string()
2140        );
2141        assert_eq!(
2142            serde_json::to_string(&TextureFormat::Etc2Rgb8UnormSrgb).unwrap(),
2143            "\"etc2-rgb8unorm-srgb\"".to_string()
2144        );
2145        assert_eq!(
2146            serde_json::to_string(&TextureFormat::Etc2Rgb8A1Unorm).unwrap(),
2147            "\"etc2-rgb8a1unorm\"".to_string()
2148        );
2149        assert_eq!(
2150            serde_json::to_string(&TextureFormat::Etc2Rgb8A1UnormSrgb).unwrap(),
2151            "\"etc2-rgb8a1unorm-srgb\"".to_string()
2152        );
2153        assert_eq!(
2154            serde_json::to_string(&TextureFormat::Etc2Rgba8Unorm).unwrap(),
2155            "\"etc2-rgba8unorm\"".to_string()
2156        );
2157        assert_eq!(
2158            serde_json::to_string(&TextureFormat::Etc2Rgba8UnormSrgb).unwrap(),
2159            "\"etc2-rgba8unorm-srgb\"".to_string()
2160        );
2161        assert_eq!(
2162            serde_json::to_string(&TextureFormat::EacR11Unorm).unwrap(),
2163            "\"eac-r11unorm\"".to_string()
2164        );
2165        assert_eq!(
2166            serde_json::to_string(&TextureFormat::EacR11Snorm).unwrap(),
2167            "\"eac-r11snorm\"".to_string()
2168        );
2169        assert_eq!(
2170            serde_json::to_string(&TextureFormat::EacRg11Unorm).unwrap(),
2171            "\"eac-rg11unorm\"".to_string()
2172        );
2173        assert_eq!(
2174            serde_json::to_string(&TextureFormat::EacRg11Snorm).unwrap(),
2175            "\"eac-rg11snorm\"".to_string()
2176        );
2177    }
2178
2179    #[test]
2180    fn texture_format_deserialize() {
2181        assert_eq!(
2182            serde_json::from_str::<TextureFormat>("\"r8unorm\"").unwrap(),
2183            TextureFormat::R8Unorm
2184        );
2185        assert_eq!(
2186            serde_json::from_str::<TextureFormat>("\"r8snorm\"").unwrap(),
2187            TextureFormat::R8Snorm
2188        );
2189        assert_eq!(
2190            serde_json::from_str::<TextureFormat>("\"r8uint\"").unwrap(),
2191            TextureFormat::R8Uint
2192        );
2193        assert_eq!(
2194            serde_json::from_str::<TextureFormat>("\"r8sint\"").unwrap(),
2195            TextureFormat::R8Sint
2196        );
2197        assert_eq!(
2198            serde_json::from_str::<TextureFormat>("\"r16uint\"").unwrap(),
2199            TextureFormat::R16Uint
2200        );
2201        assert_eq!(
2202            serde_json::from_str::<TextureFormat>("\"r16sint\"").unwrap(),
2203            TextureFormat::R16Sint
2204        );
2205        assert_eq!(
2206            serde_json::from_str::<TextureFormat>("\"r16unorm\"").unwrap(),
2207            TextureFormat::R16Unorm
2208        );
2209        assert_eq!(
2210            serde_json::from_str::<TextureFormat>("\"r16snorm\"").unwrap(),
2211            TextureFormat::R16Snorm
2212        );
2213        assert_eq!(
2214            serde_json::from_str::<TextureFormat>("\"r16float\"").unwrap(),
2215            TextureFormat::R16Float
2216        );
2217        assert_eq!(
2218            serde_json::from_str::<TextureFormat>("\"rg8unorm\"").unwrap(),
2219            TextureFormat::Rg8Unorm
2220        );
2221        assert_eq!(
2222            serde_json::from_str::<TextureFormat>("\"rg8snorm\"").unwrap(),
2223            TextureFormat::Rg8Snorm
2224        );
2225        assert_eq!(
2226            serde_json::from_str::<TextureFormat>("\"rg8uint\"").unwrap(),
2227            TextureFormat::Rg8Uint
2228        );
2229        assert_eq!(
2230            serde_json::from_str::<TextureFormat>("\"rg8sint\"").unwrap(),
2231            TextureFormat::Rg8Sint
2232        );
2233        assert_eq!(
2234            serde_json::from_str::<TextureFormat>("\"r32uint\"").unwrap(),
2235            TextureFormat::R32Uint
2236        );
2237        assert_eq!(
2238            serde_json::from_str::<TextureFormat>("\"r32sint\"").unwrap(),
2239            TextureFormat::R32Sint
2240        );
2241        assert_eq!(
2242            serde_json::from_str::<TextureFormat>("\"r32float\"").unwrap(),
2243            TextureFormat::R32Float
2244        );
2245        assert_eq!(
2246            serde_json::from_str::<TextureFormat>("\"rg16uint\"").unwrap(),
2247            TextureFormat::Rg16Uint
2248        );
2249        assert_eq!(
2250            serde_json::from_str::<TextureFormat>("\"rg16sint\"").unwrap(),
2251            TextureFormat::Rg16Sint
2252        );
2253        assert_eq!(
2254            serde_json::from_str::<TextureFormat>("\"rg16unorm\"").unwrap(),
2255            TextureFormat::Rg16Unorm
2256        );
2257        assert_eq!(
2258            serde_json::from_str::<TextureFormat>("\"rg16snorm\"").unwrap(),
2259            TextureFormat::Rg16Snorm
2260        );
2261        assert_eq!(
2262            serde_json::from_str::<TextureFormat>("\"rg16float\"").unwrap(),
2263            TextureFormat::Rg16Float
2264        );
2265        assert_eq!(
2266            serde_json::from_str::<TextureFormat>("\"rgba8unorm\"").unwrap(),
2267            TextureFormat::Rgba8Unorm
2268        );
2269        assert_eq!(
2270            serde_json::from_str::<TextureFormat>("\"rgba8unorm-srgb\"").unwrap(),
2271            TextureFormat::Rgba8UnormSrgb
2272        );
2273        assert_eq!(
2274            serde_json::from_str::<TextureFormat>("\"rgba8snorm\"").unwrap(),
2275            TextureFormat::Rgba8Snorm
2276        );
2277        assert_eq!(
2278            serde_json::from_str::<TextureFormat>("\"rgba8uint\"").unwrap(),
2279            TextureFormat::Rgba8Uint
2280        );
2281        assert_eq!(
2282            serde_json::from_str::<TextureFormat>("\"rgba8sint\"").unwrap(),
2283            TextureFormat::Rgba8Sint
2284        );
2285        assert_eq!(
2286            serde_json::from_str::<TextureFormat>("\"bgra8unorm\"").unwrap(),
2287            TextureFormat::Bgra8Unorm
2288        );
2289        assert_eq!(
2290            serde_json::from_str::<TextureFormat>("\"bgra8unorm-srgb\"").unwrap(),
2291            TextureFormat::Bgra8UnormSrgb
2292        );
2293        assert_eq!(
2294            serde_json::from_str::<TextureFormat>("\"rgb10a2uint\"").unwrap(),
2295            TextureFormat::Rgb10a2Uint
2296        );
2297        assert_eq!(
2298            serde_json::from_str::<TextureFormat>("\"rgb10a2unorm\"").unwrap(),
2299            TextureFormat::Rgb10a2Unorm
2300        );
2301        assert_eq!(
2302            serde_json::from_str::<TextureFormat>("\"rg11b10ufloat\"").unwrap(),
2303            TextureFormat::Rg11b10Ufloat
2304        );
2305        assert_eq!(
2306            serde_json::from_str::<TextureFormat>("\"r64uint\"").unwrap(),
2307            TextureFormat::R64Uint
2308        );
2309        assert_eq!(
2310            serde_json::from_str::<TextureFormat>("\"rg32uint\"").unwrap(),
2311            TextureFormat::Rg32Uint
2312        );
2313        assert_eq!(
2314            serde_json::from_str::<TextureFormat>("\"rg32sint\"").unwrap(),
2315            TextureFormat::Rg32Sint
2316        );
2317        assert_eq!(
2318            serde_json::from_str::<TextureFormat>("\"rg32float\"").unwrap(),
2319            TextureFormat::Rg32Float
2320        );
2321        assert_eq!(
2322            serde_json::from_str::<TextureFormat>("\"rgba16uint\"").unwrap(),
2323            TextureFormat::Rgba16Uint
2324        );
2325        assert_eq!(
2326            serde_json::from_str::<TextureFormat>("\"rgba16sint\"").unwrap(),
2327            TextureFormat::Rgba16Sint
2328        );
2329        assert_eq!(
2330            serde_json::from_str::<TextureFormat>("\"rgba16unorm\"").unwrap(),
2331            TextureFormat::Rgba16Unorm
2332        );
2333        assert_eq!(
2334            serde_json::from_str::<TextureFormat>("\"rgba16snorm\"").unwrap(),
2335            TextureFormat::Rgba16Snorm
2336        );
2337        assert_eq!(
2338            serde_json::from_str::<TextureFormat>("\"rgba16float\"").unwrap(),
2339            TextureFormat::Rgba16Float
2340        );
2341        assert_eq!(
2342            serde_json::from_str::<TextureFormat>("\"rgba32uint\"").unwrap(),
2343            TextureFormat::Rgba32Uint
2344        );
2345        assert_eq!(
2346            serde_json::from_str::<TextureFormat>("\"rgba32sint\"").unwrap(),
2347            TextureFormat::Rgba32Sint
2348        );
2349        assert_eq!(
2350            serde_json::from_str::<TextureFormat>("\"rgba32float\"").unwrap(),
2351            TextureFormat::Rgba32Float
2352        );
2353        assert_eq!(
2354            serde_json::from_str::<TextureFormat>("\"stencil8\"").unwrap(),
2355            TextureFormat::Stencil8
2356        );
2357        assert_eq!(
2358            serde_json::from_str::<TextureFormat>("\"depth32float\"").unwrap(),
2359            TextureFormat::Depth32Float
2360        );
2361        assert_eq!(
2362            serde_json::from_str::<TextureFormat>("\"depth16unorm\"").unwrap(),
2363            TextureFormat::Depth16Unorm
2364        );
2365        assert_eq!(
2366            serde_json::from_str::<TextureFormat>("\"depth32float-stencil8\"").unwrap(),
2367            TextureFormat::Depth32FloatStencil8
2368        );
2369        assert_eq!(
2370            serde_json::from_str::<TextureFormat>("\"depth24plus\"").unwrap(),
2371            TextureFormat::Depth24Plus
2372        );
2373        assert_eq!(
2374            serde_json::from_str::<TextureFormat>("\"depth24plus-stencil8\"").unwrap(),
2375            TextureFormat::Depth24PlusStencil8
2376        );
2377        assert_eq!(
2378            serde_json::from_str::<TextureFormat>("\"rgb9e5ufloat\"").unwrap(),
2379            TextureFormat::Rgb9e5Ufloat
2380        );
2381        assert_eq!(
2382            serde_json::from_str::<TextureFormat>("\"bc1-rgba-unorm\"").unwrap(),
2383            TextureFormat::Bc1RgbaUnorm
2384        );
2385        assert_eq!(
2386            serde_json::from_str::<TextureFormat>("\"bc1-rgba-unorm-srgb\"").unwrap(),
2387            TextureFormat::Bc1RgbaUnormSrgb
2388        );
2389        assert_eq!(
2390            serde_json::from_str::<TextureFormat>("\"bc2-rgba-unorm\"").unwrap(),
2391            TextureFormat::Bc2RgbaUnorm
2392        );
2393        assert_eq!(
2394            serde_json::from_str::<TextureFormat>("\"bc2-rgba-unorm-srgb\"").unwrap(),
2395            TextureFormat::Bc2RgbaUnormSrgb
2396        );
2397        assert_eq!(
2398            serde_json::from_str::<TextureFormat>("\"bc3-rgba-unorm\"").unwrap(),
2399            TextureFormat::Bc3RgbaUnorm
2400        );
2401        assert_eq!(
2402            serde_json::from_str::<TextureFormat>("\"bc3-rgba-unorm-srgb\"").unwrap(),
2403            TextureFormat::Bc3RgbaUnormSrgb
2404        );
2405        assert_eq!(
2406            serde_json::from_str::<TextureFormat>("\"bc4-r-unorm\"").unwrap(),
2407            TextureFormat::Bc4RUnorm
2408        );
2409        assert_eq!(
2410            serde_json::from_str::<TextureFormat>("\"bc4-r-snorm\"").unwrap(),
2411            TextureFormat::Bc4RSnorm
2412        );
2413        assert_eq!(
2414            serde_json::from_str::<TextureFormat>("\"bc5-rg-unorm\"").unwrap(),
2415            TextureFormat::Bc5RgUnorm
2416        );
2417        assert_eq!(
2418            serde_json::from_str::<TextureFormat>("\"bc5-rg-snorm\"").unwrap(),
2419            TextureFormat::Bc5RgSnorm
2420        );
2421        assert_eq!(
2422            serde_json::from_str::<TextureFormat>("\"bc6h-rgb-ufloat\"").unwrap(),
2423            TextureFormat::Bc6hRgbUfloat
2424        );
2425        assert_eq!(
2426            serde_json::from_str::<TextureFormat>("\"bc6h-rgb-float\"").unwrap(),
2427            TextureFormat::Bc6hRgbFloat
2428        );
2429        assert_eq!(
2430            serde_json::from_str::<TextureFormat>("\"bc7-rgba-unorm\"").unwrap(),
2431            TextureFormat::Bc7RgbaUnorm
2432        );
2433        assert_eq!(
2434            serde_json::from_str::<TextureFormat>("\"bc7-rgba-unorm-srgb\"").unwrap(),
2435            TextureFormat::Bc7RgbaUnormSrgb
2436        );
2437        assert_eq!(
2438            serde_json::from_str::<TextureFormat>("\"etc2-rgb8unorm\"").unwrap(),
2439            TextureFormat::Etc2Rgb8Unorm
2440        );
2441        assert_eq!(
2442            serde_json::from_str::<TextureFormat>("\"etc2-rgb8unorm-srgb\"").unwrap(),
2443            TextureFormat::Etc2Rgb8UnormSrgb
2444        );
2445        assert_eq!(
2446            serde_json::from_str::<TextureFormat>("\"etc2-rgb8a1unorm\"").unwrap(),
2447            TextureFormat::Etc2Rgb8A1Unorm
2448        );
2449        assert_eq!(
2450            serde_json::from_str::<TextureFormat>("\"etc2-rgb8a1unorm-srgb\"").unwrap(),
2451            TextureFormat::Etc2Rgb8A1UnormSrgb
2452        );
2453        assert_eq!(
2454            serde_json::from_str::<TextureFormat>("\"etc2-rgba8unorm\"").unwrap(),
2455            TextureFormat::Etc2Rgba8Unorm
2456        );
2457        assert_eq!(
2458            serde_json::from_str::<TextureFormat>("\"etc2-rgba8unorm-srgb\"").unwrap(),
2459            TextureFormat::Etc2Rgba8UnormSrgb
2460        );
2461        assert_eq!(
2462            serde_json::from_str::<TextureFormat>("\"eac-r11unorm\"").unwrap(),
2463            TextureFormat::EacR11Unorm
2464        );
2465        assert_eq!(
2466            serde_json::from_str::<TextureFormat>("\"eac-r11snorm\"").unwrap(),
2467            TextureFormat::EacR11Snorm
2468        );
2469        assert_eq!(
2470            serde_json::from_str::<TextureFormat>("\"eac-rg11unorm\"").unwrap(),
2471            TextureFormat::EacRg11Unorm
2472        );
2473        assert_eq!(
2474            serde_json::from_str::<TextureFormat>("\"eac-rg11snorm\"").unwrap(),
2475            TextureFormat::EacRg11Snorm
2476        );
2477    }
2478}