wgpu_types/
lib.rs

1//! This library describes the API surface of WebGPU that is agnostic of the backend.
2//! This API is used for targeting both Web and Native.
3
4#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
5#![allow(
6    // We don't use syntax sugar where it's not necessary.
7    clippy::match_like_matches_macro,
8)]
9#![warn(clippy::ptr_as_ptr, missing_docs, unsafe_op_in_unsafe_fn)]
10#![no_std]
11
12#[cfg(feature = "std")]
13extern crate std;
14
15extern crate alloc;
16
17use alloc::{string::String, vec, vec::Vec};
18use core::{
19    hash::{Hash, Hasher},
20    mem::size_of,
21    num::NonZeroU32,
22    ops::Range,
23};
24
25#[cfg(any(feature = "serde", test))]
26use {
27    alloc::format,
28    serde::{Deserialize, Serialize},
29};
30
31pub mod assertions;
32mod counters;
33mod env;
34pub mod instance;
35pub mod math;
36
37pub use counters::*;
38pub use instance::*;
39
40/// Integral type used for buffer offsets.
41pub type BufferAddress = u64;
42/// Integral type used for buffer slice sizes.
43pub type BufferSize = core::num::NonZeroU64;
44/// Integral type used for binding locations in shaders.
45pub type ShaderLocation = u32;
46/// Integral type used for dynamic bind group offsets.
47pub type DynamicOffset = u32;
48
49/// Buffer-Texture copies must have [`bytes_per_row`] aligned to this number.
50///
51/// This doesn't apply to [`Queue::write_texture`][Qwt].
52///
53/// [`bytes_per_row`]: TexelCopyBufferLayout::bytes_per_row
54/// [Qwt]: ../wgpu/struct.Queue.html#method.write_texture
55pub const COPY_BYTES_PER_ROW_ALIGNMENT: u32 = 256;
56/// An offset into the query resolve buffer has to be aligned to this.
57pub const QUERY_RESOLVE_BUFFER_ALIGNMENT: BufferAddress = 256;
58/// Buffer to buffer copy as well as buffer clear offsets and sizes must be aligned to this number.
59pub const COPY_BUFFER_ALIGNMENT: BufferAddress = 4;
60/// Size to align mappings.
61pub const MAP_ALIGNMENT: BufferAddress = 8;
62/// Vertex buffer strides have to be aligned to this number.
63pub const VERTEX_STRIDE_ALIGNMENT: BufferAddress = 4;
64/// Alignment all push constants need
65pub const PUSH_CONSTANT_ALIGNMENT: u32 = 4;
66/// Maximum queries in a query set
67pub const QUERY_SET_MAX_QUERIES: u32 = 4096;
68/// Size of a single piece of query data.
69pub const QUERY_SIZE: u32 = 8;
70
71/// Backends supported by wgpu.
72#[repr(u8)]
73#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
74#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
75pub enum Backend {
76    /// Dummy backend, used for testing.
77    Empty = 0,
78    /// Vulkan API (Windows, Linux, Android, MacOS via `vulkan-portability`/MoltenVK)
79    Vulkan = 1,
80    /// Metal API (Apple platforms)
81    Metal = 2,
82    /// Direct3D-12 (Windows)
83    Dx12 = 3,
84    /// OpenGL 3.3+ (Windows), OpenGL ES 3.0+ (Linux, Android, MacOS via Angle), and WebGL2
85    Gl = 4,
86    /// WebGPU in the browser
87    BrowserWebGpu = 5,
88}
89
90impl Backend {
91    /// Returns the string name of the backend.
92    #[must_use]
93    pub const fn to_str(self) -> &'static str {
94        match self {
95            Backend::Empty => "empty",
96            Backend::Vulkan => "vulkan",
97            Backend::Metal => "metal",
98            Backend::Dx12 => "dx12",
99            Backend::Gl => "gl",
100            Backend::BrowserWebGpu => "webgpu",
101        }
102    }
103}
104
105impl core::fmt::Display for Backend {
106    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
107        f.write_str(self.to_str())
108    }
109}
110
111/// Power Preference when choosing a physical adapter.
112///
113/// Corresponds to [WebGPU `GPUPowerPreference`](
114/// https://gpuweb.github.io/gpuweb/#enumdef-gpupowerpreference).
115#[repr(C)]
116#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Default)]
117#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
118#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
119pub enum PowerPreference {
120    #[default]
121    /// Power usage is not considered when choosing an adapter.
122    None = 0,
123    /// Adapter that uses the least possible power. This is often an integrated GPU.
124    LowPower = 1,
125    /// Adapter that has the highest performance. This is often a discrete GPU.
126    HighPerformance = 2,
127}
128
129impl PowerPreference {
130    /// Get a power preference from the environment variable `WGPU_POWER_PREF`.
131    pub fn from_env() -> Option<Self> {
132        let env = crate::env::var("WGPU_POWER_PREF")?;
133        match env.to_lowercase().as_str() {
134            "low" => Some(Self::LowPower),
135            "high" => Some(Self::HighPerformance),
136            "none" => Some(Self::None),
137            _ => None,
138        }
139    }
140}
141
142bitflags::bitflags! {
143    /// Represents the backends that wgpu will use.
144    #[repr(transparent)]
145    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
146    #[cfg_attr(feature = "serde", serde(transparent))]
147    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
148    pub struct Backends: u32 {
149        /// Supported on Windows, Linux/Android, and macOS/iOS via Vulkan Portability (with the Vulkan feature enabled)
150        const VULKAN = 1 << Backend::Vulkan as u32;
151        /// Supported on Linux/Android, the web through webassembly via WebGL, and Windows and
152        /// macOS/iOS via ANGLE
153        const GL = 1 << Backend::Gl as u32;
154        /// Supported on macOS/iOS
155        const METAL = 1 << Backend::Metal as u32;
156        /// Supported on Windows 10 and later
157        const DX12 = 1 << Backend::Dx12 as u32;
158        /// Supported when targeting the web through webassembly with the `webgpu` feature enabled.
159        ///
160        /// The WebGPU backend is special in several ways:
161        /// It is not not implemented by `wgpu_core` and instead by the higher level `wgpu` crate.
162        /// Whether WebGPU is targeted is decided upon the creation of the `wgpu::Instance`,
163        /// *not* upon adapter creation. See `wgpu::Instance::new`.
164        const BROWSER_WEBGPU = 1 << Backend::BrowserWebGpu as u32;
165        /// All the apis that wgpu offers first tier of support for.
166        ///
167        /// * [`Backends::VULKAN`]
168        /// * [`Backends::METAL`]
169        /// * [`Backends::DX12`]
170        /// * [`Backends::BROWSER_WEBGPU`]
171        const PRIMARY = Self::VULKAN.bits()
172            | Self::METAL.bits()
173            | Self::DX12.bits()
174            | Self::BROWSER_WEBGPU.bits();
175        /// All the apis that wgpu offers second tier of support for. These may
176        /// be unsupported/still experimental.
177        ///
178        /// * [`Backends::GL`]
179        const SECONDARY = Self::GL.bits();
180    }
181}
182
183impl Default for Backends {
184    fn default() -> Self {
185        Self::all()
186    }
187}
188
189impl From<Backend> for Backends {
190    fn from(backend: Backend) -> Self {
191        Self::from_bits(1 << backend as u32).unwrap()
192    }
193}
194
195impl Backends {
196    /// Gets a set of backends from the environment variable `WGPU_BACKEND`.
197    ///
198    /// See [`Self::from_comma_list()`] for the format of the string.
199    pub fn from_env() -> Option<Self> {
200        let env = crate::env::var("WGPU_BACKEND")?;
201        Some(Self::from_comma_list(&env))
202    }
203
204    /// Takes the given options, modifies them based on the `WGPU_BACKEND` environment variable, and returns the result.
205    pub fn with_env(&self) -> Self {
206        if let Some(env) = Self::from_env() {
207            env
208        } else {
209            *self
210        }
211    }
212
213    /// Generates a set of backends from a comma separated list of case-insensitive backend names.
214    ///
215    /// Whitespace is stripped, so both 'gl, dx12' and 'gl,dx12' are valid.
216    ///
217    /// Always returns WEBGPU on wasm over webgpu.
218    ///
219    /// Names:
220    /// - vulkan = "vulkan" or "vk"
221    /// - dx12   = "dx12" or "d3d12"
222    /// - metal  = "metal" or "mtl"
223    /// - gles   = "opengl" or "gles" or "gl"
224    /// - webgpu = "webgpu"
225    pub fn from_comma_list(string: &str) -> Self {
226        let mut backends = Self::empty();
227        for backend in string.to_lowercase().split(',') {
228            backends |= match backend.trim() {
229                "vulkan" | "vk" => Self::VULKAN,
230                "dx12" | "d3d12" => Self::DX12,
231                "metal" | "mtl" => Self::METAL,
232                "opengl" | "gles" | "gl" => Self::GL,
233                "webgpu" => Self::BROWSER_WEBGPU,
234                b => {
235                    log::warn!("unknown backend string '{}'", b);
236                    continue;
237                }
238            }
239        }
240
241        if backends.is_empty() {
242            log::warn!("no valid backend strings found!");
243        }
244
245        backends
246    }
247}
248
249/// Options for requesting adapter.
250///
251/// Corresponds to [WebGPU `GPURequestAdapterOptions`](
252/// https://gpuweb.github.io/gpuweb/#dictdef-gpurequestadapteroptions).
253#[repr(C)]
254#[derive(Clone, Debug, PartialEq, Eq, Hash)]
255#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
256pub struct RequestAdapterOptions<S> {
257    /// Power preference for the adapter.
258    pub power_preference: PowerPreference,
259    /// Indicates that only a fallback adapter can be returned. This is generally a "software"
260    /// implementation on the system.
261    pub force_fallback_adapter: bool,
262    /// Surface that is required to be presentable with the requested adapter. This does not
263    /// create the surface, only guarantees that the adapter can present to said surface.
264    /// For WebGL, this is strictly required, as an adapter can not be created without a surface.
265    pub compatible_surface: Option<S>,
266}
267
268impl<S> Default for RequestAdapterOptions<S> {
269    fn default() -> Self {
270        Self {
271            power_preference: PowerPreference::default(),
272            force_fallback_adapter: false,
273            compatible_surface: None,
274        }
275    }
276}
277
278//TODO: make robust resource access configurable
279
280bitflags::bitflags! {
281    /// Features that are not guaranteed to be supported.
282    ///
283    /// These are either part of the webgpu standard, or are extension features supported by
284    /// wgpu when targeting native.
285    ///
286    /// If you want to use a feature, you need to first verify that the adapter supports
287    /// the feature. If the adapter does not support the feature, requesting a device with it enabled
288    /// will panic.
289    ///
290    /// Corresponds to [WebGPU `GPUFeatureName`](
291    /// https://gpuweb.github.io/gpuweb/#enumdef-gpufeaturename).
292    #[repr(transparent)]
293    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
294    #[cfg_attr(feature = "serde", serde(transparent))]
295    #[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash)]
296    pub struct Features: u64 {
297        //
298        // ---- Start numbering at 1 << 0 ----
299        //
300        // WebGPU features:
301        //
302
303        // API:
304
305        /// By default, polygon depth is clipped to 0-1 range before/during rasterization.
306        /// Anything outside of that range is rejected, and respective fragments are not touched.
307        ///
308        /// With this extension, we can disabling clipping. That allows
309        /// shadow map occluders to be rendered into a tighter depth range.
310        ///
311        /// Supported platforms:
312        /// - desktops
313        /// - some mobile chips
314        ///
315        /// This is a web and native feature.
316        const DEPTH_CLIP_CONTROL = 1 << 0;
317
318        /// Allows for explicit creation of textures of format [`TextureFormat::Depth32FloatStencil8`]
319        ///
320        /// Supported platforms:
321        /// - Vulkan (mostly)
322        /// - DX12
323        /// - Metal
324        /// - OpenGL
325        ///
326        /// This is a web and native feature.
327        const DEPTH32FLOAT_STENCIL8 = 1 << 1;
328
329        /// Enables BCn family of compressed textures. All BCn textures use 4x4 pixel blocks
330        /// with 8 or 16 bytes per block.
331        ///
332        /// Compressed textures sacrifice some quality in exchange for significantly reduced
333        /// bandwidth usage.
334        ///
335        /// Support for this feature guarantees availability of [`TextureUsages::COPY_SRC | TextureUsages::COPY_DST | TextureUsages::TEXTURE_BINDING`] for BCn formats.
336        /// [`Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES`] may enable additional usages.
337        ///
338        /// This feature guarantees availability of sliced-3d textures for BC formats when combined with TEXTURE_COMPRESSION_BC_SLICED_3D.
339        ///
340        /// Supported Platforms:
341        /// - desktops
342        /// - Mobile (All Apple9 and some Apple7 and Apple8 devices)
343        ///
344        /// This is a web and native feature.
345        const TEXTURE_COMPRESSION_BC = 1 << 2;
346
347
348        /// Allows the 3d dimension for textures with BC compressed formats.
349        ///
350        /// This feature must be used in combination with TEXTURE_COMPRESSION_BC to enable 3D textures with BC compression.
351        /// It does not enable the BC formats by itself.
352        ///
353        /// Supported Platforms:
354        /// - desktops
355        /// - Mobile (All Apple9 and some Apple7 and Apple8 devices)
356        ///
357        /// This is a web and native feature.
358        const TEXTURE_COMPRESSION_BC_SLICED_3D = 1 << 3;
359
360        /// Enables ETC family of compressed textures. All ETC textures use 4x4 pixel blocks.
361        /// ETC2 RGB and RGBA1 are 8 bytes per block. RTC2 RGBA8 and EAC are 16 bytes per block.
362        ///
363        /// Compressed textures sacrifice some quality in exchange for significantly reduced
364        /// bandwidth usage.
365        ///
366        /// Support for this feature guarantees availability of [`TextureUsages::COPY_SRC | TextureUsages::COPY_DST | TextureUsages::TEXTURE_BINDING`] for ETC2 formats.
367        /// [`Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES`] may enable additional usages.
368        ///
369        /// Supported Platforms:
370        /// - Vulkan on Intel
371        /// - Mobile (some)
372        ///
373        /// This is a web and native feature.
374        const TEXTURE_COMPRESSION_ETC2 = 1 << 4;
375
376        /// Enables ASTC family of compressed textures. ASTC textures use pixel blocks varying from 4x4 to 12x12.
377        /// Blocks are always 16 bytes.
378        ///
379        /// Compressed textures sacrifice some quality in exchange for significantly reduced
380        /// bandwidth usage.
381        ///
382        /// Support for this feature guarantees availability of [`TextureUsages::COPY_SRC | TextureUsages::COPY_DST | TextureUsages::TEXTURE_BINDING`] for ASTC formats with Unorm/UnormSrgb channel type.
383        /// [`Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES`] may enable additional usages.
384        ///
385        /// Supported Platforms:
386        /// - Vulkan on Intel
387        /// - Mobile (some)
388        ///
389        /// This is a web and native feature.
390        const TEXTURE_COMPRESSION_ASTC = 1 << 5;
391
392        /// Enables use of Timestamp Queries. These queries tell the current gpu timestamp when
393        /// all work before the query is finished.
394        ///
395        /// This feature allows the use of
396        /// - [`RenderPassDescriptor::timestamp_writes`]
397        /// - [`ComputePassDescriptor::timestamp_writes`]
398        /// to write out timestamps.
399        ///
400        /// For arbitrary timestamp write commands on encoders refer to [`Features::TIMESTAMP_QUERY_INSIDE_ENCODERS`].
401        /// For arbitrary timestamp write commands on passes refer to [`Features::TIMESTAMP_QUERY_INSIDE_PASSES`].
402        ///
403        /// They must be resolved using [`CommandEncoder::resolve_query_set`] into a buffer,
404        /// then the result must be multiplied by the timestamp period [`Queue::get_timestamp_period`]
405        /// to get the timestamp in nanoseconds. Multiple timestamps can then be diffed to get the
406        /// time for operations between them to finish.
407        ///
408        /// Supported Platforms:
409        /// - Vulkan
410        /// - DX12
411        /// - Metal
412        ///
413        /// This is a web and native feature.
414        const TIMESTAMP_QUERY = 1 << 6;
415
416        /// Allows non-zero value for the `first_instance` member in indirect draw calls.
417        ///
418        /// If this feature is not enabled, and the `first_instance` member is non-zero, the behavior may be:
419        /// - The draw call is ignored.
420        /// - The draw call is executed as if the `first_instance` is zero.
421        /// - The draw call is executed with the correct `first_instance` value.
422        ///
423        /// Supported Platforms:
424        /// - Vulkan (mostly)
425        /// - DX12
426        /// - Metal on Apple3+ or Mac1+
427        /// - OpenGL (Desktop 4.2+ with ARB_shader_draw_parameters only)
428        ///
429        /// Not Supported:
430        /// - OpenGL ES / WebGL
431        ///
432        /// This is a web and native feature.
433        const INDIRECT_FIRST_INSTANCE = 1 << 7;
434
435        /// Allows shaders to acquire the FP16 ability
436        ///
437        /// Note: this is not supported in `naga` yet, only through `spirv-passthrough` right now.
438        ///
439        /// Supported Platforms:
440        /// - Vulkan
441        /// - Metal
442        ///
443        /// This is a web and native feature.
444        const SHADER_F16 = 1 << 8;
445
446
447        /// Allows for usage of textures of format [`TextureFormat::Rg11b10Ufloat`] as a render target
448        ///
449        /// Supported platforms:
450        /// - Vulkan
451        /// - DX12
452        /// - Metal
453        ///
454        /// This is a web and native feature.
455        const RG11B10UFLOAT_RENDERABLE = 1 << 9;
456
457        /// Allows the [`wgpu::TextureUsages::STORAGE_BINDING`] usage on textures with format [`TextureFormat::Bgra8unorm`]
458        ///
459        /// Supported Platforms:
460        /// - Vulkan
461        /// - DX12
462        /// - Metal
463        ///
464        /// This is a web and native feature.
465        const BGRA8UNORM_STORAGE = 1 << 10;
466
467
468        /// Allows textures with formats "r32float", "rg32float", and "rgba32float" to be filterable.
469        ///
470        /// Supported Platforms:
471        /// - Vulkan (mainly on Desktop GPUs)
472        /// - DX12
473        /// - Metal on macOS or Apple9+ GPUs, optional on iOS/iPadOS with Apple7/8 GPUs
474        /// - GL with one of `GL_ARB_color_buffer_float`/`GL_EXT_color_buffer_float`/`OES_texture_float_linear`
475        ///
476        /// This is a web and native feature.
477        const FLOAT32_FILTERABLE = 1 << 11;
478
479        // Bits 12-18 available for webgpu features. Should you chose to use some of them for
480        // for native features, don't forget to update `all_webgpu_mask` and `all_native_mask`
481        // accordingly.
482
483        //
484        // ---- Restart Numbering for Native Features ---
485        //
486        // Native Features:
487        //
488
489        /// Enables R64Uint image atomic min and max.
490        ///
491        /// Supported platforms:
492        /// - Vulkan (with VK_EXT_shader_image_atomic_int64)
493        /// - DX12 (with SM 6.6+)
494        /// - Metal (with MSL 3.1+)
495        ///
496        /// This is a native only feature.
497        const TEXTURE_INT64_ATOMIC = 1 << 18;
498
499        /// Allows shaders to use f32 atomic load, store, add, sub, and exchange.
500        ///
501        /// Supported platforms:
502        /// - Metal (with MSL 3.0+ and Apple7+/Mac2)
503        /// - Vulkan (with [VK_EXT_shader_atomic_float])
504        ///
505        /// This is a native only feature.
506        ///
507        /// [VK_EXT_shader_atomic_float]: https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_EXT_shader_atomic_float.html
508        const SHADER_FLOAT32_ATOMIC = 1 << 19;
509
510        // The features starting with a ? are features that might become part of the spec or
511        // at the very least we can implement as native features; since they should cover all
512        // possible formats and capabilities across backends.
513        //
514        // ? const FORMATS_TIER_1 = 1 << ??; (https://github.com/gpuweb/gpuweb/issues/3837)
515        // ? const RW_STORAGE_TEXTURE_TIER_1 = 1 << ??; (https://github.com/gpuweb/gpuweb/issues/3838)
516        // ? const NORM16_FILTERABLE = 1 << ??; (https://github.com/gpuweb/gpuweb/issues/3839)
517        // ? const NORM16_RESOLVE = 1 << ??; (https://github.com/gpuweb/gpuweb/issues/3839)
518        // ? const FLOAT32_BLENDABLE = 1 << ??; (https://github.com/gpuweb/gpuweb/issues/3556)
519        // ? const 32BIT_FORMAT_MULTISAMPLE = 1 << ??; (https://github.com/gpuweb/gpuweb/issues/3844)
520        // ? const 32BIT_FORMAT_RESOLVE = 1 << ??; (https://github.com/gpuweb/gpuweb/issues/3844)
521        // ? const TEXTURE_COMPRESSION_ASTC_HDR = 1 << ??; (https://github.com/gpuweb/gpuweb/issues/3856)
522        // TEXTURE_FORMAT_16BIT_NORM & TEXTURE_COMPRESSION_ASTC_HDR will most likely become web features as well
523        // TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES might not be necessary if we have all the texture features implemented
524
525        // Texture Formats:
526
527        /// Enables normalized `16-bit` texture formats.
528        ///
529        /// Supported platforms:
530        /// - Vulkan
531        /// - DX12
532        /// - Metal
533        ///
534        /// This is a native only feature.
535        const TEXTURE_FORMAT_16BIT_NORM = 1 << 20;
536        /// Enables ASTC HDR family of compressed textures.
537        ///
538        /// Compressed textures sacrifice some quality in exchange for significantly reduced
539        /// bandwidth usage.
540        ///
541        /// Support for this feature guarantees availability of [`TextureUsages::COPY_SRC | TextureUsages::COPY_DST | TextureUsages::TEXTURE_BINDING`] for ASTC formats with the HDR channel type.
542        /// [`Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES`] may enable additional usages.
543        ///
544        /// Supported Platforms:
545        /// - Metal
546        /// - Vulkan
547        /// - OpenGL
548        ///
549        /// This is a native only feature.
550        const TEXTURE_COMPRESSION_ASTC_HDR = 1 << 21;
551        /// Enables device specific texture format features.
552        ///
553        /// See `TextureFormatFeatures` for a listing of the features in question.
554        ///
555        /// By default only texture format properties as defined by the WebGPU specification are allowed.
556        /// Enabling this feature flag extends the features of each format to the ones supported by the current device.
557        /// Note that without this flag, read/write storage access is not allowed at all.
558        ///
559        /// This extension does not enable additional formats.
560        ///
561        /// This is a native only feature.
562        const TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES = 1 << 22;
563
564        // API:
565
566        /// Enables use of Pipeline Statistics Queries. These queries tell the count of various operations
567        /// performed between the start and stop call. Call [`RenderPass::begin_pipeline_statistics_query`] to start
568        /// a query, then call [`RenderPass::end_pipeline_statistics_query`] to stop one.
569        ///
570        /// They must be resolved using [`CommandEncoder::resolve_query_set`] into a buffer.
571        /// The rules on how these resolve into buffers are detailed in the documentation for [`PipelineStatisticsTypes`].
572        ///
573        /// Supported Platforms:
574        /// - Vulkan
575        /// - DX12
576        ///
577        /// This is a native only feature with a [proposal](https://github.com/gpuweb/gpuweb/blob/0008bd30da2366af88180b511a5d0d0c1dffbc36/proposals/pipeline-statistics-query.md) for the web.
578        const PIPELINE_STATISTICS_QUERY = 1 << 23;
579        /// Allows for timestamp queries directly on command encoders.
580        ///
581        /// Implies [`Features::TIMESTAMP_QUERY`] is supported.
582        ///
583        /// Additionally allows for timestamp writes on command encoders
584        /// using  [`CommandEncoder::write_timestamp`].
585        ///
586        /// Supported platforms:
587        /// - Vulkan
588        /// - DX12
589        /// - Metal
590        ///
591        /// This is a native only feature.
592        const TIMESTAMP_QUERY_INSIDE_ENCODERS = 1 << 24;
593        /// Allows for timestamp queries directly on command encoders.
594        ///
595        /// Implies [`Features::TIMESTAMP_QUERY`] & [`Features::TIMESTAMP_QUERY_INSIDE_ENCODERS`] is supported.
596        ///
597        /// Additionally allows for timestamp queries to be used inside render & compute passes using:
598        /// - [`RenderPass::write_timestamp`]
599        /// - [`ComputePass::write_timestamp`]
600        ///
601        /// Supported platforms:
602        /// - Vulkan
603        /// - DX12
604        /// - Metal (AMD & Intel, not Apple GPUs)
605        ///
606        /// This is generally not available on tile-based rasterization GPUs.
607        ///
608        /// This is a native only feature with a [proposal](https://github.com/gpuweb/gpuweb/blob/0008bd30da2366af88180b511a5d0d0c1dffbc36/proposals/timestamp-query-inside-passes.md) for the web.
609        const TIMESTAMP_QUERY_INSIDE_PASSES = 1 << 25;
610        /// Webgpu only allows the MAP_READ and MAP_WRITE buffer usage to be matched with
611        /// COPY_DST and COPY_SRC respectively. This removes this requirement.
612        ///
613        /// This is only beneficial on systems that share memory between CPU and GPU. If enabled
614        /// on a system that doesn't, this can severely hinder performance. Only use if you understand
615        /// the consequences.
616        ///
617        /// Supported platforms:
618        /// - Vulkan
619        /// - DX12
620        /// - Metal
621        ///
622        /// This is a native only feature.
623        const MAPPABLE_PRIMARY_BUFFERS = 1 << 26;
624        /// Allows the user to create uniform arrays of textures in shaders:
625        ///
626        /// ex.
627        /// - `var textures: binding_array<texture_2d<f32>, 10>` (WGSL)
628        /// - `uniform texture2D textures[10]` (GLSL)
629        ///
630        /// If [`Features::STORAGE_RESOURCE_BINDING_ARRAY`] is supported as well as this, the user
631        /// may also create uniform arrays of storage textures.
632        ///
633        /// ex.
634        /// - `var textures: array<texture_storage_2d<r32float, write>, 10>` (WGSL)
635        /// - `uniform image2D textures[10]` (GLSL)
636        ///
637        /// This capability allows them to exist and to be indexed by dynamically uniform
638        /// values.
639        ///
640        /// Supported platforms:
641        /// - DX12
642        /// - Metal (with MSL 2.0+ on macOS 10.13+)
643        /// - Vulkan
644        ///
645        /// This is a native only feature.
646        const TEXTURE_BINDING_ARRAY = 1 << 27;
647        /// Allows the user to create arrays of buffers in shaders:
648        ///
649        /// ex.
650        /// - `var<uniform> buffer_array: array<MyBuffer, 10>` (WGSL)
651        /// - `uniform myBuffer { ... } buffer_array[10]` (GLSL)
652        ///
653        /// This capability allows them to exist and to be indexed by dynamically uniform
654        /// values.
655        ///
656        /// If [`Features::STORAGE_RESOURCE_BINDING_ARRAY`] is supported as well as this, the user
657        /// may also create arrays of storage buffers.
658        ///
659        /// ex.
660        /// - `var<storage> buffer_array: array<MyBuffer, 10>` (WGSL)
661        /// - `buffer myBuffer { ... } buffer_array[10]` (GLSL)
662        ///
663        /// Supported platforms:
664        /// - Vulkan
665        ///
666        /// This is a native only feature.
667        const BUFFER_BINDING_ARRAY = 1 << 28;
668        /// Allows the user to create uniform arrays of storage buffers or textures in shaders,
669        /// if resp. [`Features::BUFFER_BINDING_ARRAY`] or [`Features::TEXTURE_BINDING_ARRAY`]
670        /// is supported.
671        ///
672        /// This capability allows them to exist and to be indexed by dynamically uniform
673        /// values.
674        ///
675        /// Supported platforms:
676        /// - Metal (with MSL 2.2+ on macOS 10.13+)
677        /// - Vulkan
678        ///
679        /// This is a native only feature.
680        const STORAGE_RESOURCE_BINDING_ARRAY = 1 << 29;
681        /// Allows shaders to index sampled texture and storage buffer resource arrays with dynamically non-uniform values:
682        ///
683        /// ex. `texture_array[vertex_data]`
684        ///
685        /// In order to use this capability, the corresponding GLSL extension must be enabled like so:
686        ///
687        /// `#extension GL_EXT_nonuniform_qualifier : require`
688        ///
689        /// and then used either as `nonuniformEXT` qualifier in variable declaration:
690        ///
691        /// ex. `layout(location = 0) nonuniformEXT flat in int vertex_data;`
692        ///
693        /// or as `nonuniformEXT` constructor:
694        ///
695        /// ex. `texture_array[nonuniformEXT(vertex_data)]`
696        ///
697        /// WGSL and HLSL do not need any extension.
698        ///
699        /// Supported platforms:
700        /// - DX12
701        /// - Metal (with MSL 2.0+ on macOS 10.13+)
702        /// - Vulkan 1.2+ (or VK_EXT_descriptor_indexing)'s shaderSampledImageArrayNonUniformIndexing & shaderStorageBufferArrayNonUniformIndexing feature)
703        ///
704        /// This is a native only feature.
705        const SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING = 1 << 30;
706        /// Allows shaders to index uniform buffer and storage texture resource arrays with dynamically non-uniform values:
707        ///
708        /// ex. `texture_array[vertex_data]`
709        ///
710        /// In order to use this capability, the corresponding GLSL extension must be enabled like so:
711        ///
712        /// `#extension GL_EXT_nonuniform_qualifier : require`
713        ///
714        /// and then used either as `nonuniformEXT` qualifier in variable declaration:
715        ///
716        /// ex. `layout(location = 0) nonuniformEXT flat in int vertex_data;`
717        ///
718        /// or as `nonuniformEXT` constructor:
719        ///
720        /// ex. `texture_array[nonuniformEXT(vertex_data)]`
721        ///
722        /// WGSL and HLSL do not need any extension.
723        ///
724        /// Supported platforms:
725        /// - DX12
726        /// - Metal (with MSL 2.0+ on macOS 10.13+)
727        /// - Vulkan 1.2+ (or VK_EXT_descriptor_indexing)'s shaderUniformBufferArrayNonUniformIndexing & shaderStorageTextureArrayNonUniformIndexing feature)
728        ///
729        /// This is a native only feature.
730        const UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING = 1 << 31;
731        /// Allows the user to create bind groups containing arrays with less bindings than the BindGroupLayout.
732        ///
733        /// Supported platforms:
734        /// - Vulkan
735        /// - DX12
736        ///
737        /// This is a native only feature.
738        const PARTIALLY_BOUND_BINDING_ARRAY = 1 << 32;
739        /// Allows the user to call [`RenderPass::multi_draw_indirect`] and [`RenderPass::multi_draw_indexed_indirect`].
740        ///
741        /// Allows multiple indirect calls to be dispatched from a single buffer.
742        ///
743        /// Natively Supported Platforms:
744        /// - DX12
745        /// - Vulkan
746        ///
747        /// Emulated Platforms:
748        /// - Metal
749        /// - OpenGL
750        /// - WebGPU
751        ///
752        /// Emulation is preformed by looping over the individual indirect draw calls in the backend. This is still significantly
753        /// faster than enulating it yourself, as wgpu only does draw call validation once.
754        ///
755        /// [`RenderPass::multi_draw_indirect`]: ../wgpu/struct.RenderPass.html#method.multi_draw_indirect
756        /// [`RenderPass::multi_draw_indexed_indirect`]: ../wgpu/struct.RenderPass.html#method.multi_draw_indexed_indirect
757        const MULTI_DRAW_INDIRECT = 1 << 33;
758        /// Allows the user to call [`RenderPass::multi_draw_indirect_count`] and [`RenderPass::multi_draw_indexed_indirect_count`].
759        ///
760        /// This allows the use of a buffer containing the actual number of draw calls.
761        ///
762        /// Supported platforms:
763        /// - DX12
764        /// - Vulkan 1.2+ (or VK_KHR_draw_indirect_count)
765        ///
766        /// This is a native only feature.
767        ///
768        /// [`RenderPass::multi_draw_indirect_count`]: ../wgpu/struct.RenderPass.html#method.multi_draw_indirect_count
769        /// [`RenderPass::multi_draw_indexed_indirect_count`]: ../wgpu/struct.RenderPass.html#method.multi_draw_indexed_indirect_count
770        const MULTI_DRAW_INDIRECT_COUNT = 1 << 34;
771        /// Allows the use of push constants: small, fast bits of memory that can be updated
772        /// inside a [`RenderPass`].
773        ///
774        /// Allows the user to call [`RenderPass::set_push_constants`], provide a non-empty array
775        /// to [`PipelineLayoutDescriptor`], and provide a non-zero limit to [`Limits::max_push_constant_size`].
776        ///
777        /// A block of push constants can be declared in WGSL with `var<push_constant>`:
778        ///
779        /// ```rust,ignore
780        /// struct PushConstants { example: f32, }
781        /// var<push_constant> c: PushConstants;
782        /// ```
783        ///
784        /// In GLSL, this corresponds to `layout(push_constant) uniform Name {..}`.
785        ///
786        /// Supported platforms:
787        /// - DX12
788        /// - Vulkan
789        /// - Metal
790        /// - OpenGL (emulated with uniforms)
791        ///
792        /// This is a native only feature.
793        ///
794        /// [`RenderPass`]: ../wgpu/struct.RenderPass.html
795        /// [`PipelineLayoutDescriptor`]: ../wgpu/struct.PipelineLayoutDescriptor.html
796        /// [`RenderPass::set_push_constants`]: ../wgpu/struct.RenderPass.html#method.set_push_constants
797        const PUSH_CONSTANTS = 1 << 35;
798        /// Allows the use of [`AddressMode::ClampToBorder`] with a border color
799        /// of [`SamplerBorderColor::Zero`].
800        ///
801        /// Supported platforms:
802        /// - DX12
803        /// - Vulkan
804        /// - Metal
805        /// - OpenGL
806        ///
807        /// This is a native only feature.
808        const ADDRESS_MODE_CLAMP_TO_ZERO = 1 << 36;
809        /// Allows the use of [`AddressMode::ClampToBorder`] with a border color
810        /// other than [`SamplerBorderColor::Zero`].
811        ///
812        /// Supported platforms:
813        /// - DX12
814        /// - Vulkan
815        /// - Metal (macOS 10.12+ only)
816        /// - OpenGL
817        ///
818        /// This is a native only feature.
819        const ADDRESS_MODE_CLAMP_TO_BORDER = 1 << 37;
820        /// Allows the user to set [`PolygonMode::Line`] in [`PrimitiveState::polygon_mode`]
821        ///
822        /// This allows drawing polygons/triangles as lines (wireframe) instead of filled
823        ///
824        /// Supported platforms:
825        /// - DX12
826        /// - Vulkan
827        /// - Metal
828        ///
829        /// This is a native only feature.
830        const POLYGON_MODE_LINE = 1 << 38;
831        /// Allows the user to set [`PolygonMode::Point`] in [`PrimitiveState::polygon_mode`]
832        ///
833        /// This allows only drawing the vertices of polygons/triangles instead of filled
834        ///
835        /// Supported platforms:
836        /// - Vulkan
837        ///
838        /// This is a native only feature.
839        const POLYGON_MODE_POINT = 1 << 39;
840        /// Allows the user to set a overestimation-conservative-rasterization in [`PrimitiveState::conservative`]
841        ///
842        /// Processing of degenerate triangles/lines is hardware specific.
843        /// Only triangles are supported.
844        ///
845        /// Supported platforms:
846        /// - Vulkan
847        ///
848        /// This is a native only feature.
849        const CONSERVATIVE_RASTERIZATION = 1 << 40;
850        /// Enables bindings of writable storage buffers and textures visible to vertex shaders.
851        ///
852        /// Note: some (tiled-based) platforms do not support vertex shaders with any side-effects.
853        ///
854        /// Supported Platforms:
855        /// - All
856        ///
857        /// This is a native only feature.
858        const VERTEX_WRITABLE_STORAGE = 1 << 41;
859        /// Enables clear to zero for textures.
860        ///
861        /// Supported platforms:
862        /// - All
863        ///
864        /// This is a native only feature.
865        const CLEAR_TEXTURE = 1 << 42;
866        /// Enables creating shader modules from SPIR-V binary data (unsafe).
867        ///
868        /// SPIR-V data is not parsed or interpreted in any way; you can use
869        /// [`wgpu::make_spirv_raw!`] to check for alignment and magic number when converting from
870        /// raw bytes.
871        ///
872        /// Supported platforms:
873        /// - Vulkan, in case shader's requested capabilities and extensions agree with
874        /// Vulkan implementation.
875        ///
876        /// This is a native only feature.
877        const SPIRV_SHADER_PASSTHROUGH = 1 << 43;
878        /// Enables multiview render passes and `builtin(view_index)` in vertex shaders.
879        ///
880        /// Supported platforms:
881        /// - Vulkan
882        /// - OpenGL (web only)
883        ///
884        /// This is a native only feature.
885        const MULTIVIEW = 1 << 44;
886        /// Enables using 64-bit types for vertex attributes.
887        ///
888        /// Requires SHADER_FLOAT64.
889        ///
890        /// Supported Platforms: N/A
891        ///
892        /// This is a native only feature.
893        const VERTEX_ATTRIBUTE_64BIT = 1 << 45;
894        /// Enables image atomic fetch add, and, xor, or, min, and max for R32Uint and R32Sint textures.
895        ///
896        /// Supported platforms:
897        /// - Vulkan
898        /// - DX12
899        /// - Metal (with MSL 3.1+)
900        ///
901        /// This is a native only feature.
902        const TEXTURE_ATOMIC = 1 << 46;
903        /// Allows for creation of textures of format [`TextureFormat::NV12`]
904        ///
905        /// Supported platforms:
906        /// - DX12
907        /// - Vulkan
908        ///
909        /// This is a native only feature.
910        const TEXTURE_FORMAT_NV12 = 1 << 47;
911        /// ***THIS IS EXPERIMENTAL:*** Features enabled by this may have
912        /// major bugs in them and are expected to be subject to breaking changes, suggestions
913        /// for the API exposed by this should be posted on [the ray-tracing issue](https://github.com/gfx-rs/wgpu/issues/1040)
914        ///
915        /// Allows for the creation of ray-tracing acceleration structures. Currently,
916        /// ray-tracing acceleration structures are only useful when used with [Features::EXPERIMENTAL_RAY_QUERY]
917        ///
918        /// Supported platforms:
919        /// - Vulkan
920        ///
921        /// This is a native-only feature.
922        const EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE = 1 << 48;
923
924        // Shader:
925
926        /// ***THIS IS EXPERIMENTAL:*** Features enabled by this may have
927        /// major bugs in it and are expected to be subject to breaking changes, suggestions
928        /// for the API exposed by this should be posted on [the ray-tracing issue](https://github.com/gfx-rs/wgpu/issues/1040)
929        ///
930        /// Allows for the creation of ray-tracing queries within shaders.
931        ///
932        /// Supported platforms:
933        /// - Vulkan
934        ///
935        /// This is a native-only feature.
936        const EXPERIMENTAL_RAY_QUERY = 1 << 49;
937        /// Enables 64-bit floating point types in SPIR-V shaders.
938        ///
939        /// Note: even when supported by GPU hardware, 64-bit floating point operations are
940        /// frequently between 16 and 64 _times_ slower than equivalent operations on 32-bit floats.
941        ///
942        /// Supported Platforms:
943        /// - Vulkan
944        ///
945        /// This is a native only feature.
946        const SHADER_F64 = 1 << 50;
947        /// Allows shaders to use i16. Not currently supported in `naga`, only available through `spirv-passthrough`.
948        ///
949        /// Supported platforms:
950        /// - Vulkan
951        ///
952        /// This is a native only feature.
953        const SHADER_I16 = 1 << 51;
954        /// Enables `builtin(primitive_index)` in fragment shaders.
955        ///
956        /// Note: enables geometry processing for pipelines using the builtin.
957        /// This may come with a significant performance impact on some hardware.
958        /// Other pipelines are not affected.
959        ///
960        /// Supported platforms:
961        /// - Vulkan
962        /// - DX12
963        /// - Metal (some)
964        /// - OpenGL (some)
965        ///
966        /// This is a native only feature.
967        const SHADER_PRIMITIVE_INDEX = 1 << 52;
968        /// Allows shaders to use the `early_depth_test` attribute.
969        ///
970        /// Supported platforms:
971        /// - GLES 3.1+
972        ///
973        /// This is a native only feature.
974        const SHADER_EARLY_DEPTH_TEST = 1 << 53;
975        /// Allows two outputs from a shader to be used for blending.
976        /// Note that dual-source blending doesn't support multiple render targets.
977        ///
978        /// For more info see the OpenGL ES extension GL_EXT_blend_func_extended.
979        ///
980        /// Supported platforms:
981        /// - OpenGL ES (with GL_EXT_blend_func_extended)
982        /// - Metal (with MSL 1.2+)
983        /// - Vulkan (with dualSrcBlend)
984        /// - DX12
985        const DUAL_SOURCE_BLENDING = 1 << 54;
986        /// Allows shaders to use i64 and u64.
987        ///
988        /// Supported platforms:
989        /// - Vulkan
990        /// - DX12 (DXC only)
991        /// - Metal (with MSL 2.3+)
992        ///
993        /// This is a native only feature.
994        const SHADER_INT64 = 1 << 55;
995        /// Allows compute and fragment shaders to use the subgroup operation built-ins
996        ///
997        /// Supported Platforms:
998        /// - Vulkan
999        /// - DX12
1000        /// - Metal
1001        ///
1002        /// This is a native only feature.
1003        const SUBGROUP = 1 << 56;
1004        /// Allows vertex shaders to use the subgroup operation built-ins
1005        ///
1006        /// Supported Platforms:
1007        /// - Vulkan
1008        ///
1009        /// This is a native only feature.
1010        const SUBGROUP_VERTEX = 1 << 57;
1011        /// Allows shaders to use the subgroup barrier
1012        ///
1013        /// Supported Platforms:
1014        /// - Vulkan
1015        /// - Metal
1016        ///
1017        /// This is a native only feature.
1018        const SUBGROUP_BARRIER = 1 << 58;
1019        /// Allows the use of pipeline cache objects
1020        ///
1021        /// Supported platforms:
1022        /// - Vulkan
1023        ///
1024        /// Unimplemented Platforms:
1025        /// - DX12
1026        /// - Metal
1027        const PIPELINE_CACHE = 1 << 59;
1028        /// Allows shaders to use i64 and u64 atomic min and max.
1029        ///
1030        /// Supported platforms:
1031        /// - Vulkan (with VK_KHR_shader_atomic_int64)
1032        /// - DX12 (with SM 6.6+)
1033        /// - Metal (with MSL 2.4+)
1034        ///
1035        /// This is a native only feature.
1036        const SHADER_INT64_ATOMIC_MIN_MAX = 1 << 60;
1037        /// Allows shaders to use all i64 and u64 atomic operations.
1038        ///
1039        /// Supported platforms:
1040        /// - Vulkan (with VK_KHR_shader_atomic_int64)
1041        /// - DX12 (with SM 6.6+)
1042        ///
1043        /// This is a native only feature.
1044        const SHADER_INT64_ATOMIC_ALL_OPS = 1 << 61;
1045        /// Allows using the [VK_GOOGLE_display_timing] Vulkan extension.
1046        ///
1047        /// This is used for frame pacing to reduce latency, and is generally only available on Android.
1048        ///
1049        /// This feature does not have a `wgpu`-level API, and so users of wgpu wishing
1050        /// to use this functionality must access it using various `as_hal` functions,
1051        /// primarily [`Surface::as_hal()`], to then use.
1052        ///
1053        /// Supported platforms:
1054        /// - Vulkan (with [VK_GOOGLE_display_timing])
1055        ///
1056        /// This is a native only feature.
1057        ///
1058        /// [VK_GOOGLE_display_timing]: https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_GOOGLE_display_timing.html
1059        /// [`Surface::as_hal()`]: https://docs.rs/wgpu/latest/wgpu/struct.Surface.html#method.as_hal
1060        const VULKAN_GOOGLE_DISPLAY_TIMING = 1 << 62;
1061
1062        /// Allows using the [VK_KHR_external_memory_win32] Vulkan extension.
1063        ///
1064        /// Supported platforms:
1065        /// - Vulkan (with [VK_KHR_external_memory_win32])
1066        ///
1067        /// This is a native only feature.
1068        ///
1069        /// [VK_KHR_external_memory_win32]: https://registry.khronos.org/vulkan/specs/latest/man/html/VK_KHR_external_memory_win32.html
1070        const VULKAN_EXTERNAL_MEMORY_WIN32 = 1 << 63;
1071    }
1072}
1073
1074impl Features {
1075    /// Mask of all features which are part of the upstream WebGPU standard.
1076    #[must_use]
1077    pub const fn all_webgpu_mask() -> Self {
1078        Self::from_bits_truncate(0x3FFFF)
1079    }
1080
1081    /// Mask of all features that are only available when targeting native (not web).
1082    #[must_use]
1083    pub const fn all_native_mask() -> Self {
1084        Self::from_bits_truncate(!Self::all_webgpu_mask().bits())
1085    }
1086
1087    /// Vertex formats allowed for creating and building BLASes
1088    #[must_use]
1089    pub fn allowed_vertex_formats_for_blas(&self) -> Vec<VertexFormat> {
1090        let mut formats = Vec::new();
1091        if self.contains(Self::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE) {
1092            formats.push(VertexFormat::Float32x3);
1093        }
1094        formats
1095    }
1096}
1097
1098/// Represents the sets of limits an adapter/device supports.
1099///
1100/// We provide three different defaults.
1101/// - [`Limits::downlevel_defaults()`]. This is a set of limits that is guaranteed to work on almost
1102///   all backends, including "downlevel" backends such as OpenGL and D3D11, other than WebGL. For
1103///   most applications we recommend using these limits, assuming they are high enough for your
1104///   application, and you do not intent to support WebGL.
1105/// - [`Limits::downlevel_webgl2_defaults()`] This is a set of limits that is lower even than the
1106///   [`downlevel_defaults()`], configured to be low enough to support running in the browser using
1107///   WebGL2.
1108/// - [`Limits::default()`]. This is the set of limits that is guaranteed to work on all modern
1109///   backends and is guaranteed to be supported by WebGPU. Applications needing more modern
1110///   features can use this as a reasonable set of limits if they are targeting only desktop and
1111///   modern mobile devices.
1112///
1113/// We recommend starting with the most restrictive limits you can and manually increasing the
1114/// limits you need boosted. This will let you stay running on all hardware that supports the limits
1115/// you need.
1116///
1117/// Limits "better" than the default must be supported by the adapter and requested when requesting
1118/// a device. If limits "better" than the adapter supports are requested, requesting a device will
1119/// panic. Once a device is requested, you may only use resources up to the limits requested _even_
1120/// if the adapter supports "better" limits.
1121///
1122/// Requesting limits that are "better" than you need may cause performance to decrease because the
1123/// implementation needs to support more than is needed. You should ideally only request exactly
1124/// what you need.
1125///
1126/// Corresponds to [WebGPU `GPUSupportedLimits`](
1127/// https://gpuweb.github.io/gpuweb/#gpusupportedlimits).
1128///
1129/// [`downlevel_defaults()`]: Limits::downlevel_defaults
1130#[repr(C)]
1131#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1132#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1133#[cfg_attr(feature = "serde", serde(rename_all = "camelCase", default))]
1134pub struct Limits {
1135    /// Maximum allowed value for the `size.width` of a texture created with `TextureDimension::D1`.
1136    /// Defaults to 8192. Higher is "better".
1137    #[cfg_attr(feature = "serde", serde(rename = "maxTextureDimension1D"))]
1138    pub max_texture_dimension_1d: u32,
1139    /// Maximum allowed value for the `size.width` and `size.height` of a texture created with `TextureDimension::D2`.
1140    /// Defaults to 8192. Higher is "better".
1141    #[cfg_attr(feature = "serde", serde(rename = "maxTextureDimension2D"))]
1142    pub max_texture_dimension_2d: u32,
1143    /// Maximum allowed value for the `size.width`, `size.height`, and `size.depth_or_array_layers`
1144    /// of a texture created with `TextureDimension::D3`.
1145    /// Defaults to 2048. Higher is "better".
1146    #[cfg_attr(feature = "serde", serde(rename = "maxTextureDimension3D"))]
1147    pub max_texture_dimension_3d: u32,
1148    /// Maximum allowed value for the `size.depth_or_array_layers` of a texture created with `TextureDimension::D2`.
1149    /// Defaults to 256. Higher is "better".
1150    pub max_texture_array_layers: u32,
1151    /// Amount of bind groups that can be attached to a pipeline at the same time. Defaults to 4. Higher is "better".
1152    pub max_bind_groups: u32,
1153    /// Maximum binding index allowed in `create_bind_group_layout`. Defaults to 1000. Higher is "better".
1154    pub max_bindings_per_bind_group: u32,
1155    /// Amount of uniform buffer bindings that can be dynamic in a single pipeline. Defaults to 8. Higher is "better".
1156    pub max_dynamic_uniform_buffers_per_pipeline_layout: u32,
1157    /// Amount of storage buffer bindings that can be dynamic in a single pipeline. Defaults to 4. Higher is "better".
1158    pub max_dynamic_storage_buffers_per_pipeline_layout: u32,
1159    /// Amount of sampled textures visible in a single shader stage. Defaults to 16. Higher is "better".
1160    pub max_sampled_textures_per_shader_stage: u32,
1161    /// Amount of samplers visible in a single shader stage. Defaults to 16. Higher is "better".
1162    pub max_samplers_per_shader_stage: u32,
1163    /// Amount of storage buffers visible in a single shader stage. Defaults to 8. Higher is "better".
1164    pub max_storage_buffers_per_shader_stage: u32,
1165    /// Amount of storage textures visible in a single shader stage. Defaults to 4. Higher is "better".
1166    pub max_storage_textures_per_shader_stage: u32,
1167    /// Amount of uniform buffers visible in a single shader stage. Defaults to 12. Higher is "better".
1168    pub max_uniform_buffers_per_shader_stage: u32,
1169    /// Maximum size in bytes of a binding to a uniform buffer. Defaults to 64 KiB. Higher is "better".
1170    pub max_uniform_buffer_binding_size: u32,
1171    /// Maximum size in bytes of a binding to a storage buffer. Defaults to 128 MiB. Higher is "better".
1172    pub max_storage_buffer_binding_size: u32,
1173    /// Maximum length of `VertexState::buffers` when creating a `RenderPipeline`.
1174    /// Defaults to 8. Higher is "better".
1175    pub max_vertex_buffers: u32,
1176    /// A limit above which buffer allocations are guaranteed to fail.
1177    /// Defaults to 256 MiB. Higher is "better".
1178    ///
1179    /// Buffer allocations below the maximum buffer size may not succeed depending on available memory,
1180    /// fragmentation and other factors.
1181    pub max_buffer_size: u64,
1182    /// Maximum length of `VertexBufferLayout::attributes`, summed over all `VertexState::buffers`,
1183    /// when creating a `RenderPipeline`.
1184    /// Defaults to 16. Higher is "better".
1185    pub max_vertex_attributes: u32,
1186    /// Maximum value for `VertexBufferLayout::array_stride` when creating a `RenderPipeline`.
1187    /// Defaults to 2048. Higher is "better".
1188    pub max_vertex_buffer_array_stride: u32,
1189    /// Required `BufferBindingType::Uniform` alignment for `BufferBinding::offset`
1190    /// when creating a `BindGroup`, or for `set_bind_group` `dynamicOffsets`.
1191    /// Defaults to 256. Lower is "better".
1192    pub min_uniform_buffer_offset_alignment: u32,
1193    /// Required `BufferBindingType::Storage` alignment for `BufferBinding::offset`
1194    /// when creating a `BindGroup`, or for `set_bind_group` `dynamicOffsets`.
1195    /// Defaults to 256. Lower is "better".
1196    pub min_storage_buffer_offset_alignment: u32,
1197    /// Maximum allowed number of components (scalars) of input or output locations for
1198    /// inter-stage communication (vertex outputs to fragment inputs). Defaults to 60.
1199    /// Higher is "better".
1200    pub max_inter_stage_shader_components: u32,
1201    /// The maximum allowed number of color attachments.
1202    pub max_color_attachments: u32,
1203    /// The maximum number of bytes necessary to hold one sample (pixel or subpixel) of render
1204    /// pipeline output data, across all color attachments as described by [`TextureFormat::target_pixel_byte_cost`]
1205    /// and [`TextureFormat::target_component_alignment`]. Defaults to 32. Higher is "better".
1206    ///
1207    /// ⚠️ `Rgba8Unorm`/`Rgba8Snorm`/`Bgra8Unorm`/`Bgra8Snorm` are deceptively 8 bytes per sample. ⚠️
1208    pub max_color_attachment_bytes_per_sample: u32,
1209    /// Maximum number of bytes used for workgroup memory in a compute entry point. Defaults to
1210    /// 16384. Higher is "better".
1211    pub max_compute_workgroup_storage_size: u32,
1212    /// Maximum value of the product of the `workgroup_size` dimensions for a compute entry-point.
1213    /// Defaults to 256. Higher is "better".
1214    pub max_compute_invocations_per_workgroup: u32,
1215    /// The maximum value of the workgroup_size X dimension for a compute stage `ShaderModule` entry-point.
1216    /// Defaults to 256. Higher is "better".
1217    pub max_compute_workgroup_size_x: u32,
1218    /// The maximum value of the workgroup_size Y dimension for a compute stage `ShaderModule` entry-point.
1219    /// Defaults to 256. Higher is "better".
1220    pub max_compute_workgroup_size_y: u32,
1221    /// The maximum value of the workgroup_size Z dimension for a compute stage `ShaderModule` entry-point.
1222    /// Defaults to 64. Higher is "better".
1223    pub max_compute_workgroup_size_z: u32,
1224    /// The maximum value for each dimension of a `ComputePass::dispatch(x, y, z)` operation.
1225    /// Defaults to 65535. Higher is "better".
1226    pub max_compute_workgroups_per_dimension: u32,
1227
1228    /// Minimal number of invocations in a subgroup. Higher is "better".
1229    pub min_subgroup_size: u32,
1230    /// Maximal number of invocations in a subgroup. Lower is "better".
1231    pub max_subgroup_size: u32,
1232    /// Amount of storage available for push constants in bytes. Defaults to 0. Higher is "better".
1233    /// Requesting more than 0 during device creation requires [`Features::PUSH_CONSTANTS`] to be enabled.
1234    ///
1235    /// Expect the size to be:
1236    /// - Vulkan: 128-256 bytes
1237    /// - DX12: 256 bytes
1238    /// - Metal: 4096 bytes
1239    /// - OpenGL doesn't natively support push constants, and are emulated with uniforms,
1240    ///   so this number is less useful but likely 256.
1241    pub max_push_constant_size: u32,
1242    /// Maximum number of live non-sampler bindings.
1243    ///
1244    /// This limit only affects the d3d12 backend. Using a large number will allow the device
1245    /// to create many bind groups at the cost of a large up-front allocation at device creation.
1246    pub max_non_sampler_bindings: u32,
1247}
1248
1249impl Default for Limits {
1250    fn default() -> Self {
1251        Self::defaults()
1252    }
1253}
1254
1255impl Limits {
1256    // Rust doesn't allow const in trait implementations, so we break this out
1257    // to allow reusing these defaults in const contexts like `downlevel_defaults`
1258    const fn defaults() -> Self {
1259        Self {
1260            max_texture_dimension_1d: 8192,
1261            max_texture_dimension_2d: 8192,
1262            max_texture_dimension_3d: 2048,
1263            max_texture_array_layers: 256,
1264            max_bind_groups: 4,
1265            max_bindings_per_bind_group: 1000,
1266            max_dynamic_uniform_buffers_per_pipeline_layout: 8,
1267            max_dynamic_storage_buffers_per_pipeline_layout: 4,
1268            max_sampled_textures_per_shader_stage: 16,
1269            max_samplers_per_shader_stage: 16,
1270            max_storage_buffers_per_shader_stage: 8,
1271            max_storage_textures_per_shader_stage: 4,
1272            max_uniform_buffers_per_shader_stage: 12,
1273            max_uniform_buffer_binding_size: 64 << 10, // (64 KiB)
1274            max_storage_buffer_binding_size: 128 << 20, // (128 MiB)
1275            max_vertex_buffers: 8,
1276            max_buffer_size: 256 << 20, // (256 MiB)
1277            max_vertex_attributes: 16,
1278            max_vertex_buffer_array_stride: 2048,
1279            min_uniform_buffer_offset_alignment: 256,
1280            min_storage_buffer_offset_alignment: 256,
1281            max_inter_stage_shader_components: 60,
1282            max_color_attachments: 8,
1283            max_color_attachment_bytes_per_sample: 32,
1284            max_compute_workgroup_storage_size: 16384,
1285            max_compute_invocations_per_workgroup: 256,
1286            max_compute_workgroup_size_x: 256,
1287            max_compute_workgroup_size_y: 256,
1288            max_compute_workgroup_size_z: 64,
1289            max_compute_workgroups_per_dimension: 65535,
1290            min_subgroup_size: 0,
1291            max_subgroup_size: 0,
1292            max_push_constant_size: 0,
1293            max_non_sampler_bindings: 1_000_000,
1294        }
1295    }
1296
1297    /// These default limits are guaranteed to be compatible with GLES-3.1, and D3D11
1298    ///
1299    /// Those limits are as follows (different from default are marked with *):
1300    /// ```rust
1301    /// # use wgpu_types::Limits;
1302    /// assert_eq!(Limits::downlevel_defaults(), Limits {
1303    ///     max_texture_dimension_1d: 2048, // *
1304    ///     max_texture_dimension_2d: 2048, // *
1305    ///     max_texture_dimension_3d: 256, // *
1306    ///     max_texture_array_layers: 256,
1307    ///     max_bind_groups: 4,
1308    ///     max_bindings_per_bind_group: 1000,
1309    ///     max_dynamic_uniform_buffers_per_pipeline_layout: 8,
1310    ///     max_dynamic_storage_buffers_per_pipeline_layout: 4,
1311    ///     max_sampled_textures_per_shader_stage: 16,
1312    ///     max_samplers_per_shader_stage: 16,
1313    ///     max_storage_buffers_per_shader_stage: 4, // *
1314    ///     max_storage_textures_per_shader_stage: 4,
1315    ///     max_uniform_buffers_per_shader_stage: 12,
1316    ///     max_uniform_buffer_binding_size: 16 << 10, // * (16 KiB)
1317    ///     max_storage_buffer_binding_size: 128 << 20, // (128 MiB)
1318    ///     max_vertex_buffers: 8,
1319    ///     max_vertex_attributes: 16,
1320    ///     max_vertex_buffer_array_stride: 2048,
1321    ///     min_subgroup_size: 0,
1322    ///     max_subgroup_size: 0,
1323    ///     max_push_constant_size: 0,
1324    ///     min_uniform_buffer_offset_alignment: 256,
1325    ///     min_storage_buffer_offset_alignment: 256,
1326    ///     max_inter_stage_shader_components: 60,
1327    ///     max_color_attachments: 8,
1328    ///     max_color_attachment_bytes_per_sample: 32,
1329    ///     max_compute_workgroup_storage_size: 16352, // *
1330    ///     max_compute_invocations_per_workgroup: 256,
1331    ///     max_compute_workgroup_size_x: 256,
1332    ///     max_compute_workgroup_size_y: 256,
1333    ///     max_compute_workgroup_size_z: 64,
1334    ///     max_compute_workgroups_per_dimension: 65535,
1335    ///     max_buffer_size: 256 << 20, // (256 MiB)
1336    ///     max_non_sampler_bindings: 1_000_000,
1337    /// });
1338    /// ```
1339    #[must_use]
1340    pub const fn downlevel_defaults() -> Self {
1341        Self {
1342            max_texture_dimension_1d: 2048,
1343            max_texture_dimension_2d: 2048,
1344            max_texture_dimension_3d: 256,
1345            max_storage_buffers_per_shader_stage: 4,
1346            max_uniform_buffer_binding_size: 16 << 10, // (16 KiB)
1347            // see: https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf#page=7
1348            max_compute_workgroup_storage_size: 16352,
1349            ..Self::defaults()
1350        }
1351    }
1352
1353    /// These default limits are guaranteed to be compatible with GLES-3.0, and D3D11, and WebGL2
1354    ///
1355    /// Those limits are as follows (different from `downlevel_defaults` are marked with +,
1356    /// *'s from `downlevel_defaults` shown as well.):
1357    /// ```rust
1358    /// # use wgpu_types::Limits;
1359    /// assert_eq!(Limits::downlevel_webgl2_defaults(), Limits {
1360    ///     max_texture_dimension_1d: 2048, // *
1361    ///     max_texture_dimension_2d: 2048, // *
1362    ///     max_texture_dimension_3d: 256, // *
1363    ///     max_texture_array_layers: 256,
1364    ///     max_bind_groups: 4,
1365    ///     max_bindings_per_bind_group: 1000,
1366    ///     max_dynamic_uniform_buffers_per_pipeline_layout: 8,
1367    ///     max_dynamic_storage_buffers_per_pipeline_layout: 0, // +
1368    ///     max_sampled_textures_per_shader_stage: 16,
1369    ///     max_samplers_per_shader_stage: 16,
1370    ///     max_storage_buffers_per_shader_stage: 0, // * +
1371    ///     max_storage_textures_per_shader_stage: 0, // +
1372    ///     max_uniform_buffers_per_shader_stage: 11, // +
1373    ///     max_uniform_buffer_binding_size: 16 << 10, // * (16 KiB)
1374    ///     max_storage_buffer_binding_size: 0, // * +
1375    ///     max_vertex_buffers: 8,
1376    ///     max_vertex_attributes: 16,
1377    ///     max_vertex_buffer_array_stride: 255, // +
1378    ///     min_subgroup_size: 0,
1379    ///     max_subgroup_size: 0,
1380    ///     max_push_constant_size: 0,
1381    ///     min_uniform_buffer_offset_alignment: 256,
1382    ///     min_storage_buffer_offset_alignment: 256,
1383    ///     max_inter_stage_shader_components: 31,
1384    ///     max_color_attachments: 8,
1385    ///     max_color_attachment_bytes_per_sample: 32,
1386    ///     max_compute_workgroup_storage_size: 0, // +
1387    ///     max_compute_invocations_per_workgroup: 0, // +
1388    ///     max_compute_workgroup_size_x: 0, // +
1389    ///     max_compute_workgroup_size_y: 0, // +
1390    ///     max_compute_workgroup_size_z: 0, // +
1391    ///     max_compute_workgroups_per_dimension: 0, // +
1392    ///     max_buffer_size: 256 << 20, // (256 MiB),
1393    ///     max_non_sampler_bindings: 1_000_000,
1394    /// });
1395    /// ```
1396    #[must_use]
1397    pub const fn downlevel_webgl2_defaults() -> Self {
1398        Self {
1399            max_uniform_buffers_per_shader_stage: 11,
1400            max_storage_buffers_per_shader_stage: 0,
1401            max_storage_textures_per_shader_stage: 0,
1402            max_dynamic_storage_buffers_per_pipeline_layout: 0,
1403            max_storage_buffer_binding_size: 0,
1404            max_vertex_buffer_array_stride: 255,
1405            max_compute_workgroup_storage_size: 0,
1406            max_compute_invocations_per_workgroup: 0,
1407            max_compute_workgroup_size_x: 0,
1408            max_compute_workgroup_size_y: 0,
1409            max_compute_workgroup_size_z: 0,
1410            max_compute_workgroups_per_dimension: 0,
1411            min_subgroup_size: 0,
1412            max_subgroup_size: 0,
1413
1414            // Value supported by Intel Celeron B830 on Windows (OpenGL 3.1)
1415            max_inter_stage_shader_components: 31,
1416
1417            // Most of the values should be the same as the downlevel defaults
1418            ..Self::downlevel_defaults()
1419        }
1420    }
1421
1422    /// Modify the current limits to use the resolution limits of the other.
1423    ///
1424    /// This is useful because the swapchain might need to be larger than any other image in the application.
1425    ///
1426    /// If your application only needs 512x512, you might be running on a 4k display and need extremely high resolution limits.
1427    #[must_use]
1428    pub const fn using_resolution(self, other: Self) -> Self {
1429        Self {
1430            max_texture_dimension_1d: other.max_texture_dimension_1d,
1431            max_texture_dimension_2d: other.max_texture_dimension_2d,
1432            max_texture_dimension_3d: other.max_texture_dimension_3d,
1433            ..self
1434        }
1435    }
1436
1437    /// Modify the current limits to use the buffer alignment limits of the adapter.
1438    ///
1439    /// This is useful for when you'd like to dynamically use the "best" supported buffer alignments.
1440    #[must_use]
1441    pub const fn using_alignment(self, other: Self) -> Self {
1442        Self {
1443            min_uniform_buffer_offset_alignment: other.min_uniform_buffer_offset_alignment,
1444            min_storage_buffer_offset_alignment: other.min_storage_buffer_offset_alignment,
1445            ..self
1446        }
1447    }
1448
1449    /// Compares every limits within self is within the limits given in `allowed`.
1450    ///
1451    /// If you need detailed information on failures, look at [`Limits::check_limits_with_fail_fn`].
1452    #[must_use]
1453    pub fn check_limits(&self, allowed: &Self) -> bool {
1454        let mut within = true;
1455        self.check_limits_with_fail_fn(allowed, true, |_, _, _| within = false);
1456        within
1457    }
1458
1459    /// Compares every limits within self is within the limits given in `allowed`.
1460    /// For an easy to use binary choice, use [`Limits::check_limits`].
1461    ///
1462    /// If a value is not within the allowed limit, this function calls the `fail_fn`
1463    /// with the:
1464    ///  - limit name
1465    ///  - self's limit
1466    ///  - allowed's limit.
1467    ///
1468    /// If fatal is true, a single failure bails out the comparison after a single failure.
1469    pub fn check_limits_with_fail_fn(
1470        &self,
1471        allowed: &Self,
1472        fatal: bool,
1473        mut fail_fn: impl FnMut(&'static str, u64, u64),
1474    ) {
1475        use core::cmp::Ordering;
1476
1477        macro_rules! compare {
1478            ($name:ident, $ordering:ident) => {
1479                match self.$name.cmp(&allowed.$name) {
1480                    Ordering::$ordering | Ordering::Equal => (),
1481                    _ => {
1482                        fail_fn(stringify!($name), self.$name as u64, allowed.$name as u64);
1483                        if fatal {
1484                            return;
1485                        }
1486                    }
1487                }
1488            };
1489        }
1490
1491        compare!(max_texture_dimension_1d, Less);
1492        compare!(max_texture_dimension_2d, Less);
1493        compare!(max_texture_dimension_3d, Less);
1494        compare!(max_texture_array_layers, Less);
1495        compare!(max_bind_groups, Less);
1496        compare!(max_bindings_per_bind_group, Less);
1497        compare!(max_dynamic_uniform_buffers_per_pipeline_layout, Less);
1498        compare!(max_dynamic_storage_buffers_per_pipeline_layout, Less);
1499        compare!(max_sampled_textures_per_shader_stage, Less);
1500        compare!(max_samplers_per_shader_stage, Less);
1501        compare!(max_storage_buffers_per_shader_stage, Less);
1502        compare!(max_storage_textures_per_shader_stage, Less);
1503        compare!(max_uniform_buffers_per_shader_stage, Less);
1504        compare!(max_uniform_buffer_binding_size, Less);
1505        compare!(max_storage_buffer_binding_size, Less);
1506        compare!(max_vertex_buffers, Less);
1507        compare!(max_buffer_size, Less);
1508        compare!(max_vertex_attributes, Less);
1509        compare!(max_vertex_buffer_array_stride, Less);
1510        compare!(min_uniform_buffer_offset_alignment, Greater);
1511        compare!(min_storage_buffer_offset_alignment, Greater);
1512        compare!(max_inter_stage_shader_components, Less);
1513        compare!(max_color_attachments, Less);
1514        compare!(max_color_attachment_bytes_per_sample, Less);
1515        compare!(max_compute_workgroup_storage_size, Less);
1516        compare!(max_compute_invocations_per_workgroup, Less);
1517        compare!(max_compute_workgroup_size_x, Less);
1518        compare!(max_compute_workgroup_size_y, Less);
1519        compare!(max_compute_workgroup_size_z, Less);
1520        compare!(max_compute_workgroups_per_dimension, Less);
1521        if self.min_subgroup_size > 0 && self.max_subgroup_size > 0 {
1522            compare!(min_subgroup_size, Greater);
1523            compare!(max_subgroup_size, Less);
1524        }
1525        compare!(max_push_constant_size, Less);
1526        compare!(max_non_sampler_bindings, Less);
1527    }
1528}
1529
1530/// Represents the sets of additional limits on an adapter,
1531/// which take place when running on downlevel backends.
1532#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
1533#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1534pub struct DownlevelLimits {}
1535
1536#[allow(clippy::derivable_impls)]
1537impl Default for DownlevelLimits {
1538    fn default() -> Self {
1539        DownlevelLimits {}
1540    }
1541}
1542
1543/// Lists various ways the underlying platform does not conform to the WebGPU standard.
1544#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
1545#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1546pub struct DownlevelCapabilities {
1547    /// Combined boolean flags.
1548    pub flags: DownlevelFlags,
1549    /// Additional limits
1550    pub limits: DownlevelLimits,
1551    /// Which collections of features shaders support. Defined in terms of D3D's shader models.
1552    pub shader_model: ShaderModel,
1553}
1554
1555impl Default for DownlevelCapabilities {
1556    fn default() -> Self {
1557        Self {
1558            flags: DownlevelFlags::all(),
1559            limits: DownlevelLimits::default(),
1560            shader_model: ShaderModel::Sm5,
1561        }
1562    }
1563}
1564
1565impl DownlevelCapabilities {
1566    /// Returns true if the underlying platform offers complete support of the baseline WebGPU standard.
1567    ///
1568    /// If this returns false, some parts of the API will result in validation errors where they would not normally.
1569    /// These parts can be determined by the values in this structure.
1570    #[must_use]
1571    pub fn is_webgpu_compliant(&self) -> bool {
1572        self.flags.contains(DownlevelFlags::compliant())
1573            && self.limits == DownlevelLimits::default()
1574            && self.shader_model >= ShaderModel::Sm5
1575    }
1576}
1577
1578bitflags::bitflags! {
1579    /// Binary flags listing features that may or may not be present on downlevel adapters.
1580    ///
1581    /// A downlevel adapter is a GPU adapter that WGPU supports, but with potentially limited
1582    /// features, due to the lack of hardware feature support.
1583    ///
1584    /// Flags that are **not** present for a downlevel adapter or device usually indicates
1585    /// non-compliance with the WebGPU specification, but not always.
1586    ///
1587    /// You can check whether a set of flags is compliant through the
1588    /// [`DownlevelCapabilities::is_webgpu_compliant()`] function.
1589    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1590    #[cfg_attr(feature = "serde", serde(transparent))]
1591    #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
1592    pub struct DownlevelFlags: u32 {
1593        /// The device supports compiling and using compute shaders.
1594        ///
1595        /// WebGL2, and GLES3.0 devices do not support compute.
1596        const COMPUTE_SHADERS = 1 << 0;
1597        /// Supports binding storage buffers and textures to fragment shaders.
1598        const FRAGMENT_WRITABLE_STORAGE = 1 << 1;
1599        /// Supports indirect drawing and dispatching.
1600        ///
1601        /// WebGL2, GLES 3.0, and Metal on Apple1/Apple2 GPUs do not support indirect.
1602        const INDIRECT_EXECUTION = 1 << 2;
1603        /// Supports non-zero `base_vertex` parameter to direct indexed draw calls.
1604        ///
1605        /// Indirect calls, if supported, always support non-zero `base_vertex`.
1606        ///
1607        /// Supported by:
1608        /// - Vulkan
1609        /// - DX12
1610        /// - Metal on Apple3+ or Mac1+
1611        /// - OpenGL 3.2+
1612        /// - OpenGL ES 3.2
1613        const BASE_VERTEX = 1 << 3;
1614        /// Supports reading from a depth/stencil texture while using it as a read-only
1615        /// depth/stencil attachment.
1616        ///
1617        /// The WebGL2 and GLES backends do not support RODS.
1618        const READ_ONLY_DEPTH_STENCIL = 1 << 4;
1619        /// Supports textures with mipmaps which have a non power of two size.
1620        const NON_POWER_OF_TWO_MIPMAPPED_TEXTURES = 1 << 5;
1621        /// Supports textures that are cube arrays.
1622        const CUBE_ARRAY_TEXTURES = 1 << 6;
1623        /// Supports comparison samplers.
1624        const COMPARISON_SAMPLERS = 1 << 7;
1625        /// Supports different blend operations per color attachment.
1626        const INDEPENDENT_BLEND = 1 << 8;
1627        /// Supports storage buffers in vertex shaders.
1628        const VERTEX_STORAGE = 1 << 9;
1629
1630        /// Supports samplers with anisotropic filtering. Note this isn't actually required by
1631        /// WebGPU, the implementation is allowed to completely ignore aniso clamp. This flag is
1632        /// here for native backends so they can communicate to the user of aniso is enabled.
1633        ///
1634        /// All backends and all devices support anisotropic filtering.
1635        const ANISOTROPIC_FILTERING = 1 << 10;
1636
1637        /// Supports storage buffers in fragment shaders.
1638        const FRAGMENT_STORAGE = 1 << 11;
1639
1640        /// Supports sample-rate shading.
1641        const MULTISAMPLED_SHADING = 1 << 12;
1642
1643        /// Supports copies between depth textures and buffers.
1644        ///
1645        /// GLES/WebGL don't support this.
1646        const DEPTH_TEXTURE_AND_BUFFER_COPIES = 1 << 13;
1647
1648        /// Supports all the texture usages described in WebGPU. If this isn't supported, you
1649        /// should call `get_texture_format_features` to get how you can use textures of a given format
1650        const WEBGPU_TEXTURE_FORMAT_SUPPORT = 1 << 14;
1651
1652        /// Supports buffer bindings with sizes that aren't a multiple of 16.
1653        ///
1654        /// WebGL doesn't support this.
1655        const BUFFER_BINDINGS_NOT_16_BYTE_ALIGNED = 1 << 15;
1656
1657        /// Supports buffers to combine [`BufferUsages::INDEX`] with usages other than [`BufferUsages::COPY_DST`] and [`BufferUsages::COPY_SRC`].
1658        /// Furthermore, in absence of this feature it is not allowed to copy index buffers from/to buffers with a set of usage flags containing
1659        /// [`BufferUsages::VERTEX`]/[`BufferUsages::UNIFORM`]/[`BufferUsages::STORAGE`] or [`BufferUsages::INDIRECT`].
1660        ///
1661        /// WebGL doesn't support this.
1662        const UNRESTRICTED_INDEX_BUFFER = 1 << 16;
1663
1664        /// Supports full 32-bit range indices (2^32-1 as opposed to 2^24-1 without this flag)
1665        ///
1666        /// Corresponds to Vulkan's `VkPhysicalDeviceFeatures.fullDrawIndexUint32`
1667        const FULL_DRAW_INDEX_UINT32 = 1 << 17;
1668
1669        /// Supports depth bias clamping
1670        ///
1671        /// Corresponds to Vulkan's `VkPhysicalDeviceFeatures.depthBiasClamp`
1672        const DEPTH_BIAS_CLAMP = 1 << 18;
1673
1674        /// Supports specifying which view format values are allowed when create_view() is called on a texture.
1675        ///
1676        /// The WebGL and GLES backends doesn't support this.
1677        const VIEW_FORMATS = 1 << 19;
1678
1679        /// With this feature not present, there are the following restrictions on `Queue::copy_external_image_to_texture`:
1680        /// - The source must not be [`web_sys::OffscreenCanvas`]
1681        /// - [`CopyExternalImageSourceInfo::origin`] must be zero.
1682        /// - [`CopyExternalImageDestInfo::color_space`] must be srgb.
1683        /// - If the source is an [`web_sys::ImageBitmap`]:
1684        ///   - [`CopyExternalImageSourceInfo::flip_y`] must be false.
1685        ///   - [`CopyExternalImageDestInfo::premultiplied_alpha`] must be false.
1686        ///
1687        /// WebGL doesn't support this. WebGPU does.
1688        const UNRESTRICTED_EXTERNAL_TEXTURE_COPIES = 1 << 20;
1689
1690        /// Supports specifying which view formats are allowed when calling create_view on the texture returned by get_current_texture.
1691        ///
1692        /// The GLES/WebGL and Vulkan on Android doesn't support this.
1693        const SURFACE_VIEW_FORMATS = 1 << 21;
1694
1695        /// If this is true, calls to `CommandEncoder::resolve_query_set` will be performed on the queue timeline.
1696        ///
1697        /// If this is false, calls to `CommandEncoder::resolve_query_set` will be performed on the device (i.e. cpu) timeline
1698        /// and will block that timeline until the query has data. You may work around this limitation by waiting until the submit
1699        /// whose queries you are resolving is fully finished (through use of `queue.on_submitted_work_done`) and only
1700        /// then submitting the resolve_query_set command. The queries will be guaranteed finished, so will not block.
1701        ///
1702        /// Supported by:
1703        /// - Vulkan,
1704        /// - DX12
1705        /// - Metal
1706        /// - OpenGL 4.4+
1707        ///
1708        /// Not Supported by:
1709        /// - GL ES / WebGL
1710        const NONBLOCKING_QUERY_RESOLVE = 1 << 22;
1711
1712        /// If this is true, use of `@builtin(vertex_index)` and `@builtin(instance_index)` will properly take into consideration
1713        /// the `first_vertex` and `first_instance` parameters of indirect draw calls.
1714        ///
1715        /// If this is false, `@builtin(vertex_index)` and `@builtin(instance_index)` will start by counting from 0, ignoring the
1716        /// `first_vertex` and `first_instance` parameters.
1717        ///
1718        /// For example, if you had a draw call like this:
1719        /// - `first_vertex: 4,`
1720        /// - `vertex_count: 12,`
1721        ///
1722        /// When this flag is present, `@builtin(vertex_index)` will start at 4 and go up to 15 (12 invocations).
1723        ///
1724        /// When this flag is not present, `@builtin(vertex_index)` will start at 0 and go up to 11 (12 invocations).
1725        ///
1726        /// This only affects the builtins in the shaders,
1727        /// vertex buffers and instance rate vertex buffers will behave like expected with this flag disabled.
1728        ///
1729        /// See also [`Features::`]
1730        ///
1731        /// Supported By:
1732        /// - Vulkan
1733        /// - Metal
1734        /// - OpenGL
1735        ///
1736        /// Will be implemented in the future by:
1737        /// - DX12 ([#2471](https://github.com/gfx-rs/wgpu/issues/2471))
1738        const VERTEX_AND_INSTANCE_INDEX_RESPECTS_RESPECTIVE_FIRST_VALUE_IN_INDIRECT_DRAW = 1 << 23;
1739    }
1740}
1741
1742impl DownlevelFlags {
1743    /// All flags that indicate if the backend is WebGPU compliant
1744    #[must_use]
1745    pub const fn compliant() -> Self {
1746        // We use manual bit twiddling to make this a const fn as `Sub` and `.remove` aren't const
1747
1748        // WebGPU doesn't actually require aniso
1749        Self::from_bits_truncate(Self::all().bits() & !Self::ANISOTROPIC_FILTERING.bits())
1750    }
1751}
1752
1753/// Collections of shader features a device supports if they support less than WebGPU normally allows.
1754// TODO: Fill out the differences between shader models more completely
1755#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
1756#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1757pub enum ShaderModel {
1758    /// Extremely limited shaders, including a total instruction limit.
1759    Sm2,
1760    /// Missing minor features and storage images.
1761    Sm4,
1762    /// WebGPU supports shader module 5.
1763    Sm5,
1764}
1765
1766/// Supported physical device types.
1767#[repr(u8)]
1768#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
1769#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1770pub enum DeviceType {
1771    /// Other or Unknown.
1772    Other,
1773    /// Integrated GPU with shared CPU/GPU memory.
1774    IntegratedGpu,
1775    /// Discrete GPU with separate CPU/GPU memory.
1776    DiscreteGpu,
1777    /// Virtual / Hosted.
1778    VirtualGpu,
1779    /// Cpu / Software Rendering.
1780    Cpu,
1781}
1782
1783//TODO: convert `vendor` and `device` to `u32`
1784
1785/// Information about an adapter.
1786#[derive(Clone, Debug, Eq, PartialEq, Hash)]
1787#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1788pub struct AdapterInfo {
1789    /// Adapter name
1790    pub name: String,
1791    /// [`Backend`]-specific vendor ID of the adapter
1792    ///
1793    /// This generally is a 16-bit PCI vendor ID in the least significant bytes of this field.
1794    /// However, more significant bytes may be non-zero if the backend uses a different
1795    /// representation.
1796    ///
1797    /// * For [`Backend::Vulkan`], the [`VkPhysicalDeviceProperties::vendorID`] is used, which is
1798    ///     a superset of PCI IDs.
1799    ///
1800    /// [`VkPhysicalDeviceProperties::vendorID`]: https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkPhysicalDeviceProperties.html
1801    pub vendor: u32,
1802    /// [`Backend`]-specific device ID of the adapter
1803    ///
1804    ///
1805    /// This generally is a 16-bit PCI device ID in the least significant bytes of this field.
1806    /// However, more significant bytes may be non-zero if the backend uses a different
1807    /// representation.
1808    ///
1809    /// * For [`Backend::Vulkan`], the [`VkPhysicalDeviceProperties::deviceID`] is used, which is
1810    ///    a superset of PCI IDs.
1811    ///
1812    /// [`VkPhysicalDeviceProperties::deviceID`]: https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkPhysicalDeviceProperties.html
1813    pub device: u32,
1814    /// Type of device
1815    pub device_type: DeviceType,
1816    /// Driver name
1817    pub driver: String,
1818    /// Driver info
1819    pub driver_info: String,
1820    /// Backend used for device
1821    pub backend: Backend,
1822}
1823
1824/// Hints to the device about the memory allocation strategy.
1825///
1826/// Some backends may ignore these hints.
1827#[derive(Clone, Debug, Default)]
1828#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1829pub enum MemoryHints {
1830    /// Favor performance over memory usage (the default value).
1831    #[default]
1832    Performance,
1833    /// Favor memory usage over performance.
1834    MemoryUsage,
1835    /// Applications that have control over the content that is rendered
1836    /// (typically games) may find an optimal compromise between memory
1837    /// usage and performance by specifying the allocation configuration.
1838    Manual {
1839        /// Defines the range of allowed memory block sizes for sub-allocated
1840        /// resources.
1841        ///
1842        /// The backend may attempt to group multiple resources into fewer
1843        /// device memory blocks (sub-allocation) for performance reasons.
1844        /// The start of the provided range specifies the initial memory
1845        /// block size for sub-allocated resources. After running out of
1846        /// space in existing memory blocks, the backend may chose to
1847        /// progressively increase the block size of subsequent allocations
1848        /// up to a limit specified by the end of the range.
1849        ///
1850        /// This does not limit resource sizes. If a resource does not fit
1851        /// in the specified range, it will typically be placed in a dedicated
1852        /// memory block.
1853        suballocated_device_memory_block_size: Range<u64>,
1854    },
1855}
1856
1857/// Describes a [`Device`](../wgpu/struct.Device.html).
1858///
1859/// Corresponds to [WebGPU `GPUDeviceDescriptor`](
1860/// https://gpuweb.github.io/gpuweb/#gpudevicedescriptor).
1861#[derive(Clone, Debug, Default)]
1862#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1863pub struct DeviceDescriptor<L> {
1864    /// Debug label for the device.
1865    pub label: L,
1866    /// Specifies the features that are required by the device request.
1867    /// The request will fail if the adapter cannot provide these features.
1868    ///
1869    /// Exactly the specified set of features, and no more or less,
1870    /// will be allowed in validation of API calls on the resulting device.
1871    pub required_features: Features,
1872    /// Specifies the limits that are required by the device request.
1873    /// The request will fail if the adapter cannot provide these limits.
1874    ///
1875    /// Exactly the specified limits, and no better or worse,
1876    /// will be allowed in validation of API calls on the resulting device.
1877    pub required_limits: Limits,
1878    /// Hints for memory allocation strategies.
1879    pub memory_hints: MemoryHints,
1880}
1881
1882impl<L> DeviceDescriptor<L> {
1883    /// Takes a closure and maps the label of the device descriptor into another.
1884    #[must_use]
1885    pub fn map_label<K>(&self, fun: impl FnOnce(&L) -> K) -> DeviceDescriptor<K> {
1886        DeviceDescriptor {
1887            label: fun(&self.label),
1888            required_features: self.required_features,
1889            required_limits: self.required_limits.clone(),
1890            memory_hints: self.memory_hints.clone(),
1891        }
1892    }
1893}
1894
1895bitflags::bitflags! {
1896    /// Describes the shader stages that a binding will be visible from.
1897    ///
1898    /// These can be combined so something that is visible from both vertex and fragment shaders can be defined as:
1899    ///
1900    /// `ShaderStages::VERTEX | ShaderStages::FRAGMENT`
1901    ///
1902    /// Corresponds to [WebGPU `GPUShaderStageFlags`](
1903    /// https://gpuweb.github.io/gpuweb/#typedefdef-gpushaderstageflags).
1904    #[repr(transparent)]
1905    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1906    #[cfg_attr(feature = "serde", serde(transparent))]
1907    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1908    pub struct ShaderStages: u32 {
1909        /// Binding is not visible from any shader stage.
1910        const NONE = 0;
1911        /// Binding is visible from the vertex shader of a render pipeline.
1912        const VERTEX = 1 << 0;
1913        /// Binding is visible from the fragment shader of a render pipeline.
1914        const FRAGMENT = 1 << 1;
1915        /// Binding is visible from the compute shader of a compute pipeline.
1916        const COMPUTE = 1 << 2;
1917        /// Binding is visible from the vertex and fragment shaders of a render pipeline.
1918        const VERTEX_FRAGMENT = Self::VERTEX.bits() | Self::FRAGMENT.bits();
1919    }
1920}
1921
1922/// Order in which TextureData is laid out in memory.
1923#[derive(Clone, Copy, Default, Debug, PartialEq, Eq, Hash)]
1924pub enum TextureDataOrder {
1925    /// The texture is laid out densely in memory as:
1926    ///
1927    /// ```text
1928    /// Layer0Mip0 Layer0Mip1 Layer0Mip2
1929    /// Layer1Mip0 Layer1Mip1 Layer1Mip2
1930    /// Layer2Mip0 Layer2Mip1 Layer2Mip2
1931    /// ````
1932    ///
1933    /// This is the layout used by dds files.
1934    #[default]
1935    LayerMajor,
1936    /// The texture is laid out densely in memory as:
1937    ///
1938    /// ```text
1939    /// Layer0Mip0 Layer1Mip0 Layer2Mip0
1940    /// Layer0Mip1 Layer1Mip1 Layer2Mip1
1941    /// Layer0Mip2 Layer1Mip2 Layer2Mip2
1942    /// ```
1943    ///
1944    /// This is the layout used by ktx and ktx2 files.
1945    MipMajor,
1946}
1947
1948/// Dimensions of a particular texture view.
1949///
1950/// Corresponds to [WebGPU `GPUTextureViewDimension`](
1951/// https://gpuweb.github.io/gpuweb/#enumdef-gputextureviewdimension).
1952#[repr(C)]
1953#[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq)]
1954#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1955pub enum TextureViewDimension {
1956    /// A one dimensional texture. `texture_1d` in WGSL and `texture1D` in GLSL.
1957    #[cfg_attr(feature = "serde", serde(rename = "1d"))]
1958    D1,
1959    /// A two dimensional texture. `texture_2d` in WGSL and `texture2D` in GLSL.
1960    #[cfg_attr(feature = "serde", serde(rename = "2d"))]
1961    #[default]
1962    D2,
1963    /// A two dimensional array texture. `texture_2d_array` in WGSL and `texture2DArray` in GLSL.
1964    #[cfg_attr(feature = "serde", serde(rename = "2d-array"))]
1965    D2Array,
1966    /// A cubemap texture. `texture_cube` in WGSL and `textureCube` in GLSL.
1967    #[cfg_attr(feature = "serde", serde(rename = "cube"))]
1968    Cube,
1969    /// A cubemap array texture. `texture_cube_array` in WGSL and `textureCubeArray` in GLSL.
1970    #[cfg_attr(feature = "serde", serde(rename = "cube-array"))]
1971    CubeArray,
1972    /// A three dimensional texture. `texture_3d` in WGSL and `texture3D` in GLSL.
1973    #[cfg_attr(feature = "serde", serde(rename = "3d"))]
1974    D3,
1975}
1976
1977impl TextureViewDimension {
1978    /// Get the texture dimension required of this texture view dimension.
1979    #[must_use]
1980    pub fn compatible_texture_dimension(self) -> TextureDimension {
1981        match self {
1982            Self::D1 => TextureDimension::D1,
1983            Self::D2 | Self::D2Array | Self::Cube | Self::CubeArray => TextureDimension::D2,
1984            Self::D3 => TextureDimension::D3,
1985        }
1986    }
1987}
1988
1989/// Alpha blend factor.
1990///
1991/// Corresponds to [WebGPU `GPUBlendFactor`](
1992/// https://gpuweb.github.io/gpuweb/#enumdef-gpublendfactor). Values using `Src1`
1993/// require [`Features::DUAL_SOURCE_BLENDING`] and can only be used with the first
1994/// render target.
1995///
1996/// For further details on how the blend factors are applied, see the analogous
1997/// functionality in OpenGL: <https://www.khronos.org/opengl/wiki/Blending#Blending_Parameters>.
1998#[repr(C)]
1999#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
2000#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2001#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
2002pub enum BlendFactor {
2003    /// 0.0
2004    Zero = 0,
2005    /// 1.0
2006    One = 1,
2007    /// S.component
2008    Src = 2,
2009    /// 1.0 - S.component
2010    OneMinusSrc = 3,
2011    /// S.alpha
2012    SrcAlpha = 4,
2013    /// 1.0 - S.alpha
2014    OneMinusSrcAlpha = 5,
2015    /// D.component
2016    Dst = 6,
2017    /// 1.0 - D.component
2018    OneMinusDst = 7,
2019    /// D.alpha
2020    DstAlpha = 8,
2021    /// 1.0 - D.alpha
2022    OneMinusDstAlpha = 9,
2023    /// min(S.alpha, 1.0 - D.alpha)
2024    SrcAlphaSaturated = 10,
2025    /// Constant
2026    Constant = 11,
2027    /// 1.0 - Constant
2028    OneMinusConstant = 12,
2029    /// S1.component
2030    Src1 = 13,
2031    /// 1.0 - S1.component
2032    OneMinusSrc1 = 14,
2033    /// S1.alpha
2034    Src1Alpha = 15,
2035    /// 1.0 - S1.alpha
2036    OneMinusSrc1Alpha = 16,
2037}
2038
2039impl BlendFactor {
2040    /// Returns `true` if the blend factor references the second blend source.
2041    ///
2042    /// Note that the usage of those blend factors require [`Features::DUAL_SOURCE_BLENDING`].
2043    #[must_use]
2044    pub fn ref_second_blend_source(&self) -> bool {
2045        match self {
2046            BlendFactor::Src1
2047            | BlendFactor::OneMinusSrc1
2048            | BlendFactor::Src1Alpha
2049            | BlendFactor::OneMinusSrc1Alpha => true,
2050            _ => false,
2051        }
2052    }
2053}
2054
2055/// Alpha blend operation.
2056///
2057/// Corresponds to [WebGPU `GPUBlendOperation`](
2058/// https://gpuweb.github.io/gpuweb/#enumdef-gpublendoperation).
2059///
2060/// For further details on how the blend operations are applied, see
2061/// the analogous functionality in OpenGL: <https://www.khronos.org/opengl/wiki/Blending#Blend_Equations>.
2062#[repr(C)]
2063#[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq)]
2064#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2065#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
2066pub enum BlendOperation {
2067    /// Src + Dst
2068    #[default]
2069    Add = 0,
2070    /// Src - Dst
2071    Subtract = 1,
2072    /// Dst - Src
2073    ReverseSubtract = 2,
2074    /// min(Src, Dst)
2075    Min = 3,
2076    /// max(Src, Dst)
2077    Max = 4,
2078}
2079
2080/// Describes a blend component of a [`BlendState`].
2081///
2082/// Corresponds to [WebGPU `GPUBlendComponent`](
2083/// https://gpuweb.github.io/gpuweb/#dictdef-gpublendcomponent).
2084#[repr(C)]
2085#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
2086#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2087#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
2088pub struct BlendComponent {
2089    /// Multiplier for the source, which is produced by the fragment shader.
2090    pub src_factor: BlendFactor,
2091    /// Multiplier for the destination, which is stored in the target.
2092    pub dst_factor: BlendFactor,
2093    /// The binary operation applied to the source and destination,
2094    /// multiplied by their respective factors.
2095    pub operation: BlendOperation,
2096}
2097
2098impl BlendComponent {
2099    /// Default blending state that replaces destination with the source.
2100    pub const REPLACE: Self = Self {
2101        src_factor: BlendFactor::One,
2102        dst_factor: BlendFactor::Zero,
2103        operation: BlendOperation::Add,
2104    };
2105
2106    /// Blend state of (1 * src) + ((1 - src_alpha) * dst)
2107    pub const OVER: Self = Self {
2108        src_factor: BlendFactor::One,
2109        dst_factor: BlendFactor::OneMinusSrcAlpha,
2110        operation: BlendOperation::Add,
2111    };
2112
2113    /// Returns true if the state relies on the constant color, which is
2114    /// set independently on a render command encoder.
2115    #[must_use]
2116    pub fn uses_constant(&self) -> bool {
2117        match (self.src_factor, self.dst_factor) {
2118            (BlendFactor::Constant, _)
2119            | (BlendFactor::OneMinusConstant, _)
2120            | (_, BlendFactor::Constant)
2121            | (_, BlendFactor::OneMinusConstant) => true,
2122            (_, _) => false,
2123        }
2124    }
2125}
2126
2127impl Default for BlendComponent {
2128    fn default() -> Self {
2129        Self::REPLACE
2130    }
2131}
2132
2133/// Describe the blend state of a render pipeline,
2134/// within [`ColorTargetState`].
2135///
2136/// Corresponds to [WebGPU `GPUBlendState`](
2137/// https://gpuweb.github.io/gpuweb/#dictdef-gpublendstate).
2138#[repr(C)]
2139#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
2140#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2141#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
2142pub struct BlendState {
2143    /// Color equation.
2144    pub color: BlendComponent,
2145    /// Alpha equation.
2146    pub alpha: BlendComponent,
2147}
2148
2149impl BlendState {
2150    /// Blend mode that does no color blending, just overwrites the output with the contents of the shader.
2151    pub const REPLACE: Self = Self {
2152        color: BlendComponent::REPLACE,
2153        alpha: BlendComponent::REPLACE,
2154    };
2155
2156    /// Blend mode that does standard alpha blending with non-premultiplied alpha.
2157    pub const ALPHA_BLENDING: Self = Self {
2158        color: BlendComponent {
2159            src_factor: BlendFactor::SrcAlpha,
2160            dst_factor: BlendFactor::OneMinusSrcAlpha,
2161            operation: BlendOperation::Add,
2162        },
2163        alpha: BlendComponent::OVER,
2164    };
2165
2166    /// Blend mode that does standard alpha blending with premultiplied alpha.
2167    pub const PREMULTIPLIED_ALPHA_BLENDING: Self = Self {
2168        color: BlendComponent::OVER,
2169        alpha: BlendComponent::OVER,
2170    };
2171}
2172
2173/// Describes the color state of a render pipeline.
2174///
2175/// Corresponds to [WebGPU `GPUColorTargetState`](
2176/// https://gpuweb.github.io/gpuweb/#dictdef-gpucolortargetstate).
2177#[repr(C)]
2178#[derive(Clone, Debug, PartialEq, Eq, Hash)]
2179#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2180#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
2181pub struct ColorTargetState {
2182    /// The [`TextureFormat`] of the image that this pipeline will render to. Must match the format
2183    /// of the corresponding color attachment in [`CommandEncoder::begin_render_pass`][CEbrp]
2184    ///
2185    /// [CEbrp]: ../wgpu/struct.CommandEncoder.html#method.begin_render_pass
2186    pub format: TextureFormat,
2187    /// The blending that is used for this pipeline.
2188    #[cfg_attr(feature = "serde", serde(default))]
2189    pub blend: Option<BlendState>,
2190    /// Mask which enables/disables writes to different color/alpha channel.
2191    #[cfg_attr(feature = "serde", serde(default))]
2192    pub write_mask: ColorWrites,
2193}
2194
2195impl From<TextureFormat> for ColorTargetState {
2196    fn from(format: TextureFormat) -> Self {
2197        Self {
2198            format,
2199            blend: None,
2200            write_mask: ColorWrites::ALL,
2201        }
2202    }
2203}
2204
2205/// Primitive type the input mesh is composed of.
2206///
2207/// Corresponds to [WebGPU `GPUPrimitiveTopology`](
2208/// https://gpuweb.github.io/gpuweb/#enumdef-gpuprimitivetopology).
2209#[repr(C)]
2210#[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq)]
2211#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2212#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
2213pub enum PrimitiveTopology {
2214    /// Vertex data is a list of points. Each vertex is a new point.
2215    PointList = 0,
2216    /// Vertex data is a list of lines. Each pair of vertices composes a new line.
2217    ///
2218    /// Vertices `0 1 2 3` create two lines `0 1` and `2 3`
2219    LineList = 1,
2220    /// Vertex data is a strip of lines. Each set of two adjacent vertices form a line.
2221    ///
2222    /// Vertices `0 1 2 3` create three lines `0 1`, `1 2`, and `2 3`.
2223    LineStrip = 2,
2224    /// Vertex data is a list of triangles. Each set of 3 vertices composes a new triangle.
2225    ///
2226    /// Vertices `0 1 2 3 4 5` create two triangles `0 1 2` and `3 4 5`
2227    #[default]
2228    TriangleList = 3,
2229    /// Vertex data is a triangle strip. Each set of three adjacent vertices form a triangle.
2230    ///
2231    /// Vertices `0 1 2 3 4 5` create four triangles `0 1 2`, `2 1 3`, `2 3 4`, and `4 3 5`
2232    TriangleStrip = 4,
2233}
2234
2235impl PrimitiveTopology {
2236    /// Returns true for strip topologies.
2237    #[must_use]
2238    pub fn is_strip(&self) -> bool {
2239        match *self {
2240            Self::PointList | Self::LineList | Self::TriangleList => false,
2241            Self::LineStrip | Self::TriangleStrip => true,
2242        }
2243    }
2244}
2245
2246/// Vertex winding order which classifies the "front" face of a triangle.
2247///
2248/// Corresponds to [WebGPU `GPUFrontFace`](
2249/// https://gpuweb.github.io/gpuweb/#enumdef-gpufrontface).
2250#[repr(C)]
2251#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
2252#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2253#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
2254pub enum FrontFace {
2255    /// Triangles with vertices in counter clockwise order are considered the front face.
2256    ///
2257    /// This is the default with right handed coordinate spaces.
2258    #[default]
2259    Ccw = 0,
2260    /// Triangles with vertices in clockwise order are considered the front face.
2261    ///
2262    /// This is the default with left handed coordinate spaces.
2263    Cw = 1,
2264}
2265
2266/// Face of a vertex.
2267///
2268/// Corresponds to [WebGPU `GPUCullMode`](
2269/// https://gpuweb.github.io/gpuweb/#enumdef-gpucullmode),
2270/// except that the `"none"` value is represented using `Option<Face>` instead.
2271#[repr(C)]
2272#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
2273#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2274#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
2275pub enum Face {
2276    /// Front face
2277    Front = 0,
2278    /// Back face
2279    Back = 1,
2280}
2281
2282/// Type of drawing mode for polygons
2283#[repr(C)]
2284#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
2285#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2286#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
2287pub enum PolygonMode {
2288    /// Polygons are filled
2289    #[default]
2290    Fill = 0,
2291    /// Polygons are drawn as line segments
2292    Line = 1,
2293    /// Polygons are drawn as points
2294    Point = 2,
2295}
2296
2297/// Describes the state of primitive assembly and rasterization in a render pipeline.
2298///
2299/// Corresponds to [WebGPU `GPUPrimitiveState`](
2300/// https://gpuweb.github.io/gpuweb/#dictdef-gpuprimitivestate).
2301#[repr(C)]
2302#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
2303#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2304#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
2305pub struct PrimitiveState {
2306    /// The primitive topology used to interpret vertices.
2307    pub topology: PrimitiveTopology,
2308    /// When drawing strip topologies with indices, this is the required format for the index buffer.
2309    /// This has no effect on non-indexed or non-strip draws.
2310    ///
2311    /// Specifying this value enables primitive restart, allowing individual strips to be separated
2312    /// with the index value `0xFFFF` when using `Uint16`, or `0xFFFFFFFF` when using `Uint32`.
2313    #[cfg_attr(feature = "serde", serde(default))]
2314    pub strip_index_format: Option<IndexFormat>,
2315    /// The face to consider the front for the purpose of culling and stencil operations.
2316    #[cfg_attr(feature = "serde", serde(default))]
2317    pub front_face: FrontFace,
2318    /// The face culling mode.
2319    #[cfg_attr(feature = "serde", serde(default))]
2320    pub cull_mode: Option<Face>,
2321    /// If set to true, the polygon depth is not clipped to 0-1 before rasterization.
2322    ///
2323    /// Enabling this requires `Features::DEPTH_CLIP_CONTROL` to be enabled.
2324    #[cfg_attr(feature = "serde", serde(default))]
2325    pub unclipped_depth: bool,
2326    /// Controls the way each polygon is rasterized. Can be either `Fill` (default), `Line` or `Point`
2327    ///
2328    /// Setting this to `Line` requires `Features::POLYGON_MODE_LINE` to be enabled.
2329    ///
2330    /// Setting this to `Point` requires `Features::POLYGON_MODE_POINT` to be enabled.
2331    #[cfg_attr(feature = "serde", serde(default))]
2332    pub polygon_mode: PolygonMode,
2333    /// If set to true, the primitives are rendered with conservative overestimation. I.e. any rastered pixel touched by it is filled.
2334    /// Only valid for PolygonMode::Fill!
2335    ///
2336    /// Enabling this requires `Features::CONSERVATIVE_RASTERIZATION` to be enabled.
2337    pub conservative: bool,
2338}
2339
2340/// Describes the multi-sampling state of a render pipeline.
2341///
2342/// Corresponds to [WebGPU `GPUMultisampleState`](
2343/// https://gpuweb.github.io/gpuweb/#dictdef-gpumultisamplestate).
2344#[repr(C)]
2345#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
2346#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2347#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
2348pub struct MultisampleState {
2349    /// The number of samples calculated per pixel (for MSAA). For non-multisampled textures,
2350    /// this should be `1`
2351    pub count: u32,
2352    /// Bitmask that restricts the samples of a pixel modified by this pipeline. All samples
2353    /// can be enabled using the value `!0`
2354    pub mask: u64,
2355    /// When enabled, produces another sample mask per pixel based on the alpha output value, that
2356    /// is ANDed with the sample_mask and the primitive coverage to restrict the set of samples
2357    /// affected by a primitive.
2358    ///
2359    /// The implicit mask produced for alpha of zero is guaranteed to be zero, and for alpha of one
2360    /// is guaranteed to be all 1-s.
2361    pub alpha_to_coverage_enabled: bool,
2362}
2363
2364impl Default for MultisampleState {
2365    fn default() -> Self {
2366        MultisampleState {
2367            count: 1,
2368            mask: !0,
2369            alpha_to_coverage_enabled: false,
2370        }
2371    }
2372}
2373
2374bitflags::bitflags! {
2375    /// Feature flags for a texture format.
2376    #[repr(transparent)]
2377    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2378    #[cfg_attr(feature = "serde", serde(transparent))]
2379    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
2380    pub struct TextureFormatFeatureFlags: u32 {
2381        /// If not present, the texture can't be sampled with a filtering sampler.
2382        /// This may overwrite TextureSampleType::Float.filterable
2383        const FILTERABLE = 1 << 0;
2384        /// Allows [`TextureDescriptor::sample_count`] to be `2`.
2385        const MULTISAMPLE_X2 = 1 << 1;
2386        /// Allows [`TextureDescriptor::sample_count`] to be `4`.
2387        const MULTISAMPLE_X4 = 1 << 2 ;
2388        /// Allows [`TextureDescriptor::sample_count`] to be `8`.
2389        const MULTISAMPLE_X8 = 1 << 3 ;
2390        /// Allows [`TextureDescriptor::sample_count`] to be `16`.
2391        const MULTISAMPLE_X16 = 1 << 4;
2392        /// Allows a texture of this format to back a view passed as `resolve_target`
2393        /// to a render pass for an automatic driver-implemented resolve.
2394        const MULTISAMPLE_RESOLVE = 1 << 5;
2395        /// When used as a STORAGE texture, then a texture with this format can be bound with
2396        /// [`StorageTextureAccess::ReadOnly`].
2397        const STORAGE_READ_ONLY = 1 << 6;
2398        /// When used as a STORAGE texture, then a texture with this format can be bound with
2399        /// [`StorageTextureAccess::WriteOnly`].
2400        const STORAGE_WRITE_ONLY = 1 << 7;
2401        /// When used as a STORAGE texture, then a texture with this format can be bound with
2402        /// [`StorageTextureAccess::ReadWrite`].
2403        const STORAGE_READ_WRITE = 1 << 8;
2404        /// When used as a STORAGE texture, then a texture with this format can be bound with
2405        /// [`StorageTextureAccess::Atomic`].
2406        const STORAGE_ATOMIC = 1 << 9;
2407        /// If not present, the texture can't be blended into the render target.
2408        const BLENDABLE = 1 << 10;
2409    }
2410}
2411
2412impl TextureFormatFeatureFlags {
2413    /// Sample count supported by a given texture format.
2414    ///
2415    /// returns `true` if `count` is a supported sample count.
2416    #[must_use]
2417    pub fn sample_count_supported(&self, count: u32) -> bool {
2418        use TextureFormatFeatureFlags as tfsc;
2419
2420        match count {
2421            1 => true,
2422            2 => self.contains(tfsc::MULTISAMPLE_X2),
2423            4 => self.contains(tfsc::MULTISAMPLE_X4),
2424            8 => self.contains(tfsc::MULTISAMPLE_X8),
2425            16 => self.contains(tfsc::MULTISAMPLE_X16),
2426            _ => false,
2427        }
2428    }
2429
2430    /// A `Vec` of supported sample counts.
2431    #[must_use]
2432    pub fn supported_sample_counts(&self) -> Vec<u32> {
2433        let all_possible_sample_counts: [u32; 5] = [1, 2, 4, 8, 16];
2434        all_possible_sample_counts
2435            .into_iter()
2436            .filter(|&sc| self.sample_count_supported(sc))
2437            .collect()
2438    }
2439}
2440
2441/// Features supported by a given texture format
2442///
2443/// Features are defined by WebGPU specification unless `Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES` is enabled.
2444#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
2445#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2446pub struct TextureFormatFeatures {
2447    /// Valid bits for `TextureDescriptor::Usage` provided for format creation.
2448    pub allowed_usages: TextureUsages,
2449    /// Additional property flags for the format.
2450    pub flags: TextureFormatFeatureFlags,
2451}
2452
2453/// ASTC block dimensions
2454#[repr(C)]
2455#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
2456#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2457pub enum AstcBlock {
2458    /// 4x4 block compressed texture. 16 bytes per block (8 bit/px).
2459    B4x4,
2460    /// 5x4 block compressed texture. 16 bytes per block (6.4 bit/px).
2461    B5x4,
2462    /// 5x5 block compressed texture. 16 bytes per block (5.12 bit/px).
2463    B5x5,
2464    /// 6x5 block compressed texture. 16 bytes per block (4.27 bit/px).
2465    B6x5,
2466    /// 6x6 block compressed texture. 16 bytes per block (3.56 bit/px).
2467    B6x6,
2468    /// 8x5 block compressed texture. 16 bytes per block (3.2 bit/px).
2469    B8x5,
2470    /// 8x6 block compressed texture. 16 bytes per block (2.67 bit/px).
2471    B8x6,
2472    /// 8x8 block compressed texture. 16 bytes per block (2 bit/px).
2473    B8x8,
2474    /// 10x5 block compressed texture. 16 bytes per block (2.56 bit/px).
2475    B10x5,
2476    /// 10x6 block compressed texture. 16 bytes per block (2.13 bit/px).
2477    B10x6,
2478    /// 10x8 block compressed texture. 16 bytes per block (1.6 bit/px).
2479    B10x8,
2480    /// 10x10 block compressed texture. 16 bytes per block (1.28 bit/px).
2481    B10x10,
2482    /// 12x10 block compressed texture. 16 bytes per block (1.07 bit/px).
2483    B12x10,
2484    /// 12x12 block compressed texture. 16 bytes per block (0.89 bit/px).
2485    B12x12,
2486}
2487
2488/// ASTC RGBA channel
2489#[repr(C)]
2490#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
2491#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2492pub enum AstcChannel {
2493    /// 8 bit integer RGBA, [0, 255] converted to/from linear-color float [0, 1] in shader.
2494    ///
2495    /// [`Features::TEXTURE_COMPRESSION_ASTC`] must be enabled to use this channel.
2496    Unorm,
2497    /// 8 bit integer RGBA, Srgb-color [0, 255] converted to/from linear-color float [0, 1] in shader.
2498    ///
2499    /// [`Features::TEXTURE_COMPRESSION_ASTC`] must be enabled to use this channel.
2500    UnormSrgb,
2501    /// floating-point RGBA, linear-color float can be outside of the [0, 1] range.
2502    ///
2503    /// [`Features::TEXTURE_COMPRESSION_ASTC_HDR`] must be enabled to use this channel.
2504    Hdr,
2505}
2506
2507/// Underlying texture data format.
2508///
2509/// If there is a conversion in the format (such as srgb -> linear), the conversion listed here is for
2510/// loading from texture in a shader. When writing to the texture, the opposite conversion takes place.
2511///
2512/// Corresponds to [WebGPU `GPUTextureFormat`](
2513/// https://gpuweb.github.io/gpuweb/#enumdef-gputextureformat).
2514#[repr(C)]
2515#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
2516pub enum TextureFormat {
2517    // Normal 8 bit formats
2518    /// Red channel only. 8 bit integer per channel. [0, 255] converted to/from float [0, 1] in shader.
2519    R8Unorm,
2520    /// Red channel only. 8 bit integer per channel. [-127, 127] converted to/from float [-1, 1] in shader.
2521    R8Snorm,
2522    /// Red channel only. 8 bit integer per channel. Unsigned in shader.
2523    R8Uint,
2524    /// Red channel only. 8 bit integer per channel. Signed in shader.
2525    R8Sint,
2526
2527    // Normal 16 bit formats
2528    /// Red channel only. 16 bit integer per channel. Unsigned in shader.
2529    R16Uint,
2530    /// Red channel only. 16 bit integer per channel. Signed in shader.
2531    R16Sint,
2532    /// Red channel only. 16 bit integer per channel. [0, 65535] converted to/from float [0, 1] in shader.
2533    ///
2534    /// [`Features::TEXTURE_FORMAT_16BIT_NORM`] must be enabled to use this texture format.
2535    R16Unorm,
2536    /// Red channel only. 16 bit integer per channel. [0, 65535] converted to/from float [-1, 1] in shader.
2537    ///
2538    /// [`Features::TEXTURE_FORMAT_16BIT_NORM`] must be enabled to use this texture format.
2539    R16Snorm,
2540    /// Red channel only. 16 bit float per channel. Float in shader.
2541    R16Float,
2542    /// Red and green channels. 8 bit integer per channel. [0, 255] converted to/from float [0, 1] in shader.
2543    Rg8Unorm,
2544    /// Red and green channels. 8 bit integer per channel. [-127, 127] converted to/from float [-1, 1] in shader.
2545    Rg8Snorm,
2546    /// Red and green channels. 8 bit integer per channel. Unsigned in shader.
2547    Rg8Uint,
2548    /// Red and green channels. 8 bit integer per channel. Signed in shader.
2549    Rg8Sint,
2550
2551    // Normal 32 bit formats
2552    /// Red channel only. 32 bit integer per channel. Unsigned in shader.
2553    R32Uint,
2554    /// Red channel only. 32 bit integer per channel. Signed in shader.
2555    R32Sint,
2556    /// Red channel only. 32 bit float per channel. Float in shader.
2557    R32Float,
2558    /// Red and green channels. 16 bit integer per channel. Unsigned in shader.
2559    Rg16Uint,
2560    /// Red and green channels. 16 bit integer per channel. Signed in shader.
2561    Rg16Sint,
2562    /// Red and green channels. 16 bit integer per channel. [0, 65535] converted to/from float [0, 1] in shader.
2563    ///
2564    /// [`Features::TEXTURE_FORMAT_16BIT_NORM`] must be enabled to use this texture format.
2565    Rg16Unorm,
2566    /// Red and green channels. 16 bit integer per channel. [0, 65535] converted to/from float [-1, 1] in shader.
2567    ///
2568    /// [`Features::TEXTURE_FORMAT_16BIT_NORM`] must be enabled to use this texture format.
2569    Rg16Snorm,
2570    /// Red and green channels. 16 bit float per channel. Float in shader.
2571    Rg16Float,
2572    /// Red, green, blue, and alpha channels. 8 bit integer per channel. [0, 255] converted to/from float [0, 1] in shader.
2573    Rgba8Unorm,
2574    /// 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.
2575    Rgba8UnormSrgb,
2576    /// Red, green, blue, and alpha channels. 8 bit integer per channel. [-127, 127] converted to/from float [-1, 1] in shader.
2577    Rgba8Snorm,
2578    /// Red, green, blue, and alpha channels. 8 bit integer per channel. Unsigned in shader.
2579    Rgba8Uint,
2580    /// Red, green, blue, and alpha channels. 8 bit integer per channel. Signed in shader.
2581    Rgba8Sint,
2582    /// Blue, green, red, and alpha channels. 8 bit integer per channel. [0, 255] converted to/from float [0, 1] in shader.
2583    Bgra8Unorm,
2584    /// 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.
2585    Bgra8UnormSrgb,
2586
2587    // Packed 32 bit formats
2588    /// Packed unsigned float with 9 bits mantisa for each RGB component, then a common 5 bits exponent
2589    Rgb9e5Ufloat,
2590    /// Red, green, blue, and alpha channels. 10 bit integer for RGB channels, 2 bit integer for alpha channel. Unsigned in shader.
2591    Rgb10a2Uint,
2592    /// 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.
2593    Rgb10a2Unorm,
2594    /// 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.
2595    Rg11b10Ufloat,
2596
2597    // Normal 64 bit formats
2598    /// Red channel only. 64 bit integer per channel. Unsigned in shader.
2599    ///
2600    /// [`Features::TEXTURE_INT64_ATOMIC`] must be enabled to use this texture format.
2601    R64Uint,
2602    /// Red and green channels. 32 bit integer per channel. Unsigned in shader.
2603    Rg32Uint,
2604    /// Red and green channels. 32 bit integer per channel. Signed in shader.
2605    Rg32Sint,
2606    /// Red and green channels. 32 bit float per channel. Float in shader.
2607    Rg32Float,
2608    /// Red, green, blue, and alpha channels. 16 bit integer per channel. Unsigned in shader.
2609    Rgba16Uint,
2610    /// Red, green, blue, and alpha channels. 16 bit integer per channel. Signed in shader.
2611    Rgba16Sint,
2612    /// Red, green, blue, and alpha channels. 16 bit integer per channel. [0, 65535] converted to/from float [0, 1] in shader.
2613    ///
2614    /// [`Features::TEXTURE_FORMAT_16BIT_NORM`] must be enabled to use this texture format.
2615    Rgba16Unorm,
2616    /// Red, green, blue, and alpha. 16 bit integer per channel. [0, 65535] converted to/from float [-1, 1] in shader.
2617    ///
2618    /// [`Features::TEXTURE_FORMAT_16BIT_NORM`] must be enabled to use this texture format.
2619    Rgba16Snorm,
2620    /// Red, green, blue, and alpha channels. 16 bit float per channel. Float in shader.
2621    Rgba16Float,
2622
2623    // Normal 128 bit formats
2624    /// Red, green, blue, and alpha channels. 32 bit integer per channel. Unsigned in shader.
2625    Rgba32Uint,
2626    /// Red, green, blue, and alpha channels. 32 bit integer per channel. Signed in shader.
2627    Rgba32Sint,
2628    /// Red, green, blue, and alpha channels. 32 bit float per channel. Float in shader.
2629    Rgba32Float,
2630
2631    // Depth and stencil formats
2632    /// Stencil format with 8 bit integer stencil.
2633    Stencil8,
2634    /// Special depth format with 16 bit integer depth.
2635    Depth16Unorm,
2636    /// Special depth format with at least 24 bit integer depth.
2637    Depth24Plus,
2638    /// Special depth/stencil format with at least 24 bit integer depth and 8 bits integer stencil.
2639    Depth24PlusStencil8,
2640    /// Special depth format with 32 bit floating point depth.
2641    Depth32Float,
2642    /// Special depth/stencil format with 32 bit floating point depth and 8 bits integer stencil.
2643    ///
2644    /// [`Features::DEPTH32FLOAT_STENCIL8`] must be enabled to use this texture format.
2645    Depth32FloatStencil8,
2646
2647    /// YUV 4:2:0 chroma subsampled format.
2648    ///
2649    /// Contains two planes:
2650    /// - 0: Single 8 bit channel luminance.
2651    /// - 1: Dual 8 bit channel chrominance at half width and half height.
2652    ///
2653    /// Valid view formats for luminance are [`TextureFormat::R8Unorm`].
2654    ///
2655    /// Valid view formats for chrominance are [`TextureFormat::Rg8Unorm`].
2656    ///
2657    /// Width and height must be even.
2658    ///
2659    /// [`Features::TEXTURE_FORMAT_NV12`] must be enabled to use this texture format.
2660    NV12,
2661
2662    // Compressed textures usable with `TEXTURE_COMPRESSION_BC` feature. `TEXTURE_COMPRESSION_SLICED_3D` is required to use with 3D textures.
2663    /// 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.
2664    /// [0, 63] ([0, 1] for alpha) converted to/from float [0, 1] in shader.
2665    ///
2666    /// Also known as DXT1.
2667    ///
2668    /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
2669    /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
2670    Bc1RgbaUnorm,
2671    /// 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.
2672    /// Srgb-color [0, 63] ([0, 1] for alpha) converted to/from linear-color float [0, 1] in shader.
2673    ///
2674    /// Also known as DXT1.
2675    ///
2676    /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
2677    /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
2678    Bc1RgbaUnormSrgb,
2679    /// 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.
2680    /// [0, 63] ([0, 15] for alpha) converted to/from float [0, 1] in shader.
2681    ///
2682    /// Also known as DXT3.
2683    ///
2684    /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
2685    /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
2686    Bc2RgbaUnorm,
2687    /// 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.
2688    /// Srgb-color [0, 63] ([0, 255] for alpha) converted to/from linear-color float [0, 1] in shader.
2689    ///
2690    /// Also known as DXT3.
2691    ///
2692    /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
2693    /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
2694    Bc2RgbaUnormSrgb,
2695    /// 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.
2696    /// [0, 63] ([0, 255] for alpha) converted to/from float [0, 1] in shader.
2697    ///
2698    /// Also known as DXT5.
2699    ///
2700    /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
2701    /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
2702    Bc3RgbaUnorm,
2703    /// 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.
2704    /// Srgb-color [0, 63] ([0, 255] for alpha) converted to/from linear-color float [0, 1] in shader.
2705    ///
2706    /// Also known as DXT5.
2707    ///
2708    /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
2709    /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
2710    Bc3RgbaUnormSrgb,
2711    /// 4x4 block compressed texture. 8 bytes per block (4 bit/px). 8 color pallet. 8 bit R.
2712    /// [0, 255] converted to/from float [0, 1] in shader.
2713    ///
2714    /// Also known as RGTC1.
2715    ///
2716    /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
2717    /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
2718    Bc4RUnorm,
2719    /// 4x4 block compressed texture. 8 bytes per block (4 bit/px). 8 color pallet. 8 bit R.
2720    /// [-127, 127] converted to/from float [-1, 1] in shader.
2721    ///
2722    /// Also known as RGTC1.
2723    ///
2724    /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
2725    /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
2726    Bc4RSnorm,
2727    /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). 8 color red pallet + 8 color green pallet. 8 bit RG.
2728    /// [0, 255] converted to/from float [0, 1] in shader.
2729    ///
2730    /// Also known as RGTC2.
2731    ///
2732    /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
2733    /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
2734    Bc5RgUnorm,
2735    /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). 8 color red pallet + 8 color green pallet. 8 bit RG.
2736    /// [-127, 127] converted to/from float [-1, 1] in shader.
2737    ///
2738    /// Also known as RGTC2.
2739    ///
2740    /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
2741    /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
2742    Bc5RgSnorm,
2743    /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). Variable sized pallet. 16 bit unsigned float RGB. Float in shader.
2744    ///
2745    /// Also known as BPTC (float).
2746    ///
2747    /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
2748    /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
2749    Bc6hRgbUfloat,
2750    /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). Variable sized pallet. 16 bit signed float RGB. Float in shader.
2751    ///
2752    /// Also known as BPTC (float).
2753    ///
2754    /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
2755    /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
2756    Bc6hRgbFloat,
2757    /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). Variable sized pallet. 8 bit integer RGBA.
2758    /// [0, 255] converted to/from float [0, 1] in shader.
2759    ///
2760    /// Also known as BPTC (unorm).
2761    ///
2762    /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
2763    /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
2764    Bc7RgbaUnorm,
2765    /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). Variable sized pallet. 8 bit integer RGBA.
2766    /// Srgb-color [0, 255] converted to/from linear-color float [0, 1] in shader.
2767    ///
2768    /// Also known as BPTC (unorm).
2769    ///
2770    /// [`Features::TEXTURE_COMPRESSION_BC`] must be enabled to use this texture format.
2771    /// [`Features::TEXTURE_COMPRESSION_BC_SLICED_3D`] must be enabled to use this texture format with 3D dimension.
2772    Bc7RgbaUnormSrgb,
2773    /// 4x4 block compressed texture. 8 bytes per block (4 bit/px). Complex pallet. 8 bit integer RGB.
2774    /// [0, 255] converted to/from float [0, 1] in shader.
2775    ///
2776    /// [`Features::TEXTURE_COMPRESSION_ETC2`] must be enabled to use this texture format.
2777    Etc2Rgb8Unorm,
2778    /// 4x4 block compressed texture. 8 bytes per block (4 bit/px). Complex pallet. 8 bit integer RGB.
2779    /// Srgb-color [0, 255] converted to/from linear-color float [0, 1] in shader.
2780    ///
2781    /// [`Features::TEXTURE_COMPRESSION_ETC2`] must be enabled to use this texture format.
2782    Etc2Rgb8UnormSrgb,
2783    /// 4x4 block compressed texture. 8 bytes per block (4 bit/px). Complex pallet. 8 bit integer RGB + 1 bit alpha.
2784    /// [0, 255] ([0, 1] for alpha) converted to/from float [0, 1] in shader.
2785    ///
2786    /// [`Features::TEXTURE_COMPRESSION_ETC2`] must be enabled to use this texture format.
2787    Etc2Rgb8A1Unorm,
2788    /// 4x4 block compressed texture. 8 bytes per block (4 bit/px). Complex pallet. 8 bit integer RGB + 1 bit alpha.
2789    /// Srgb-color [0, 255] ([0, 1] for alpha) converted to/from linear-color float [0, 1] in shader.
2790    ///
2791    /// [`Features::TEXTURE_COMPRESSION_ETC2`] must be enabled to use this texture format.
2792    Etc2Rgb8A1UnormSrgb,
2793    /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). Complex pallet. 8 bit integer RGB + 8 bit alpha.
2794    /// [0, 255] converted to/from float [0, 1] in shader.
2795    ///
2796    /// [`Features::TEXTURE_COMPRESSION_ETC2`] must be enabled to use this texture format.
2797    Etc2Rgba8Unorm,
2798    /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). Complex pallet. 8 bit integer RGB + 8 bit alpha.
2799    /// Srgb-color [0, 255] converted to/from linear-color float [0, 1] in shader.
2800    ///
2801    /// [`Features::TEXTURE_COMPRESSION_ETC2`] must be enabled to use this texture format.
2802    Etc2Rgba8UnormSrgb,
2803    /// 4x4 block compressed texture. 8 bytes per block (4 bit/px). Complex pallet. 11 bit integer R.
2804    /// [0, 255] converted to/from float [0, 1] in shader.
2805    ///
2806    /// [`Features::TEXTURE_COMPRESSION_ETC2`] must be enabled to use this texture format.
2807    EacR11Unorm,
2808    /// 4x4 block compressed texture. 8 bytes per block (4 bit/px). Complex pallet. 11 bit integer R.
2809    /// [-127, 127] converted to/from float [-1, 1] in shader.
2810    ///
2811    /// [`Features::TEXTURE_COMPRESSION_ETC2`] must be enabled to use this texture format.
2812    EacR11Snorm,
2813    /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). Complex pallet. 11 bit integer R + 11 bit integer G.
2814    /// [0, 255] converted to/from float [0, 1] in shader.
2815    ///
2816    /// [`Features::TEXTURE_COMPRESSION_ETC2`] must be enabled to use this texture format.
2817    EacRg11Unorm,
2818    /// 4x4 block compressed texture. 16 bytes per block (8 bit/px). Complex pallet. 11 bit integer R + 11 bit integer G.
2819    /// [-127, 127] converted to/from float [-1, 1] in shader.
2820    ///
2821    /// [`Features::TEXTURE_COMPRESSION_ETC2`] must be enabled to use this texture format.
2822    EacRg11Snorm,
2823    /// block compressed texture. 16 bytes per block.
2824    ///
2825    /// Features [`TEXTURE_COMPRESSION_ASTC`] or [`TEXTURE_COMPRESSION_ASTC_HDR`]
2826    /// must be enabled to use this texture format.
2827    ///
2828    /// [`TEXTURE_COMPRESSION_ASTC`]: Features::TEXTURE_COMPRESSION_ASTC
2829    /// [`TEXTURE_COMPRESSION_ASTC_HDR`]: Features::TEXTURE_COMPRESSION_ASTC_HDR
2830    Astc {
2831        /// compressed block dimensions
2832        block: AstcBlock,
2833        /// ASTC RGBA channel
2834        channel: AstcChannel,
2835    },
2836}
2837
2838#[cfg(any(feature = "serde", test))]
2839impl<'de> Deserialize<'de> for TextureFormat {
2840    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2841    where
2842        D: serde::Deserializer<'de>,
2843    {
2844        use serde::de::{self, Error, Unexpected};
2845
2846        struct TextureFormatVisitor;
2847
2848        impl de::Visitor<'_> for TextureFormatVisitor {
2849            type Value = TextureFormat;
2850
2851            fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
2852                formatter.write_str("a valid texture format")
2853            }
2854
2855            fn visit_str<E: Error>(self, s: &str) -> Result<Self::Value, E> {
2856                let format = match s {
2857                    "r8unorm" => TextureFormat::R8Unorm,
2858                    "r8snorm" => TextureFormat::R8Snorm,
2859                    "r8uint" => TextureFormat::R8Uint,
2860                    "r8sint" => TextureFormat::R8Sint,
2861                    "r16uint" => TextureFormat::R16Uint,
2862                    "r16sint" => TextureFormat::R16Sint,
2863                    "r16unorm" => TextureFormat::R16Unorm,
2864                    "r16snorm" => TextureFormat::R16Snorm,
2865                    "r16float" => TextureFormat::R16Float,
2866                    "rg8unorm" => TextureFormat::Rg8Unorm,
2867                    "rg8snorm" => TextureFormat::Rg8Snorm,
2868                    "rg8uint" => TextureFormat::Rg8Uint,
2869                    "rg8sint" => TextureFormat::Rg8Sint,
2870                    "r32uint" => TextureFormat::R32Uint,
2871                    "r32sint" => TextureFormat::R32Sint,
2872                    "r32float" => TextureFormat::R32Float,
2873                    "rg16uint" => TextureFormat::Rg16Uint,
2874                    "rg16sint" => TextureFormat::Rg16Sint,
2875                    "rg16unorm" => TextureFormat::Rg16Unorm,
2876                    "rg16snorm" => TextureFormat::Rg16Snorm,
2877                    "rg16float" => TextureFormat::Rg16Float,
2878                    "rgba8unorm" => TextureFormat::Rgba8Unorm,
2879                    "rgba8unorm-srgb" => TextureFormat::Rgba8UnormSrgb,
2880                    "rgba8snorm" => TextureFormat::Rgba8Snorm,
2881                    "rgba8uint" => TextureFormat::Rgba8Uint,
2882                    "rgba8sint" => TextureFormat::Rgba8Sint,
2883                    "bgra8unorm" => TextureFormat::Bgra8Unorm,
2884                    "bgra8unorm-srgb" => TextureFormat::Bgra8UnormSrgb,
2885                    "rgb10a2uint" => TextureFormat::Rgb10a2Uint,
2886                    "rgb10a2unorm" => TextureFormat::Rgb10a2Unorm,
2887                    "rg11b10ufloat" => TextureFormat::Rg11b10Ufloat,
2888                    "r64uint" => TextureFormat::R64Uint,
2889                    "rg32uint" => TextureFormat::Rg32Uint,
2890                    "rg32sint" => TextureFormat::Rg32Sint,
2891                    "rg32float" => TextureFormat::Rg32Float,
2892                    "rgba16uint" => TextureFormat::Rgba16Uint,
2893                    "rgba16sint" => TextureFormat::Rgba16Sint,
2894                    "rgba16unorm" => TextureFormat::Rgba16Unorm,
2895                    "rgba16snorm" => TextureFormat::Rgba16Snorm,
2896                    "rgba16float" => TextureFormat::Rgba16Float,
2897                    "rgba32uint" => TextureFormat::Rgba32Uint,
2898                    "rgba32sint" => TextureFormat::Rgba32Sint,
2899                    "rgba32float" => TextureFormat::Rgba32Float,
2900                    "stencil8" => TextureFormat::Stencil8,
2901                    "depth32float" => TextureFormat::Depth32Float,
2902                    "depth32float-stencil8" => TextureFormat::Depth32FloatStencil8,
2903                    "depth16unorm" => TextureFormat::Depth16Unorm,
2904                    "depth24plus" => TextureFormat::Depth24Plus,
2905                    "depth24plus-stencil8" => TextureFormat::Depth24PlusStencil8,
2906                    "nv12" => TextureFormat::NV12,
2907                    "rgb9e5ufloat" => TextureFormat::Rgb9e5Ufloat,
2908                    "bc1-rgba-unorm" => TextureFormat::Bc1RgbaUnorm,
2909                    "bc1-rgba-unorm-srgb" => TextureFormat::Bc1RgbaUnormSrgb,
2910                    "bc2-rgba-unorm" => TextureFormat::Bc2RgbaUnorm,
2911                    "bc2-rgba-unorm-srgb" => TextureFormat::Bc2RgbaUnormSrgb,
2912                    "bc3-rgba-unorm" => TextureFormat::Bc3RgbaUnorm,
2913                    "bc3-rgba-unorm-srgb" => TextureFormat::Bc3RgbaUnormSrgb,
2914                    "bc4-r-unorm" => TextureFormat::Bc4RUnorm,
2915                    "bc4-r-snorm" => TextureFormat::Bc4RSnorm,
2916                    "bc5-rg-unorm" => TextureFormat::Bc5RgUnorm,
2917                    "bc5-rg-snorm" => TextureFormat::Bc5RgSnorm,
2918                    "bc6h-rgb-ufloat" => TextureFormat::Bc6hRgbUfloat,
2919                    "bc6h-rgb-float" => TextureFormat::Bc6hRgbFloat,
2920                    "bc7-rgba-unorm" => TextureFormat::Bc7RgbaUnorm,
2921                    "bc7-rgba-unorm-srgb" => TextureFormat::Bc7RgbaUnormSrgb,
2922                    "etc2-rgb8unorm" => TextureFormat::Etc2Rgb8Unorm,
2923                    "etc2-rgb8unorm-srgb" => TextureFormat::Etc2Rgb8UnormSrgb,
2924                    "etc2-rgb8a1unorm" => TextureFormat::Etc2Rgb8A1Unorm,
2925                    "etc2-rgb8a1unorm-srgb" => TextureFormat::Etc2Rgb8A1UnormSrgb,
2926                    "etc2-rgba8unorm" => TextureFormat::Etc2Rgba8Unorm,
2927                    "etc2-rgba8unorm-srgb" => TextureFormat::Etc2Rgba8UnormSrgb,
2928                    "eac-r11unorm" => TextureFormat::EacR11Unorm,
2929                    "eac-r11snorm" => TextureFormat::EacR11Snorm,
2930                    "eac-rg11unorm" => TextureFormat::EacRg11Unorm,
2931                    "eac-rg11snorm" => TextureFormat::EacRg11Snorm,
2932                    other => {
2933                        if let Some(parts) = other.strip_prefix("astc-") {
2934                            let (block, channel) = parts
2935                                .split_once('-')
2936                                .ok_or_else(|| E::invalid_value(Unexpected::Str(s), &self))?;
2937
2938                            let block = match block {
2939                                "4x4" => AstcBlock::B4x4,
2940                                "5x4" => AstcBlock::B5x4,
2941                                "5x5" => AstcBlock::B5x5,
2942                                "6x5" => AstcBlock::B6x5,
2943                                "6x6" => AstcBlock::B6x6,
2944                                "8x5" => AstcBlock::B8x5,
2945                                "8x6" => AstcBlock::B8x6,
2946                                "8x8" => AstcBlock::B8x8,
2947                                "10x5" => AstcBlock::B10x5,
2948                                "10x6" => AstcBlock::B10x6,
2949                                "10x8" => AstcBlock::B10x8,
2950                                "10x10" => AstcBlock::B10x10,
2951                                "12x10" => AstcBlock::B12x10,
2952                                "12x12" => AstcBlock::B12x12,
2953                                _ => return Err(E::invalid_value(Unexpected::Str(s), &self)),
2954                            };
2955
2956                            let channel = match channel {
2957                                "unorm" => AstcChannel::Unorm,
2958                                "unorm-srgb" => AstcChannel::UnormSrgb,
2959                                "hdr" => AstcChannel::Hdr,
2960                                _ => return Err(E::invalid_value(Unexpected::Str(s), &self)),
2961                            };
2962
2963                            TextureFormat::Astc { block, channel }
2964                        } else {
2965                            return Err(E::invalid_value(Unexpected::Str(s), &self));
2966                        }
2967                    }
2968                };
2969
2970                Ok(format)
2971            }
2972        }
2973
2974        deserializer.deserialize_str(TextureFormatVisitor)
2975    }
2976}
2977
2978#[cfg(any(feature = "serde", test))]
2979impl Serialize for TextureFormat {
2980    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
2981    where
2982        S: serde::Serializer,
2983    {
2984        let s: String;
2985        let name = match *self {
2986            TextureFormat::R8Unorm => "r8unorm",
2987            TextureFormat::R8Snorm => "r8snorm",
2988            TextureFormat::R8Uint => "r8uint",
2989            TextureFormat::R8Sint => "r8sint",
2990            TextureFormat::R16Uint => "r16uint",
2991            TextureFormat::R16Sint => "r16sint",
2992            TextureFormat::R16Unorm => "r16unorm",
2993            TextureFormat::R16Snorm => "r16snorm",
2994            TextureFormat::R16Float => "r16float",
2995            TextureFormat::Rg8Unorm => "rg8unorm",
2996            TextureFormat::Rg8Snorm => "rg8snorm",
2997            TextureFormat::Rg8Uint => "rg8uint",
2998            TextureFormat::Rg8Sint => "rg8sint",
2999            TextureFormat::R32Uint => "r32uint",
3000            TextureFormat::R32Sint => "r32sint",
3001            TextureFormat::R32Float => "r32float",
3002            TextureFormat::Rg16Uint => "rg16uint",
3003            TextureFormat::Rg16Sint => "rg16sint",
3004            TextureFormat::Rg16Unorm => "rg16unorm",
3005            TextureFormat::Rg16Snorm => "rg16snorm",
3006            TextureFormat::Rg16Float => "rg16float",
3007            TextureFormat::Rgba8Unorm => "rgba8unorm",
3008            TextureFormat::Rgba8UnormSrgb => "rgba8unorm-srgb",
3009            TextureFormat::Rgba8Snorm => "rgba8snorm",
3010            TextureFormat::Rgba8Uint => "rgba8uint",
3011            TextureFormat::Rgba8Sint => "rgba8sint",
3012            TextureFormat::Bgra8Unorm => "bgra8unorm",
3013            TextureFormat::Bgra8UnormSrgb => "bgra8unorm-srgb",
3014            TextureFormat::Rgb10a2Uint => "rgb10a2uint",
3015            TextureFormat::Rgb10a2Unorm => "rgb10a2unorm",
3016            TextureFormat::Rg11b10Ufloat => "rg11b10ufloat",
3017            TextureFormat::R64Uint => "r64uint",
3018            TextureFormat::Rg32Uint => "rg32uint",
3019            TextureFormat::Rg32Sint => "rg32sint",
3020            TextureFormat::Rg32Float => "rg32float",
3021            TextureFormat::Rgba16Uint => "rgba16uint",
3022            TextureFormat::Rgba16Sint => "rgba16sint",
3023            TextureFormat::Rgba16Unorm => "rgba16unorm",
3024            TextureFormat::Rgba16Snorm => "rgba16snorm",
3025            TextureFormat::Rgba16Float => "rgba16float",
3026            TextureFormat::Rgba32Uint => "rgba32uint",
3027            TextureFormat::Rgba32Sint => "rgba32sint",
3028            TextureFormat::Rgba32Float => "rgba32float",
3029            TextureFormat::Stencil8 => "stencil8",
3030            TextureFormat::Depth32Float => "depth32float",
3031            TextureFormat::Depth16Unorm => "depth16unorm",
3032            TextureFormat::Depth32FloatStencil8 => "depth32float-stencil8",
3033            TextureFormat::Depth24Plus => "depth24plus",
3034            TextureFormat::Depth24PlusStencil8 => "depth24plus-stencil8",
3035            TextureFormat::NV12 => "nv12",
3036            TextureFormat::Rgb9e5Ufloat => "rgb9e5ufloat",
3037            TextureFormat::Bc1RgbaUnorm => "bc1-rgba-unorm",
3038            TextureFormat::Bc1RgbaUnormSrgb => "bc1-rgba-unorm-srgb",
3039            TextureFormat::Bc2RgbaUnorm => "bc2-rgba-unorm",
3040            TextureFormat::Bc2RgbaUnormSrgb => "bc2-rgba-unorm-srgb",
3041            TextureFormat::Bc3RgbaUnorm => "bc3-rgba-unorm",
3042            TextureFormat::Bc3RgbaUnormSrgb => "bc3-rgba-unorm-srgb",
3043            TextureFormat::Bc4RUnorm => "bc4-r-unorm",
3044            TextureFormat::Bc4RSnorm => "bc4-r-snorm",
3045            TextureFormat::Bc5RgUnorm => "bc5-rg-unorm",
3046            TextureFormat::Bc5RgSnorm => "bc5-rg-snorm",
3047            TextureFormat::Bc6hRgbUfloat => "bc6h-rgb-ufloat",
3048            TextureFormat::Bc6hRgbFloat => "bc6h-rgb-float",
3049            TextureFormat::Bc7RgbaUnorm => "bc7-rgba-unorm",
3050            TextureFormat::Bc7RgbaUnormSrgb => "bc7-rgba-unorm-srgb",
3051            TextureFormat::Etc2Rgb8Unorm => "etc2-rgb8unorm",
3052            TextureFormat::Etc2Rgb8UnormSrgb => "etc2-rgb8unorm-srgb",
3053            TextureFormat::Etc2Rgb8A1Unorm => "etc2-rgb8a1unorm",
3054            TextureFormat::Etc2Rgb8A1UnormSrgb => "etc2-rgb8a1unorm-srgb",
3055            TextureFormat::Etc2Rgba8Unorm => "etc2-rgba8unorm",
3056            TextureFormat::Etc2Rgba8UnormSrgb => "etc2-rgba8unorm-srgb",
3057            TextureFormat::EacR11Unorm => "eac-r11unorm",
3058            TextureFormat::EacR11Snorm => "eac-r11snorm",
3059            TextureFormat::EacRg11Unorm => "eac-rg11unorm",
3060            TextureFormat::EacRg11Snorm => "eac-rg11snorm",
3061            TextureFormat::Astc { block, channel } => {
3062                let block = match block {
3063                    AstcBlock::B4x4 => "4x4",
3064                    AstcBlock::B5x4 => "5x4",
3065                    AstcBlock::B5x5 => "5x5",
3066                    AstcBlock::B6x5 => "6x5",
3067                    AstcBlock::B6x6 => "6x6",
3068                    AstcBlock::B8x5 => "8x5",
3069                    AstcBlock::B8x6 => "8x6",
3070                    AstcBlock::B8x8 => "8x8",
3071                    AstcBlock::B10x5 => "10x5",
3072                    AstcBlock::B10x6 => "10x6",
3073                    AstcBlock::B10x8 => "10x8",
3074                    AstcBlock::B10x10 => "10x10",
3075                    AstcBlock::B12x10 => "12x10",
3076                    AstcBlock::B12x12 => "12x12",
3077                };
3078
3079                let channel = match channel {
3080                    AstcChannel::Unorm => "unorm",
3081                    AstcChannel::UnormSrgb => "unorm-srgb",
3082                    AstcChannel::Hdr => "hdr",
3083                };
3084
3085                s = format!("astc-{block}-{channel}");
3086                &s
3087            }
3088        };
3089        serializer.serialize_str(name)
3090    }
3091}
3092
3093impl TextureAspect {
3094    /// Returns the texture aspect for a given plane.
3095    #[must_use]
3096    pub fn from_plane(plane: u32) -> Option<Self> {
3097        Some(match plane {
3098            0 => Self::Plane0,
3099            1 => Self::Plane1,
3100            2 => Self::Plane2,
3101            _ => return None,
3102        })
3103    }
3104}
3105
3106impl TextureFormat {
3107    /// Returns the aspect-specific format of the original format
3108    ///
3109    /// see <https://gpuweb.github.io/gpuweb/#abstract-opdef-resolving-gputextureaspect>
3110    #[must_use]
3111    pub fn aspect_specific_format(&self, aspect: TextureAspect) -> Option<Self> {
3112        match (*self, aspect) {
3113            (Self::Stencil8, TextureAspect::StencilOnly) => Some(*self),
3114            (
3115                Self::Depth16Unorm | Self::Depth24Plus | Self::Depth32Float,
3116                TextureAspect::DepthOnly,
3117            ) => Some(*self),
3118            (
3119                Self::Depth24PlusStencil8 | Self::Depth32FloatStencil8,
3120                TextureAspect::StencilOnly,
3121            ) => Some(Self::Stencil8),
3122            (Self::Depth24PlusStencil8, TextureAspect::DepthOnly) => Some(Self::Depth24Plus),
3123            (Self::Depth32FloatStencil8, TextureAspect::DepthOnly) => Some(Self::Depth32Float),
3124            (Self::NV12, TextureAspect::Plane0) => Some(Self::R8Unorm),
3125            (Self::NV12, TextureAspect::Plane1) => Some(Self::Rg8Unorm),
3126            // views to multi-planar formats must specify the plane
3127            (format, TextureAspect::All) if !format.is_multi_planar_format() => Some(format),
3128            _ => None,
3129        }
3130    }
3131
3132    /// Returns `true` if `self` is a depth or stencil component of the given
3133    /// combined depth-stencil format
3134    #[must_use]
3135    pub fn is_depth_stencil_component(&self, combined_format: Self) -> bool {
3136        match (combined_format, *self) {
3137            (Self::Depth24PlusStencil8, Self::Depth24Plus | Self::Stencil8)
3138            | (Self::Depth32FloatStencil8, Self::Depth32Float | Self::Stencil8) => true,
3139            _ => false,
3140        }
3141    }
3142
3143    /// Returns `true` if the format is a depth and/or stencil format
3144    ///
3145    /// see <https://gpuweb.github.io/gpuweb/#depth-formats>
3146    #[must_use]
3147    pub fn is_depth_stencil_format(&self) -> bool {
3148        match *self {
3149            Self::Stencil8
3150            | Self::Depth16Unorm
3151            | Self::Depth24Plus
3152            | Self::Depth24PlusStencil8
3153            | Self::Depth32Float
3154            | Self::Depth32FloatStencil8 => true,
3155            _ => false,
3156        }
3157    }
3158
3159    /// Returns `true` if the format is a combined depth-stencil format
3160    ///
3161    /// see <https://gpuweb.github.io/gpuweb/#combined-depth-stencil-format>
3162    #[must_use]
3163    pub fn is_combined_depth_stencil_format(&self) -> bool {
3164        match *self {
3165            Self::Depth24PlusStencil8 | Self::Depth32FloatStencil8 => true,
3166            _ => false,
3167        }
3168    }
3169
3170    /// Returns `true` if the format is a multi-planar format
3171    #[must_use]
3172    pub fn is_multi_planar_format(&self) -> bool {
3173        self.planes().is_some()
3174    }
3175
3176    /// Returns the number of planes a multi-planar format has.
3177    #[must_use]
3178    pub fn planes(&self) -> Option<u32> {
3179        match *self {
3180            Self::NV12 => Some(2),
3181            _ => None,
3182        }
3183    }
3184
3185    /// Returns `true` if the format has a color aspect
3186    #[must_use]
3187    pub fn has_color_aspect(&self) -> bool {
3188        !self.is_depth_stencil_format()
3189    }
3190
3191    /// Returns `true` if the format has a depth aspect
3192    #[must_use]
3193    pub fn has_depth_aspect(&self) -> bool {
3194        match *self {
3195            Self::Depth16Unorm
3196            | Self::Depth24Plus
3197            | Self::Depth24PlusStencil8
3198            | Self::Depth32Float
3199            | Self::Depth32FloatStencil8 => true,
3200            _ => false,
3201        }
3202    }
3203
3204    /// Returns `true` if the format has a stencil aspect
3205    #[must_use]
3206    pub fn has_stencil_aspect(&self) -> bool {
3207        match *self {
3208            Self::Stencil8 | Self::Depth24PlusStencil8 | Self::Depth32FloatStencil8 => true,
3209            _ => false,
3210        }
3211    }
3212
3213    /// Returns the size multiple requirement for a texture using this format.
3214    #[must_use]
3215    pub fn size_multiple_requirement(&self) -> (u32, u32) {
3216        match *self {
3217            Self::NV12 => (2, 2),
3218            _ => self.block_dimensions(),
3219        }
3220    }
3221
3222    /// Returns the dimension of a [block](https://gpuweb.github.io/gpuweb/#texel-block) of texels.
3223    ///
3224    /// Uncompressed formats have a block dimension of `(1, 1)`.
3225    #[must_use]
3226    pub fn block_dimensions(&self) -> (u32, u32) {
3227        match *self {
3228            Self::R8Unorm
3229            | Self::R8Snorm
3230            | Self::R8Uint
3231            | Self::R8Sint
3232            | Self::R16Uint
3233            | Self::R16Sint
3234            | Self::R16Unorm
3235            | Self::R16Snorm
3236            | Self::R16Float
3237            | Self::Rg8Unorm
3238            | Self::Rg8Snorm
3239            | Self::Rg8Uint
3240            | Self::Rg8Sint
3241            | Self::R32Uint
3242            | Self::R32Sint
3243            | Self::R32Float
3244            | Self::Rg16Uint
3245            | Self::Rg16Sint
3246            | Self::Rg16Unorm
3247            | Self::Rg16Snorm
3248            | Self::Rg16Float
3249            | Self::Rgba8Unorm
3250            | Self::Rgba8UnormSrgb
3251            | Self::Rgba8Snorm
3252            | Self::Rgba8Uint
3253            | Self::Rgba8Sint
3254            | Self::Bgra8Unorm
3255            | Self::Bgra8UnormSrgb
3256            | Self::Rgb9e5Ufloat
3257            | Self::Rgb10a2Uint
3258            | Self::Rgb10a2Unorm
3259            | Self::Rg11b10Ufloat
3260            | Self::R64Uint
3261            | Self::Rg32Uint
3262            | Self::Rg32Sint
3263            | Self::Rg32Float
3264            | Self::Rgba16Uint
3265            | Self::Rgba16Sint
3266            | Self::Rgba16Unorm
3267            | Self::Rgba16Snorm
3268            | Self::Rgba16Float
3269            | Self::Rgba32Uint
3270            | Self::Rgba32Sint
3271            | Self::Rgba32Float
3272            | Self::Stencil8
3273            | Self::Depth16Unorm
3274            | Self::Depth24Plus
3275            | Self::Depth24PlusStencil8
3276            | Self::Depth32Float
3277            | Self::Depth32FloatStencil8
3278            | Self::NV12 => (1, 1),
3279
3280            Self::Bc1RgbaUnorm
3281            | Self::Bc1RgbaUnormSrgb
3282            | Self::Bc2RgbaUnorm
3283            | Self::Bc2RgbaUnormSrgb
3284            | Self::Bc3RgbaUnorm
3285            | Self::Bc3RgbaUnormSrgb
3286            | Self::Bc4RUnorm
3287            | Self::Bc4RSnorm
3288            | Self::Bc5RgUnorm
3289            | Self::Bc5RgSnorm
3290            | Self::Bc6hRgbUfloat
3291            | Self::Bc6hRgbFloat
3292            | Self::Bc7RgbaUnorm
3293            | Self::Bc7RgbaUnormSrgb => (4, 4),
3294
3295            Self::Etc2Rgb8Unorm
3296            | Self::Etc2Rgb8UnormSrgb
3297            | Self::Etc2Rgb8A1Unorm
3298            | Self::Etc2Rgb8A1UnormSrgb
3299            | Self::Etc2Rgba8Unorm
3300            | Self::Etc2Rgba8UnormSrgb
3301            | Self::EacR11Unorm
3302            | Self::EacR11Snorm
3303            | Self::EacRg11Unorm
3304            | Self::EacRg11Snorm => (4, 4),
3305
3306            Self::Astc { block, .. } => match block {
3307                AstcBlock::B4x4 => (4, 4),
3308                AstcBlock::B5x4 => (5, 4),
3309                AstcBlock::B5x5 => (5, 5),
3310                AstcBlock::B6x5 => (6, 5),
3311                AstcBlock::B6x6 => (6, 6),
3312                AstcBlock::B8x5 => (8, 5),
3313                AstcBlock::B8x6 => (8, 6),
3314                AstcBlock::B8x8 => (8, 8),
3315                AstcBlock::B10x5 => (10, 5),
3316                AstcBlock::B10x6 => (10, 6),
3317                AstcBlock::B10x8 => (10, 8),
3318                AstcBlock::B10x10 => (10, 10),
3319                AstcBlock::B12x10 => (12, 10),
3320                AstcBlock::B12x12 => (12, 12),
3321            },
3322        }
3323    }
3324
3325    /// Returns `true` for compressed formats.
3326    #[must_use]
3327    pub fn is_compressed(&self) -> bool {
3328        self.block_dimensions() != (1, 1)
3329    }
3330
3331    /// Returns `true` for BCn compressed formats.
3332    #[must_use]
3333    pub fn is_bcn(&self) -> bool {
3334        self.required_features() == Features::TEXTURE_COMPRESSION_BC
3335    }
3336
3337    /// Returns the required features (if any) in order to use the texture.
3338    #[must_use]
3339    pub fn required_features(&self) -> Features {
3340        match *self {
3341            Self::R8Unorm
3342            | Self::R8Snorm
3343            | Self::R8Uint
3344            | Self::R8Sint
3345            | Self::R16Uint
3346            | Self::R16Sint
3347            | Self::R16Float
3348            | Self::Rg8Unorm
3349            | Self::Rg8Snorm
3350            | Self::Rg8Uint
3351            | Self::Rg8Sint
3352            | Self::R32Uint
3353            | Self::R32Sint
3354            | Self::R32Float
3355            | Self::Rg16Uint
3356            | Self::Rg16Sint
3357            | Self::Rg16Float
3358            | Self::Rgba8Unorm
3359            | Self::Rgba8UnormSrgb
3360            | Self::Rgba8Snorm
3361            | Self::Rgba8Uint
3362            | Self::Rgba8Sint
3363            | Self::Bgra8Unorm
3364            | Self::Bgra8UnormSrgb
3365            | Self::Rgb9e5Ufloat
3366            | Self::Rgb10a2Uint
3367            | Self::Rgb10a2Unorm
3368            | Self::Rg11b10Ufloat
3369            | Self::Rg32Uint
3370            | Self::Rg32Sint
3371            | Self::Rg32Float
3372            | Self::Rgba16Uint
3373            | Self::Rgba16Sint
3374            | Self::Rgba16Float
3375            | Self::Rgba32Uint
3376            | Self::Rgba32Sint
3377            | Self::Rgba32Float
3378            | Self::Stencil8
3379            | Self::Depth16Unorm
3380            | Self::Depth24Plus
3381            | Self::Depth24PlusStencil8
3382            | Self::Depth32Float => Features::empty(),
3383
3384            Self::R64Uint => Features::TEXTURE_INT64_ATOMIC,
3385
3386            Self::Depth32FloatStencil8 => Features::DEPTH32FLOAT_STENCIL8,
3387
3388            Self::NV12 => Features::TEXTURE_FORMAT_NV12,
3389
3390            Self::R16Unorm
3391            | Self::R16Snorm
3392            | Self::Rg16Unorm
3393            | Self::Rg16Snorm
3394            | Self::Rgba16Unorm
3395            | Self::Rgba16Snorm => Features::TEXTURE_FORMAT_16BIT_NORM,
3396
3397            Self::Bc1RgbaUnorm
3398            | Self::Bc1RgbaUnormSrgb
3399            | Self::Bc2RgbaUnorm
3400            | Self::Bc2RgbaUnormSrgb
3401            | Self::Bc3RgbaUnorm
3402            | Self::Bc3RgbaUnormSrgb
3403            | Self::Bc4RUnorm
3404            | Self::Bc4RSnorm
3405            | Self::Bc5RgUnorm
3406            | Self::Bc5RgSnorm
3407            | Self::Bc6hRgbUfloat
3408            | Self::Bc6hRgbFloat
3409            | Self::Bc7RgbaUnorm
3410            | Self::Bc7RgbaUnormSrgb => Features::TEXTURE_COMPRESSION_BC,
3411
3412            Self::Etc2Rgb8Unorm
3413            | Self::Etc2Rgb8UnormSrgb
3414            | Self::Etc2Rgb8A1Unorm
3415            | Self::Etc2Rgb8A1UnormSrgb
3416            | Self::Etc2Rgba8Unorm
3417            | Self::Etc2Rgba8UnormSrgb
3418            | Self::EacR11Unorm
3419            | Self::EacR11Snorm
3420            | Self::EacRg11Unorm
3421            | Self::EacRg11Snorm => Features::TEXTURE_COMPRESSION_ETC2,
3422
3423            Self::Astc { channel, .. } => match channel {
3424                AstcChannel::Hdr => Features::TEXTURE_COMPRESSION_ASTC_HDR,
3425                AstcChannel::Unorm | AstcChannel::UnormSrgb => Features::TEXTURE_COMPRESSION_ASTC,
3426            },
3427        }
3428    }
3429
3430    /// Returns the format features guaranteed by the WebGPU spec.
3431    ///
3432    /// Additional features are available if `Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES` is enabled.
3433    #[must_use]
3434    pub fn guaranteed_format_features(&self, device_features: Features) -> TextureFormatFeatures {
3435        // Multisampling
3436        let none = TextureFormatFeatureFlags::empty();
3437        let msaa = TextureFormatFeatureFlags::MULTISAMPLE_X4;
3438        let msaa_resolve = msaa | TextureFormatFeatureFlags::MULTISAMPLE_RESOLVE;
3439
3440        let s_ro_wo = TextureFormatFeatureFlags::STORAGE_READ_ONLY
3441            | TextureFormatFeatureFlags::STORAGE_WRITE_ONLY;
3442        let s_all = s_ro_wo | TextureFormatFeatureFlags::STORAGE_READ_WRITE;
3443
3444        // Flags
3445        let basic =
3446            TextureUsages::COPY_SRC | TextureUsages::COPY_DST | TextureUsages::TEXTURE_BINDING;
3447        let attachment = basic | TextureUsages::RENDER_ATTACHMENT;
3448        let storage = basic | TextureUsages::STORAGE_BINDING;
3449        let binding = TextureUsages::TEXTURE_BINDING;
3450        let all_flags = attachment | storage | binding;
3451        let atomic_64 = if device_features.contains(Features::TEXTURE_ATOMIC) {
3452            storage | binding | TextureUsages::STORAGE_ATOMIC
3453        } else {
3454            storage | binding
3455        };
3456        let atomic = attachment | atomic_64;
3457        let rg11b10f = if device_features.contains(Features::RG11B10UFLOAT_RENDERABLE) {
3458            attachment
3459        } else {
3460            basic
3461        };
3462        let (bgra8unorm_f, bgra8unorm) = if device_features.contains(Features::BGRA8UNORM_STORAGE) {
3463            (
3464                msaa_resolve | TextureFormatFeatureFlags::STORAGE_WRITE_ONLY,
3465                attachment | TextureUsages::STORAGE_BINDING,
3466            )
3467        } else {
3468            (msaa_resolve, attachment)
3469        };
3470
3471        #[rustfmt::skip] // lets make a nice table
3472        let (
3473            mut flags,
3474            allowed_usages,
3475        ) = match *self {
3476            Self::R8Unorm =>              (msaa_resolve, attachment),
3477            Self::R8Snorm =>              (        none,      basic),
3478            Self::R8Uint =>               (        msaa, attachment),
3479            Self::R8Sint =>               (        msaa, attachment),
3480            Self::R16Uint =>              (        msaa, attachment),
3481            Self::R16Sint =>              (        msaa, attachment),
3482            Self::R16Float =>             (msaa_resolve, attachment),
3483            Self::Rg8Unorm =>             (msaa_resolve, attachment),
3484            Self::Rg8Snorm =>             (        none,      basic),
3485            Self::Rg8Uint =>              (        msaa, attachment),
3486            Self::Rg8Sint =>              (        msaa, attachment),
3487            Self::R32Uint =>              (       s_all,     atomic),
3488            Self::R32Sint =>              (       s_all,     atomic),
3489            Self::R32Float =>             (msaa | s_all,  all_flags),
3490            Self::Rg16Uint =>             (        msaa, attachment),
3491            Self::Rg16Sint =>             (        msaa, attachment),
3492            Self::Rg16Float =>            (msaa_resolve, attachment),
3493            Self::Rgba8Unorm =>           (msaa_resolve | s_ro_wo,  all_flags),
3494            Self::Rgba8UnormSrgb =>       (msaa_resolve, attachment),
3495            Self::Rgba8Snorm =>           (     s_ro_wo,    storage),
3496            Self::Rgba8Uint =>            (        msaa | s_ro_wo,  all_flags),
3497            Self::Rgba8Sint =>            (        msaa | s_ro_wo,  all_flags),
3498            Self::Bgra8Unorm =>           (bgra8unorm_f, bgra8unorm),
3499            Self::Bgra8UnormSrgb =>       (msaa_resolve, attachment),
3500            Self::Rgb10a2Uint =>          (        msaa, attachment),
3501            Self::Rgb10a2Unorm =>         (msaa_resolve, attachment),
3502            Self::Rg11b10Ufloat =>        (        msaa,   rg11b10f),
3503            Self::R64Uint =>              (     s_ro_wo,  atomic_64),
3504            Self::Rg32Uint =>             (     s_ro_wo,  all_flags),
3505            Self::Rg32Sint =>             (     s_ro_wo,  all_flags),
3506            Self::Rg32Float =>            (     s_ro_wo,  all_flags),
3507            Self::Rgba16Uint =>           (        msaa | s_ro_wo,  all_flags),
3508            Self::Rgba16Sint =>           (        msaa | s_ro_wo,  all_flags),
3509            Self::Rgba16Float =>          (msaa_resolve | s_ro_wo,  all_flags),
3510            Self::Rgba32Uint =>           (     s_ro_wo,  all_flags),
3511            Self::Rgba32Sint =>           (     s_ro_wo,  all_flags),
3512            Self::Rgba32Float =>          (     s_ro_wo,  all_flags),
3513
3514            Self::Stencil8 =>             (        msaa, attachment),
3515            Self::Depth16Unorm =>         (        msaa, attachment),
3516            Self::Depth24Plus =>          (        msaa, attachment),
3517            Self::Depth24PlusStencil8 =>  (        msaa, attachment),
3518            Self::Depth32Float =>         (        msaa, attachment),
3519            Self::Depth32FloatStencil8 => (        msaa, attachment),
3520
3521            // We only support sampling nv12 textures until we implement transfer plane data.
3522            Self::NV12 =>                 (        none,    binding),
3523
3524            Self::R16Unorm =>             (        msaa | s_ro_wo,    storage),
3525            Self::R16Snorm =>             (        msaa | s_ro_wo,    storage),
3526            Self::Rg16Unorm =>            (        msaa | s_ro_wo,    storage),
3527            Self::Rg16Snorm =>            (        msaa | s_ro_wo,    storage),
3528            Self::Rgba16Unorm =>          (        msaa | s_ro_wo,    storage),
3529            Self::Rgba16Snorm =>          (        msaa | s_ro_wo,    storage),
3530
3531            Self::Rgb9e5Ufloat =>         (        none,      basic),
3532
3533            Self::Bc1RgbaUnorm =>         (        none,      basic),
3534            Self::Bc1RgbaUnormSrgb =>     (        none,      basic),
3535            Self::Bc2RgbaUnorm =>         (        none,      basic),
3536            Self::Bc2RgbaUnormSrgb =>     (        none,      basic),
3537            Self::Bc3RgbaUnorm =>         (        none,      basic),
3538            Self::Bc3RgbaUnormSrgb =>     (        none,      basic),
3539            Self::Bc4RUnorm =>            (        none,      basic),
3540            Self::Bc4RSnorm =>            (        none,      basic),
3541            Self::Bc5RgUnorm =>           (        none,      basic),
3542            Self::Bc5RgSnorm =>           (        none,      basic),
3543            Self::Bc6hRgbUfloat =>        (        none,      basic),
3544            Self::Bc6hRgbFloat =>         (        none,      basic),
3545            Self::Bc7RgbaUnorm =>         (        none,      basic),
3546            Self::Bc7RgbaUnormSrgb =>     (        none,      basic),
3547
3548            Self::Etc2Rgb8Unorm =>        (        none,      basic),
3549            Self::Etc2Rgb8UnormSrgb =>    (        none,      basic),
3550            Self::Etc2Rgb8A1Unorm =>      (        none,      basic),
3551            Self::Etc2Rgb8A1UnormSrgb =>  (        none,      basic),
3552            Self::Etc2Rgba8Unorm =>       (        none,      basic),
3553            Self::Etc2Rgba8UnormSrgb =>   (        none,      basic),
3554            Self::EacR11Unorm =>          (        none,      basic),
3555            Self::EacR11Snorm =>          (        none,      basic),
3556            Self::EacRg11Unorm =>         (        none,      basic),
3557            Self::EacRg11Snorm =>         (        none,      basic),
3558
3559            Self::Astc { .. } =>          (        none,      basic),
3560        };
3561
3562        // Get whether the format is filterable, taking features into account
3563        let sample_type1 = self.sample_type(None, Some(device_features));
3564        let is_filterable = sample_type1 == Some(TextureSampleType::Float { filterable: true });
3565
3566        // Features that enable filtering don't affect blendability
3567        let sample_type2 = self.sample_type(None, None);
3568        let is_blendable = sample_type2 == Some(TextureSampleType::Float { filterable: true });
3569
3570        flags.set(TextureFormatFeatureFlags::FILTERABLE, is_filterable);
3571        flags.set(TextureFormatFeatureFlags::BLENDABLE, is_blendable);
3572        flags.set(
3573            TextureFormatFeatureFlags::STORAGE_ATOMIC,
3574            allowed_usages.contains(TextureUsages::STORAGE_ATOMIC),
3575        );
3576
3577        TextureFormatFeatures {
3578            allowed_usages,
3579            flags,
3580        }
3581    }
3582
3583    /// Returns the sample type compatible with this format and aspect.
3584    ///
3585    /// Returns `None` only if this is a combined depth-stencil format or a multi-planar format
3586    /// and `TextureAspect::All` or no `aspect` was provided.
3587    #[must_use]
3588    pub fn sample_type(
3589        &self,
3590        aspect: Option<TextureAspect>,
3591        device_features: Option<Features>,
3592    ) -> Option<TextureSampleType> {
3593        let float = TextureSampleType::Float { filterable: true };
3594        let unfilterable_float = TextureSampleType::Float { filterable: false };
3595        let float32_sample_type = TextureSampleType::Float {
3596            filterable: device_features
3597                .unwrap_or(Features::empty())
3598                .contains(Features::FLOAT32_FILTERABLE),
3599        };
3600        let depth = TextureSampleType::Depth;
3601        let uint = TextureSampleType::Uint;
3602        let sint = TextureSampleType::Sint;
3603
3604        match *self {
3605            Self::R8Unorm
3606            | Self::R8Snorm
3607            | Self::Rg8Unorm
3608            | Self::Rg8Snorm
3609            | Self::Rgba8Unorm
3610            | Self::Rgba8UnormSrgb
3611            | Self::Rgba8Snorm
3612            | Self::Bgra8Unorm
3613            | Self::Bgra8UnormSrgb
3614            | Self::R16Float
3615            | Self::Rg16Float
3616            | Self::Rgba16Float
3617            | Self::Rgb10a2Unorm
3618            | Self::Rg11b10Ufloat => Some(float),
3619
3620            Self::R32Float | Self::Rg32Float | Self::Rgba32Float => Some(float32_sample_type),
3621
3622            Self::R8Uint
3623            | Self::Rg8Uint
3624            | Self::Rgba8Uint
3625            | Self::R16Uint
3626            | Self::Rg16Uint
3627            | Self::Rgba16Uint
3628            | Self::R32Uint
3629            | Self::R64Uint
3630            | Self::Rg32Uint
3631            | Self::Rgba32Uint
3632            | Self::Rgb10a2Uint => Some(uint),
3633
3634            Self::R8Sint
3635            | Self::Rg8Sint
3636            | Self::Rgba8Sint
3637            | Self::R16Sint
3638            | Self::Rg16Sint
3639            | Self::Rgba16Sint
3640            | Self::R32Sint
3641            | Self::Rg32Sint
3642            | Self::Rgba32Sint => Some(sint),
3643
3644            Self::Stencil8 => Some(uint),
3645            Self::Depth16Unorm | Self::Depth24Plus | Self::Depth32Float => Some(depth),
3646            Self::Depth24PlusStencil8 | Self::Depth32FloatStencil8 => match aspect {
3647                Some(TextureAspect::DepthOnly) => Some(depth),
3648                Some(TextureAspect::StencilOnly) => Some(uint),
3649                _ => None,
3650            },
3651
3652            Self::NV12 => match aspect {
3653                Some(TextureAspect::Plane0) | Some(TextureAspect::Plane1) => {
3654                    Some(unfilterable_float)
3655                }
3656                _ => None,
3657            },
3658
3659            Self::R16Unorm
3660            | Self::R16Snorm
3661            | Self::Rg16Unorm
3662            | Self::Rg16Snorm
3663            | Self::Rgba16Unorm
3664            | Self::Rgba16Snorm => Some(float),
3665
3666            Self::Rgb9e5Ufloat => Some(float),
3667
3668            Self::Bc1RgbaUnorm
3669            | Self::Bc1RgbaUnormSrgb
3670            | Self::Bc2RgbaUnorm
3671            | Self::Bc2RgbaUnormSrgb
3672            | Self::Bc3RgbaUnorm
3673            | Self::Bc3RgbaUnormSrgb
3674            | Self::Bc4RUnorm
3675            | Self::Bc4RSnorm
3676            | Self::Bc5RgUnorm
3677            | Self::Bc5RgSnorm
3678            | Self::Bc6hRgbUfloat
3679            | Self::Bc6hRgbFloat
3680            | Self::Bc7RgbaUnorm
3681            | Self::Bc7RgbaUnormSrgb => Some(float),
3682
3683            Self::Etc2Rgb8Unorm
3684            | Self::Etc2Rgb8UnormSrgb
3685            | Self::Etc2Rgb8A1Unorm
3686            | Self::Etc2Rgb8A1UnormSrgb
3687            | Self::Etc2Rgba8Unorm
3688            | Self::Etc2Rgba8UnormSrgb
3689            | Self::EacR11Unorm
3690            | Self::EacR11Snorm
3691            | Self::EacRg11Unorm
3692            | Self::EacRg11Snorm => Some(float),
3693
3694            Self::Astc { .. } => Some(float),
3695        }
3696    }
3697
3698    /// The number of bytes one [texel block](https://gpuweb.github.io/gpuweb/#texel-block) occupies during an image copy, if applicable.
3699    ///
3700    /// Known as the [texel block copy footprint](https://gpuweb.github.io/gpuweb/#texel-block-copy-footprint).
3701    ///
3702    /// Note that for uncompressed formats this is the same as the size of a single texel,
3703    /// since uncompressed formats have a block size of 1x1.
3704    ///
3705    /// Returns `None` if any of the following are true:
3706    ///  - the format is a combined depth-stencil and no `aspect` was provided
3707    ///  - the format is a multi-planar format and no `aspect` was provided
3708    ///  - the format is `Depth24Plus`
3709    ///  - the format is `Depth24PlusStencil8` and `aspect` is depth.
3710    #[deprecated(since = "0.19.0", note = "Use `block_copy_size` instead.")]
3711    #[must_use]
3712    pub fn block_size(&self, aspect: Option<TextureAspect>) -> Option<u32> {
3713        self.block_copy_size(aspect)
3714    }
3715
3716    /// The number of bytes one [texel block](https://gpuweb.github.io/gpuweb/#texel-block) occupies during an image copy, if applicable.
3717    ///
3718    /// Known as the [texel block copy footprint](https://gpuweb.github.io/gpuweb/#texel-block-copy-footprint).
3719    ///
3720    /// Note that for uncompressed formats this is the same as the size of a single texel,
3721    /// since uncompressed formats have a block size of 1x1.
3722    ///
3723    /// Returns `None` if any of the following are true:
3724    ///  - the format is a combined depth-stencil and no `aspect` was provided
3725    ///  - the format is a multi-planar format and no `aspect` was provided
3726    ///  - the format is `Depth24Plus`
3727    ///  - the format is `Depth24PlusStencil8` and `aspect` is depth.
3728    #[must_use]
3729    pub fn block_copy_size(&self, aspect: Option<TextureAspect>) -> Option<u32> {
3730        match *self {
3731            Self::R8Unorm | Self::R8Snorm | Self::R8Uint | Self::R8Sint => Some(1),
3732
3733            Self::Rg8Unorm | Self::Rg8Snorm | Self::Rg8Uint | Self::Rg8Sint => Some(2),
3734            Self::R16Unorm | Self::R16Snorm | Self::R16Uint | Self::R16Sint | Self::R16Float => {
3735                Some(2)
3736            }
3737
3738            Self::Rgba8Unorm
3739            | Self::Rgba8UnormSrgb
3740            | Self::Rgba8Snorm
3741            | Self::Rgba8Uint
3742            | Self::Rgba8Sint
3743            | Self::Bgra8Unorm
3744            | Self::Bgra8UnormSrgb => Some(4),
3745            Self::Rg16Unorm
3746            | Self::Rg16Snorm
3747            | Self::Rg16Uint
3748            | Self::Rg16Sint
3749            | Self::Rg16Float => Some(4),
3750            Self::R32Uint | Self::R32Sint | Self::R32Float => Some(4),
3751            Self::Rgb9e5Ufloat | Self::Rgb10a2Uint | Self::Rgb10a2Unorm | Self::Rg11b10Ufloat => {
3752                Some(4)
3753            }
3754
3755            Self::Rgba16Unorm
3756            | Self::Rgba16Snorm
3757            | Self::Rgba16Uint
3758            | Self::Rgba16Sint
3759            | Self::Rgba16Float => Some(8),
3760            Self::R64Uint | Self::Rg32Uint | Self::Rg32Sint | Self::Rg32Float => Some(8),
3761
3762            Self::Rgba32Uint | Self::Rgba32Sint | Self::Rgba32Float => Some(16),
3763
3764            Self::Stencil8 => Some(1),
3765            Self::Depth16Unorm => Some(2),
3766            Self::Depth32Float => Some(4),
3767            Self::Depth24Plus => None,
3768            Self::Depth24PlusStencil8 => match aspect {
3769                Some(TextureAspect::DepthOnly) => None,
3770                Some(TextureAspect::StencilOnly) => Some(1),
3771                _ => None,
3772            },
3773            Self::Depth32FloatStencil8 => match aspect {
3774                Some(TextureAspect::DepthOnly) => Some(4),
3775                Some(TextureAspect::StencilOnly) => Some(1),
3776                _ => None,
3777            },
3778
3779            Self::NV12 => match aspect {
3780                Some(TextureAspect::Plane0) => Some(1),
3781                Some(TextureAspect::Plane1) => Some(2),
3782                _ => None,
3783            },
3784
3785            Self::Bc1RgbaUnorm | Self::Bc1RgbaUnormSrgb | Self::Bc4RUnorm | Self::Bc4RSnorm => {
3786                Some(8)
3787            }
3788            Self::Bc2RgbaUnorm
3789            | Self::Bc2RgbaUnormSrgb
3790            | Self::Bc3RgbaUnorm
3791            | Self::Bc3RgbaUnormSrgb
3792            | Self::Bc5RgUnorm
3793            | Self::Bc5RgSnorm
3794            | Self::Bc6hRgbUfloat
3795            | Self::Bc6hRgbFloat
3796            | Self::Bc7RgbaUnorm
3797            | Self::Bc7RgbaUnormSrgb => Some(16),
3798
3799            Self::Etc2Rgb8Unorm
3800            | Self::Etc2Rgb8UnormSrgb
3801            | Self::Etc2Rgb8A1Unorm
3802            | Self::Etc2Rgb8A1UnormSrgb
3803            | Self::EacR11Unorm
3804            | Self::EacR11Snorm => Some(8),
3805            Self::Etc2Rgba8Unorm
3806            | Self::Etc2Rgba8UnormSrgb
3807            | Self::EacRg11Unorm
3808            | Self::EacRg11Snorm => Some(16),
3809
3810            Self::Astc { .. } => Some(16),
3811        }
3812    }
3813
3814    /// The largest number that can be returned by [`Self::target_pixel_byte_cost`].
3815    pub const MAX_TARGET_PIXEL_BYTE_COST: u32 = 16;
3816
3817    /// The number of bytes occupied per pixel in a color attachment
3818    /// <https://gpuweb.github.io/gpuweb/#render-target-pixel-byte-cost>
3819    #[must_use]
3820    pub fn target_pixel_byte_cost(&self) -> Option<u32> {
3821        match *self {
3822            Self::R8Unorm | Self::R8Snorm | Self::R8Uint | Self::R8Sint => Some(1),
3823            Self::Rg8Unorm
3824            | Self::Rg8Snorm
3825            | Self::Rg8Uint
3826            | Self::Rg8Sint
3827            | Self::R16Uint
3828            | Self::R16Sint
3829            | Self::R16Unorm
3830            | Self::R16Snorm
3831            | Self::R16Float => Some(2),
3832            Self::Rgba8Uint
3833            | Self::Rgba8Sint
3834            | Self::Rg16Uint
3835            | Self::Rg16Sint
3836            | Self::Rg16Unorm
3837            | Self::Rg16Snorm
3838            | Self::Rg16Float
3839            | Self::R32Uint
3840            | Self::R32Sint
3841            | Self::R32Float => Some(4),
3842            // Despite being 4 bytes per pixel, these are 8 bytes per pixel in the table
3843            Self::Rgba8Unorm
3844            | Self::Rgba8UnormSrgb
3845            | Self::Rgba8Snorm
3846            | Self::Bgra8Unorm
3847            | Self::Bgra8UnormSrgb
3848            // ---
3849            | Self::Rgba16Uint
3850            | Self::Rgba16Sint
3851            | Self::Rgba16Unorm
3852            | Self::Rgba16Snorm
3853            | Self::Rgba16Float
3854            | Self::R64Uint
3855            | Self::Rg32Uint
3856            | Self::Rg32Sint
3857            | Self::Rg32Float
3858            | Self::Rgb10a2Uint
3859            | Self::Rgb10a2Unorm
3860            | Self::Rg11b10Ufloat => Some(8),
3861            Self::Rgba32Uint | Self::Rgba32Sint | Self::Rgba32Float => Some(16),
3862            // ⚠️ If you add formats with larger sizes, make sure you change `MAX_TARGET_PIXEL_BYTE_COST`` ⚠️
3863            Self::Stencil8
3864            | Self::Depth16Unorm
3865            | Self::Depth24Plus
3866            | Self::Depth24PlusStencil8
3867            | Self::Depth32Float
3868            | Self::Depth32FloatStencil8
3869            | Self::NV12
3870            | Self::Rgb9e5Ufloat
3871            | Self::Bc1RgbaUnorm
3872            | Self::Bc1RgbaUnormSrgb
3873            | Self::Bc2RgbaUnorm
3874            | Self::Bc2RgbaUnormSrgb
3875            | Self::Bc3RgbaUnorm
3876            | Self::Bc3RgbaUnormSrgb
3877            | Self::Bc4RUnorm
3878            | Self::Bc4RSnorm
3879            | Self::Bc5RgUnorm
3880            | Self::Bc5RgSnorm
3881            | Self::Bc6hRgbUfloat
3882            | Self::Bc6hRgbFloat
3883            | Self::Bc7RgbaUnorm
3884            | Self::Bc7RgbaUnormSrgb
3885            | Self::Etc2Rgb8Unorm
3886            | Self::Etc2Rgb8UnormSrgb
3887            | Self::Etc2Rgb8A1Unorm
3888            | Self::Etc2Rgb8A1UnormSrgb
3889            | Self::Etc2Rgba8Unorm
3890            | Self::Etc2Rgba8UnormSrgb
3891            | Self::EacR11Unorm
3892            | Self::EacR11Snorm
3893            | Self::EacRg11Unorm
3894            | Self::EacRg11Snorm
3895            | Self::Astc { .. } => None,
3896        }
3897    }
3898
3899    /// See <https://gpuweb.github.io/gpuweb/#render-target-component-alignment>
3900    #[must_use]
3901    pub fn target_component_alignment(&self) -> Option<u32> {
3902        match *self {
3903            Self::R8Unorm
3904            | Self::R8Snorm
3905            | Self::R8Uint
3906            | Self::R8Sint
3907            | Self::Rg8Unorm
3908            | Self::Rg8Snorm
3909            | Self::Rg8Uint
3910            | Self::Rg8Sint
3911            | Self::Rgba8Unorm
3912            | Self::Rgba8UnormSrgb
3913            | Self::Rgba8Snorm
3914            | Self::Rgba8Uint
3915            | Self::Rgba8Sint
3916            | Self::Bgra8Unorm
3917            | Self::Bgra8UnormSrgb => Some(1),
3918            Self::R16Uint
3919            | Self::R16Sint
3920            | Self::R16Unorm
3921            | Self::R16Snorm
3922            | Self::R16Float
3923            | Self::Rg16Uint
3924            | Self::Rg16Sint
3925            | Self::Rg16Unorm
3926            | Self::Rg16Snorm
3927            | Self::Rg16Float
3928            | Self::Rgba16Uint
3929            | Self::Rgba16Sint
3930            | Self::Rgba16Unorm
3931            | Self::Rgba16Snorm
3932            | Self::Rgba16Float => Some(2),
3933            Self::R32Uint
3934            | Self::R32Sint
3935            | Self::R32Float
3936            | Self::R64Uint
3937            | Self::Rg32Uint
3938            | Self::Rg32Sint
3939            | Self::Rg32Float
3940            | Self::Rgba32Uint
3941            | Self::Rgba32Sint
3942            | Self::Rgba32Float
3943            | Self::Rgb10a2Uint
3944            | Self::Rgb10a2Unorm
3945            | Self::Rg11b10Ufloat => Some(4),
3946            Self::Stencil8
3947            | Self::Depth16Unorm
3948            | Self::Depth24Plus
3949            | Self::Depth24PlusStencil8
3950            | Self::Depth32Float
3951            | Self::Depth32FloatStencil8
3952            | Self::NV12
3953            | Self::Rgb9e5Ufloat
3954            | Self::Bc1RgbaUnorm
3955            | Self::Bc1RgbaUnormSrgb
3956            | Self::Bc2RgbaUnorm
3957            | Self::Bc2RgbaUnormSrgb
3958            | Self::Bc3RgbaUnorm
3959            | Self::Bc3RgbaUnormSrgb
3960            | Self::Bc4RUnorm
3961            | Self::Bc4RSnorm
3962            | Self::Bc5RgUnorm
3963            | Self::Bc5RgSnorm
3964            | Self::Bc6hRgbUfloat
3965            | Self::Bc6hRgbFloat
3966            | Self::Bc7RgbaUnorm
3967            | Self::Bc7RgbaUnormSrgb
3968            | Self::Etc2Rgb8Unorm
3969            | Self::Etc2Rgb8UnormSrgb
3970            | Self::Etc2Rgb8A1Unorm
3971            | Self::Etc2Rgb8A1UnormSrgb
3972            | Self::Etc2Rgba8Unorm
3973            | Self::Etc2Rgba8UnormSrgb
3974            | Self::EacR11Unorm
3975            | Self::EacR11Snorm
3976            | Self::EacRg11Unorm
3977            | Self::EacRg11Snorm
3978            | Self::Astc { .. } => None,
3979        }
3980    }
3981
3982    /// Returns the number of components this format has.
3983    #[must_use]
3984    pub fn components(&self) -> u8 {
3985        self.components_with_aspect(TextureAspect::All)
3986    }
3987
3988    /// Returns the number of components this format has taking into account the `aspect`.
3989    ///
3990    /// The `aspect` is only relevant for combined depth-stencil formats and multi-planar formats.
3991    #[must_use]
3992    pub fn components_with_aspect(&self, aspect: TextureAspect) -> u8 {
3993        match *self {
3994            Self::R8Unorm
3995            | Self::R8Snorm
3996            | Self::R8Uint
3997            | Self::R8Sint
3998            | Self::R16Unorm
3999            | Self::R16Snorm
4000            | Self::R16Uint
4001            | Self::R16Sint
4002            | Self::R16Float
4003            | Self::R32Uint
4004            | Self::R32Sint
4005            | Self::R32Float
4006            | Self::R64Uint => 1,
4007
4008            Self::Rg8Unorm
4009            | Self::Rg8Snorm
4010            | Self::Rg8Uint
4011            | Self::Rg8Sint
4012            | Self::Rg16Unorm
4013            | Self::Rg16Snorm
4014            | Self::Rg16Uint
4015            | Self::Rg16Sint
4016            | Self::Rg16Float
4017            | Self::Rg32Uint
4018            | Self::Rg32Sint
4019            | Self::Rg32Float => 2,
4020
4021            Self::Rgba8Unorm
4022            | Self::Rgba8UnormSrgb
4023            | Self::Rgba8Snorm
4024            | Self::Rgba8Uint
4025            | Self::Rgba8Sint
4026            | Self::Bgra8Unorm
4027            | Self::Bgra8UnormSrgb
4028            | Self::Rgba16Unorm
4029            | Self::Rgba16Snorm
4030            | Self::Rgba16Uint
4031            | Self::Rgba16Sint
4032            | Self::Rgba16Float
4033            | Self::Rgba32Uint
4034            | Self::Rgba32Sint
4035            | Self::Rgba32Float => 4,
4036
4037            Self::Rgb9e5Ufloat | Self::Rg11b10Ufloat => 3,
4038            Self::Rgb10a2Uint | Self::Rgb10a2Unorm => 4,
4039
4040            Self::Stencil8 | Self::Depth16Unorm | Self::Depth24Plus | Self::Depth32Float => 1,
4041
4042            Self::Depth24PlusStencil8 | Self::Depth32FloatStencil8 => match aspect {
4043                TextureAspect::DepthOnly | TextureAspect::StencilOnly => 1,
4044                _ => 2,
4045            },
4046
4047            Self::NV12 => match aspect {
4048                TextureAspect::Plane0 => 1,
4049                TextureAspect::Plane1 => 2,
4050                _ => 3,
4051            },
4052
4053            Self::Bc4RUnorm | Self::Bc4RSnorm => 1,
4054            Self::Bc5RgUnorm | Self::Bc5RgSnorm => 2,
4055            Self::Bc6hRgbUfloat | Self::Bc6hRgbFloat => 3,
4056            Self::Bc1RgbaUnorm
4057            | Self::Bc1RgbaUnormSrgb
4058            | Self::Bc2RgbaUnorm
4059            | Self::Bc2RgbaUnormSrgb
4060            | Self::Bc3RgbaUnorm
4061            | Self::Bc3RgbaUnormSrgb
4062            | Self::Bc7RgbaUnorm
4063            | Self::Bc7RgbaUnormSrgb => 4,
4064
4065            Self::EacR11Unorm | Self::EacR11Snorm => 1,
4066            Self::EacRg11Unorm | Self::EacRg11Snorm => 2,
4067            Self::Etc2Rgb8Unorm | Self::Etc2Rgb8UnormSrgb => 3,
4068            Self::Etc2Rgb8A1Unorm
4069            | Self::Etc2Rgb8A1UnormSrgb
4070            | Self::Etc2Rgba8Unorm
4071            | Self::Etc2Rgba8UnormSrgb => 4,
4072
4073            Self::Astc { .. } => 4,
4074        }
4075    }
4076
4077    /// Strips the `Srgb` suffix from the given texture format.
4078    #[must_use]
4079    pub fn remove_srgb_suffix(&self) -> TextureFormat {
4080        match *self {
4081            Self::Rgba8UnormSrgb => Self::Rgba8Unorm,
4082            Self::Bgra8UnormSrgb => Self::Bgra8Unorm,
4083            Self::Bc1RgbaUnormSrgb => Self::Bc1RgbaUnorm,
4084            Self::Bc2RgbaUnormSrgb => Self::Bc2RgbaUnorm,
4085            Self::Bc3RgbaUnormSrgb => Self::Bc3RgbaUnorm,
4086            Self::Bc7RgbaUnormSrgb => Self::Bc7RgbaUnorm,
4087            Self::Etc2Rgb8UnormSrgb => Self::Etc2Rgb8Unorm,
4088            Self::Etc2Rgb8A1UnormSrgb => Self::Etc2Rgb8A1Unorm,
4089            Self::Etc2Rgba8UnormSrgb => Self::Etc2Rgba8Unorm,
4090            Self::Astc {
4091                block,
4092                channel: AstcChannel::UnormSrgb,
4093            } => Self::Astc {
4094                block,
4095                channel: AstcChannel::Unorm,
4096            },
4097            _ => *self,
4098        }
4099    }
4100
4101    /// Adds an `Srgb` suffix to the given texture format, if the format supports it.
4102    #[must_use]
4103    pub fn add_srgb_suffix(&self) -> TextureFormat {
4104        match *self {
4105            Self::Rgba8Unorm => Self::Rgba8UnormSrgb,
4106            Self::Bgra8Unorm => Self::Bgra8UnormSrgb,
4107            Self::Bc1RgbaUnorm => Self::Bc1RgbaUnormSrgb,
4108            Self::Bc2RgbaUnorm => Self::Bc2RgbaUnormSrgb,
4109            Self::Bc3RgbaUnorm => Self::Bc3RgbaUnormSrgb,
4110            Self::Bc7RgbaUnorm => Self::Bc7RgbaUnormSrgb,
4111            Self::Etc2Rgb8Unorm => Self::Etc2Rgb8UnormSrgb,
4112            Self::Etc2Rgb8A1Unorm => Self::Etc2Rgb8A1UnormSrgb,
4113            Self::Etc2Rgba8Unorm => Self::Etc2Rgba8UnormSrgb,
4114            Self::Astc {
4115                block,
4116                channel: AstcChannel::Unorm,
4117            } => Self::Astc {
4118                block,
4119                channel: AstcChannel::UnormSrgb,
4120            },
4121            _ => *self,
4122        }
4123    }
4124
4125    /// Returns `true` for srgb formats.
4126    #[must_use]
4127    pub fn is_srgb(&self) -> bool {
4128        *self != self.remove_srgb_suffix()
4129    }
4130}
4131
4132#[test]
4133fn texture_format_serialize() {
4134    use alloc::string::ToString;
4135
4136    assert_eq!(
4137        serde_json::to_string(&TextureFormat::R8Unorm).unwrap(),
4138        "\"r8unorm\"".to_string()
4139    );
4140    assert_eq!(
4141        serde_json::to_string(&TextureFormat::R8Snorm).unwrap(),
4142        "\"r8snorm\"".to_string()
4143    );
4144    assert_eq!(
4145        serde_json::to_string(&TextureFormat::R8Uint).unwrap(),
4146        "\"r8uint\"".to_string()
4147    );
4148    assert_eq!(
4149        serde_json::to_string(&TextureFormat::R8Sint).unwrap(),
4150        "\"r8sint\"".to_string()
4151    );
4152    assert_eq!(
4153        serde_json::to_string(&TextureFormat::R16Uint).unwrap(),
4154        "\"r16uint\"".to_string()
4155    );
4156    assert_eq!(
4157        serde_json::to_string(&TextureFormat::R16Sint).unwrap(),
4158        "\"r16sint\"".to_string()
4159    );
4160    assert_eq!(
4161        serde_json::to_string(&TextureFormat::R16Unorm).unwrap(),
4162        "\"r16unorm\"".to_string()
4163    );
4164    assert_eq!(
4165        serde_json::to_string(&TextureFormat::R16Snorm).unwrap(),
4166        "\"r16snorm\"".to_string()
4167    );
4168    assert_eq!(
4169        serde_json::to_string(&TextureFormat::R16Float).unwrap(),
4170        "\"r16float\"".to_string()
4171    );
4172    assert_eq!(
4173        serde_json::to_string(&TextureFormat::Rg8Unorm).unwrap(),
4174        "\"rg8unorm\"".to_string()
4175    );
4176    assert_eq!(
4177        serde_json::to_string(&TextureFormat::Rg8Snorm).unwrap(),
4178        "\"rg8snorm\"".to_string()
4179    );
4180    assert_eq!(
4181        serde_json::to_string(&TextureFormat::Rg8Uint).unwrap(),
4182        "\"rg8uint\"".to_string()
4183    );
4184    assert_eq!(
4185        serde_json::to_string(&TextureFormat::Rg8Sint).unwrap(),
4186        "\"rg8sint\"".to_string()
4187    );
4188    assert_eq!(
4189        serde_json::to_string(&TextureFormat::R32Uint).unwrap(),
4190        "\"r32uint\"".to_string()
4191    );
4192    assert_eq!(
4193        serde_json::to_string(&TextureFormat::R32Sint).unwrap(),
4194        "\"r32sint\"".to_string()
4195    );
4196    assert_eq!(
4197        serde_json::to_string(&TextureFormat::R32Float).unwrap(),
4198        "\"r32float\"".to_string()
4199    );
4200    assert_eq!(
4201        serde_json::to_string(&TextureFormat::Rg16Uint).unwrap(),
4202        "\"rg16uint\"".to_string()
4203    );
4204    assert_eq!(
4205        serde_json::to_string(&TextureFormat::Rg16Sint).unwrap(),
4206        "\"rg16sint\"".to_string()
4207    );
4208    assert_eq!(
4209        serde_json::to_string(&TextureFormat::Rg16Unorm).unwrap(),
4210        "\"rg16unorm\"".to_string()
4211    );
4212    assert_eq!(
4213        serde_json::to_string(&TextureFormat::Rg16Snorm).unwrap(),
4214        "\"rg16snorm\"".to_string()
4215    );
4216    assert_eq!(
4217        serde_json::to_string(&TextureFormat::Rg16Float).unwrap(),
4218        "\"rg16float\"".to_string()
4219    );
4220    assert_eq!(
4221        serde_json::to_string(&TextureFormat::Rgba8Unorm).unwrap(),
4222        "\"rgba8unorm\"".to_string()
4223    );
4224    assert_eq!(
4225        serde_json::to_string(&TextureFormat::Rgba8UnormSrgb).unwrap(),
4226        "\"rgba8unorm-srgb\"".to_string()
4227    );
4228    assert_eq!(
4229        serde_json::to_string(&TextureFormat::Rgba8Snorm).unwrap(),
4230        "\"rgba8snorm\"".to_string()
4231    );
4232    assert_eq!(
4233        serde_json::to_string(&TextureFormat::Rgba8Uint).unwrap(),
4234        "\"rgba8uint\"".to_string()
4235    );
4236    assert_eq!(
4237        serde_json::to_string(&TextureFormat::Rgba8Sint).unwrap(),
4238        "\"rgba8sint\"".to_string()
4239    );
4240    assert_eq!(
4241        serde_json::to_string(&TextureFormat::Bgra8Unorm).unwrap(),
4242        "\"bgra8unorm\"".to_string()
4243    );
4244    assert_eq!(
4245        serde_json::to_string(&TextureFormat::Bgra8UnormSrgb).unwrap(),
4246        "\"bgra8unorm-srgb\"".to_string()
4247    );
4248    assert_eq!(
4249        serde_json::to_string(&TextureFormat::Rgb10a2Uint).unwrap(),
4250        "\"rgb10a2uint\"".to_string()
4251    );
4252    assert_eq!(
4253        serde_json::to_string(&TextureFormat::Rgb10a2Unorm).unwrap(),
4254        "\"rgb10a2unorm\"".to_string()
4255    );
4256    assert_eq!(
4257        serde_json::to_string(&TextureFormat::Rg11b10Ufloat).unwrap(),
4258        "\"rg11b10ufloat\"".to_string()
4259    );
4260    assert_eq!(
4261        serde_json::to_string(&TextureFormat::R64Uint).unwrap(),
4262        "\"r64uint\"".to_string()
4263    );
4264    assert_eq!(
4265        serde_json::to_string(&TextureFormat::Rg32Uint).unwrap(),
4266        "\"rg32uint\"".to_string()
4267    );
4268    assert_eq!(
4269        serde_json::to_string(&TextureFormat::Rg32Sint).unwrap(),
4270        "\"rg32sint\"".to_string()
4271    );
4272    assert_eq!(
4273        serde_json::to_string(&TextureFormat::Rg32Float).unwrap(),
4274        "\"rg32float\"".to_string()
4275    );
4276    assert_eq!(
4277        serde_json::to_string(&TextureFormat::Rgba16Uint).unwrap(),
4278        "\"rgba16uint\"".to_string()
4279    );
4280    assert_eq!(
4281        serde_json::to_string(&TextureFormat::Rgba16Sint).unwrap(),
4282        "\"rgba16sint\"".to_string()
4283    );
4284    assert_eq!(
4285        serde_json::to_string(&TextureFormat::Rgba16Unorm).unwrap(),
4286        "\"rgba16unorm\"".to_string()
4287    );
4288    assert_eq!(
4289        serde_json::to_string(&TextureFormat::Rgba16Snorm).unwrap(),
4290        "\"rgba16snorm\"".to_string()
4291    );
4292    assert_eq!(
4293        serde_json::to_string(&TextureFormat::Rgba16Float).unwrap(),
4294        "\"rgba16float\"".to_string()
4295    );
4296    assert_eq!(
4297        serde_json::to_string(&TextureFormat::Rgba32Uint).unwrap(),
4298        "\"rgba32uint\"".to_string()
4299    );
4300    assert_eq!(
4301        serde_json::to_string(&TextureFormat::Rgba32Sint).unwrap(),
4302        "\"rgba32sint\"".to_string()
4303    );
4304    assert_eq!(
4305        serde_json::to_string(&TextureFormat::Rgba32Float).unwrap(),
4306        "\"rgba32float\"".to_string()
4307    );
4308    assert_eq!(
4309        serde_json::to_string(&TextureFormat::Stencil8).unwrap(),
4310        "\"stencil8\"".to_string()
4311    );
4312    assert_eq!(
4313        serde_json::to_string(&TextureFormat::Depth32Float).unwrap(),
4314        "\"depth32float\"".to_string()
4315    );
4316    assert_eq!(
4317        serde_json::to_string(&TextureFormat::Depth16Unorm).unwrap(),
4318        "\"depth16unorm\"".to_string()
4319    );
4320    assert_eq!(
4321        serde_json::to_string(&TextureFormat::Depth32FloatStencil8).unwrap(),
4322        "\"depth32float-stencil8\"".to_string()
4323    );
4324    assert_eq!(
4325        serde_json::to_string(&TextureFormat::Depth24Plus).unwrap(),
4326        "\"depth24plus\"".to_string()
4327    );
4328    assert_eq!(
4329        serde_json::to_string(&TextureFormat::Depth24PlusStencil8).unwrap(),
4330        "\"depth24plus-stencil8\"".to_string()
4331    );
4332    assert_eq!(
4333        serde_json::to_string(&TextureFormat::Rgb9e5Ufloat).unwrap(),
4334        "\"rgb9e5ufloat\"".to_string()
4335    );
4336    assert_eq!(
4337        serde_json::to_string(&TextureFormat::Bc1RgbaUnorm).unwrap(),
4338        "\"bc1-rgba-unorm\"".to_string()
4339    );
4340    assert_eq!(
4341        serde_json::to_string(&TextureFormat::Bc1RgbaUnormSrgb).unwrap(),
4342        "\"bc1-rgba-unorm-srgb\"".to_string()
4343    );
4344    assert_eq!(
4345        serde_json::to_string(&TextureFormat::Bc2RgbaUnorm).unwrap(),
4346        "\"bc2-rgba-unorm\"".to_string()
4347    );
4348    assert_eq!(
4349        serde_json::to_string(&TextureFormat::Bc2RgbaUnormSrgb).unwrap(),
4350        "\"bc2-rgba-unorm-srgb\"".to_string()
4351    );
4352    assert_eq!(
4353        serde_json::to_string(&TextureFormat::Bc3RgbaUnorm).unwrap(),
4354        "\"bc3-rgba-unorm\"".to_string()
4355    );
4356    assert_eq!(
4357        serde_json::to_string(&TextureFormat::Bc3RgbaUnormSrgb).unwrap(),
4358        "\"bc3-rgba-unorm-srgb\"".to_string()
4359    );
4360    assert_eq!(
4361        serde_json::to_string(&TextureFormat::Bc4RUnorm).unwrap(),
4362        "\"bc4-r-unorm\"".to_string()
4363    );
4364    assert_eq!(
4365        serde_json::to_string(&TextureFormat::Bc4RSnorm).unwrap(),
4366        "\"bc4-r-snorm\"".to_string()
4367    );
4368    assert_eq!(
4369        serde_json::to_string(&TextureFormat::Bc5RgUnorm).unwrap(),
4370        "\"bc5-rg-unorm\"".to_string()
4371    );
4372    assert_eq!(
4373        serde_json::to_string(&TextureFormat::Bc5RgSnorm).unwrap(),
4374        "\"bc5-rg-snorm\"".to_string()
4375    );
4376    assert_eq!(
4377        serde_json::to_string(&TextureFormat::Bc6hRgbUfloat).unwrap(),
4378        "\"bc6h-rgb-ufloat\"".to_string()
4379    );
4380    assert_eq!(
4381        serde_json::to_string(&TextureFormat::Bc6hRgbFloat).unwrap(),
4382        "\"bc6h-rgb-float\"".to_string()
4383    );
4384    assert_eq!(
4385        serde_json::to_string(&TextureFormat::Bc7RgbaUnorm).unwrap(),
4386        "\"bc7-rgba-unorm\"".to_string()
4387    );
4388    assert_eq!(
4389        serde_json::to_string(&TextureFormat::Bc7RgbaUnormSrgb).unwrap(),
4390        "\"bc7-rgba-unorm-srgb\"".to_string()
4391    );
4392    assert_eq!(
4393        serde_json::to_string(&TextureFormat::Etc2Rgb8Unorm).unwrap(),
4394        "\"etc2-rgb8unorm\"".to_string()
4395    );
4396    assert_eq!(
4397        serde_json::to_string(&TextureFormat::Etc2Rgb8UnormSrgb).unwrap(),
4398        "\"etc2-rgb8unorm-srgb\"".to_string()
4399    );
4400    assert_eq!(
4401        serde_json::to_string(&TextureFormat::Etc2Rgb8A1Unorm).unwrap(),
4402        "\"etc2-rgb8a1unorm\"".to_string()
4403    );
4404    assert_eq!(
4405        serde_json::to_string(&TextureFormat::Etc2Rgb8A1UnormSrgb).unwrap(),
4406        "\"etc2-rgb8a1unorm-srgb\"".to_string()
4407    );
4408    assert_eq!(
4409        serde_json::to_string(&TextureFormat::Etc2Rgba8Unorm).unwrap(),
4410        "\"etc2-rgba8unorm\"".to_string()
4411    );
4412    assert_eq!(
4413        serde_json::to_string(&TextureFormat::Etc2Rgba8UnormSrgb).unwrap(),
4414        "\"etc2-rgba8unorm-srgb\"".to_string()
4415    );
4416    assert_eq!(
4417        serde_json::to_string(&TextureFormat::EacR11Unorm).unwrap(),
4418        "\"eac-r11unorm\"".to_string()
4419    );
4420    assert_eq!(
4421        serde_json::to_string(&TextureFormat::EacR11Snorm).unwrap(),
4422        "\"eac-r11snorm\"".to_string()
4423    );
4424    assert_eq!(
4425        serde_json::to_string(&TextureFormat::EacRg11Unorm).unwrap(),
4426        "\"eac-rg11unorm\"".to_string()
4427    );
4428    assert_eq!(
4429        serde_json::to_string(&TextureFormat::EacRg11Snorm).unwrap(),
4430        "\"eac-rg11snorm\"".to_string()
4431    );
4432}
4433
4434#[test]
4435fn texture_format_deserialize() {
4436    assert_eq!(
4437        serde_json::from_str::<TextureFormat>("\"r8unorm\"").unwrap(),
4438        TextureFormat::R8Unorm
4439    );
4440    assert_eq!(
4441        serde_json::from_str::<TextureFormat>("\"r8snorm\"").unwrap(),
4442        TextureFormat::R8Snorm
4443    );
4444    assert_eq!(
4445        serde_json::from_str::<TextureFormat>("\"r8uint\"").unwrap(),
4446        TextureFormat::R8Uint
4447    );
4448    assert_eq!(
4449        serde_json::from_str::<TextureFormat>("\"r8sint\"").unwrap(),
4450        TextureFormat::R8Sint
4451    );
4452    assert_eq!(
4453        serde_json::from_str::<TextureFormat>("\"r16uint\"").unwrap(),
4454        TextureFormat::R16Uint
4455    );
4456    assert_eq!(
4457        serde_json::from_str::<TextureFormat>("\"r16sint\"").unwrap(),
4458        TextureFormat::R16Sint
4459    );
4460    assert_eq!(
4461        serde_json::from_str::<TextureFormat>("\"r16unorm\"").unwrap(),
4462        TextureFormat::R16Unorm
4463    );
4464    assert_eq!(
4465        serde_json::from_str::<TextureFormat>("\"r16snorm\"").unwrap(),
4466        TextureFormat::R16Snorm
4467    );
4468    assert_eq!(
4469        serde_json::from_str::<TextureFormat>("\"r16float\"").unwrap(),
4470        TextureFormat::R16Float
4471    );
4472    assert_eq!(
4473        serde_json::from_str::<TextureFormat>("\"rg8unorm\"").unwrap(),
4474        TextureFormat::Rg8Unorm
4475    );
4476    assert_eq!(
4477        serde_json::from_str::<TextureFormat>("\"rg8snorm\"").unwrap(),
4478        TextureFormat::Rg8Snorm
4479    );
4480    assert_eq!(
4481        serde_json::from_str::<TextureFormat>("\"rg8uint\"").unwrap(),
4482        TextureFormat::Rg8Uint
4483    );
4484    assert_eq!(
4485        serde_json::from_str::<TextureFormat>("\"rg8sint\"").unwrap(),
4486        TextureFormat::Rg8Sint
4487    );
4488    assert_eq!(
4489        serde_json::from_str::<TextureFormat>("\"r32uint\"").unwrap(),
4490        TextureFormat::R32Uint
4491    );
4492    assert_eq!(
4493        serde_json::from_str::<TextureFormat>("\"r32sint\"").unwrap(),
4494        TextureFormat::R32Sint
4495    );
4496    assert_eq!(
4497        serde_json::from_str::<TextureFormat>("\"r32float\"").unwrap(),
4498        TextureFormat::R32Float
4499    );
4500    assert_eq!(
4501        serde_json::from_str::<TextureFormat>("\"rg16uint\"").unwrap(),
4502        TextureFormat::Rg16Uint
4503    );
4504    assert_eq!(
4505        serde_json::from_str::<TextureFormat>("\"rg16sint\"").unwrap(),
4506        TextureFormat::Rg16Sint
4507    );
4508    assert_eq!(
4509        serde_json::from_str::<TextureFormat>("\"rg16unorm\"").unwrap(),
4510        TextureFormat::Rg16Unorm
4511    );
4512    assert_eq!(
4513        serde_json::from_str::<TextureFormat>("\"rg16snorm\"").unwrap(),
4514        TextureFormat::Rg16Snorm
4515    );
4516    assert_eq!(
4517        serde_json::from_str::<TextureFormat>("\"rg16float\"").unwrap(),
4518        TextureFormat::Rg16Float
4519    );
4520    assert_eq!(
4521        serde_json::from_str::<TextureFormat>("\"rgba8unorm\"").unwrap(),
4522        TextureFormat::Rgba8Unorm
4523    );
4524    assert_eq!(
4525        serde_json::from_str::<TextureFormat>("\"rgba8unorm-srgb\"").unwrap(),
4526        TextureFormat::Rgba8UnormSrgb
4527    );
4528    assert_eq!(
4529        serde_json::from_str::<TextureFormat>("\"rgba8snorm\"").unwrap(),
4530        TextureFormat::Rgba8Snorm
4531    );
4532    assert_eq!(
4533        serde_json::from_str::<TextureFormat>("\"rgba8uint\"").unwrap(),
4534        TextureFormat::Rgba8Uint
4535    );
4536    assert_eq!(
4537        serde_json::from_str::<TextureFormat>("\"rgba8sint\"").unwrap(),
4538        TextureFormat::Rgba8Sint
4539    );
4540    assert_eq!(
4541        serde_json::from_str::<TextureFormat>("\"bgra8unorm\"").unwrap(),
4542        TextureFormat::Bgra8Unorm
4543    );
4544    assert_eq!(
4545        serde_json::from_str::<TextureFormat>("\"bgra8unorm-srgb\"").unwrap(),
4546        TextureFormat::Bgra8UnormSrgb
4547    );
4548    assert_eq!(
4549        serde_json::from_str::<TextureFormat>("\"rgb10a2uint\"").unwrap(),
4550        TextureFormat::Rgb10a2Uint
4551    );
4552    assert_eq!(
4553        serde_json::from_str::<TextureFormat>("\"rgb10a2unorm\"").unwrap(),
4554        TextureFormat::Rgb10a2Unorm
4555    );
4556    assert_eq!(
4557        serde_json::from_str::<TextureFormat>("\"rg11b10ufloat\"").unwrap(),
4558        TextureFormat::Rg11b10Ufloat
4559    );
4560    assert_eq!(
4561        serde_json::from_str::<TextureFormat>("\"r64uint\"").unwrap(),
4562        TextureFormat::R64Uint
4563    );
4564    assert_eq!(
4565        serde_json::from_str::<TextureFormat>("\"rg32uint\"").unwrap(),
4566        TextureFormat::Rg32Uint
4567    );
4568    assert_eq!(
4569        serde_json::from_str::<TextureFormat>("\"rg32sint\"").unwrap(),
4570        TextureFormat::Rg32Sint
4571    );
4572    assert_eq!(
4573        serde_json::from_str::<TextureFormat>("\"rg32float\"").unwrap(),
4574        TextureFormat::Rg32Float
4575    );
4576    assert_eq!(
4577        serde_json::from_str::<TextureFormat>("\"rgba16uint\"").unwrap(),
4578        TextureFormat::Rgba16Uint
4579    );
4580    assert_eq!(
4581        serde_json::from_str::<TextureFormat>("\"rgba16sint\"").unwrap(),
4582        TextureFormat::Rgba16Sint
4583    );
4584    assert_eq!(
4585        serde_json::from_str::<TextureFormat>("\"rgba16unorm\"").unwrap(),
4586        TextureFormat::Rgba16Unorm
4587    );
4588    assert_eq!(
4589        serde_json::from_str::<TextureFormat>("\"rgba16snorm\"").unwrap(),
4590        TextureFormat::Rgba16Snorm
4591    );
4592    assert_eq!(
4593        serde_json::from_str::<TextureFormat>("\"rgba16float\"").unwrap(),
4594        TextureFormat::Rgba16Float
4595    );
4596    assert_eq!(
4597        serde_json::from_str::<TextureFormat>("\"rgba32uint\"").unwrap(),
4598        TextureFormat::Rgba32Uint
4599    );
4600    assert_eq!(
4601        serde_json::from_str::<TextureFormat>("\"rgba32sint\"").unwrap(),
4602        TextureFormat::Rgba32Sint
4603    );
4604    assert_eq!(
4605        serde_json::from_str::<TextureFormat>("\"rgba32float\"").unwrap(),
4606        TextureFormat::Rgba32Float
4607    );
4608    assert_eq!(
4609        serde_json::from_str::<TextureFormat>("\"stencil8\"").unwrap(),
4610        TextureFormat::Stencil8
4611    );
4612    assert_eq!(
4613        serde_json::from_str::<TextureFormat>("\"depth32float\"").unwrap(),
4614        TextureFormat::Depth32Float
4615    );
4616    assert_eq!(
4617        serde_json::from_str::<TextureFormat>("\"depth16unorm\"").unwrap(),
4618        TextureFormat::Depth16Unorm
4619    );
4620    assert_eq!(
4621        serde_json::from_str::<TextureFormat>("\"depth32float-stencil8\"").unwrap(),
4622        TextureFormat::Depth32FloatStencil8
4623    );
4624    assert_eq!(
4625        serde_json::from_str::<TextureFormat>("\"depth24plus\"").unwrap(),
4626        TextureFormat::Depth24Plus
4627    );
4628    assert_eq!(
4629        serde_json::from_str::<TextureFormat>("\"depth24plus-stencil8\"").unwrap(),
4630        TextureFormat::Depth24PlusStencil8
4631    );
4632    assert_eq!(
4633        serde_json::from_str::<TextureFormat>("\"rgb9e5ufloat\"").unwrap(),
4634        TextureFormat::Rgb9e5Ufloat
4635    );
4636    assert_eq!(
4637        serde_json::from_str::<TextureFormat>("\"bc1-rgba-unorm\"").unwrap(),
4638        TextureFormat::Bc1RgbaUnorm
4639    );
4640    assert_eq!(
4641        serde_json::from_str::<TextureFormat>("\"bc1-rgba-unorm-srgb\"").unwrap(),
4642        TextureFormat::Bc1RgbaUnormSrgb
4643    );
4644    assert_eq!(
4645        serde_json::from_str::<TextureFormat>("\"bc2-rgba-unorm\"").unwrap(),
4646        TextureFormat::Bc2RgbaUnorm
4647    );
4648    assert_eq!(
4649        serde_json::from_str::<TextureFormat>("\"bc2-rgba-unorm-srgb\"").unwrap(),
4650        TextureFormat::Bc2RgbaUnormSrgb
4651    );
4652    assert_eq!(
4653        serde_json::from_str::<TextureFormat>("\"bc3-rgba-unorm\"").unwrap(),
4654        TextureFormat::Bc3RgbaUnorm
4655    );
4656    assert_eq!(
4657        serde_json::from_str::<TextureFormat>("\"bc3-rgba-unorm-srgb\"").unwrap(),
4658        TextureFormat::Bc3RgbaUnormSrgb
4659    );
4660    assert_eq!(
4661        serde_json::from_str::<TextureFormat>("\"bc4-r-unorm\"").unwrap(),
4662        TextureFormat::Bc4RUnorm
4663    );
4664    assert_eq!(
4665        serde_json::from_str::<TextureFormat>("\"bc4-r-snorm\"").unwrap(),
4666        TextureFormat::Bc4RSnorm
4667    );
4668    assert_eq!(
4669        serde_json::from_str::<TextureFormat>("\"bc5-rg-unorm\"").unwrap(),
4670        TextureFormat::Bc5RgUnorm
4671    );
4672    assert_eq!(
4673        serde_json::from_str::<TextureFormat>("\"bc5-rg-snorm\"").unwrap(),
4674        TextureFormat::Bc5RgSnorm
4675    );
4676    assert_eq!(
4677        serde_json::from_str::<TextureFormat>("\"bc6h-rgb-ufloat\"").unwrap(),
4678        TextureFormat::Bc6hRgbUfloat
4679    );
4680    assert_eq!(
4681        serde_json::from_str::<TextureFormat>("\"bc6h-rgb-float\"").unwrap(),
4682        TextureFormat::Bc6hRgbFloat
4683    );
4684    assert_eq!(
4685        serde_json::from_str::<TextureFormat>("\"bc7-rgba-unorm\"").unwrap(),
4686        TextureFormat::Bc7RgbaUnorm
4687    );
4688    assert_eq!(
4689        serde_json::from_str::<TextureFormat>("\"bc7-rgba-unorm-srgb\"").unwrap(),
4690        TextureFormat::Bc7RgbaUnormSrgb
4691    );
4692    assert_eq!(
4693        serde_json::from_str::<TextureFormat>("\"etc2-rgb8unorm\"").unwrap(),
4694        TextureFormat::Etc2Rgb8Unorm
4695    );
4696    assert_eq!(
4697        serde_json::from_str::<TextureFormat>("\"etc2-rgb8unorm-srgb\"").unwrap(),
4698        TextureFormat::Etc2Rgb8UnormSrgb
4699    );
4700    assert_eq!(
4701        serde_json::from_str::<TextureFormat>("\"etc2-rgb8a1unorm\"").unwrap(),
4702        TextureFormat::Etc2Rgb8A1Unorm
4703    );
4704    assert_eq!(
4705        serde_json::from_str::<TextureFormat>("\"etc2-rgb8a1unorm-srgb\"").unwrap(),
4706        TextureFormat::Etc2Rgb8A1UnormSrgb
4707    );
4708    assert_eq!(
4709        serde_json::from_str::<TextureFormat>("\"etc2-rgba8unorm\"").unwrap(),
4710        TextureFormat::Etc2Rgba8Unorm
4711    );
4712    assert_eq!(
4713        serde_json::from_str::<TextureFormat>("\"etc2-rgba8unorm-srgb\"").unwrap(),
4714        TextureFormat::Etc2Rgba8UnormSrgb
4715    );
4716    assert_eq!(
4717        serde_json::from_str::<TextureFormat>("\"eac-r11unorm\"").unwrap(),
4718        TextureFormat::EacR11Unorm
4719    );
4720    assert_eq!(
4721        serde_json::from_str::<TextureFormat>("\"eac-r11snorm\"").unwrap(),
4722        TextureFormat::EacR11Snorm
4723    );
4724    assert_eq!(
4725        serde_json::from_str::<TextureFormat>("\"eac-rg11unorm\"").unwrap(),
4726        TextureFormat::EacRg11Unorm
4727    );
4728    assert_eq!(
4729        serde_json::from_str::<TextureFormat>("\"eac-rg11snorm\"").unwrap(),
4730        TextureFormat::EacRg11Snorm
4731    );
4732}
4733
4734/// Color write mask. Disabled color channels will not be written to.
4735///
4736/// Corresponds to [WebGPU `GPUColorWriteFlags`](
4737/// https://gpuweb.github.io/gpuweb/#typedefdef-gpucolorwriteflags).
4738#[repr(transparent)]
4739#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4740#[cfg_attr(feature = "serde", serde(transparent))]
4741#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
4742pub struct ColorWrites(u32);
4743
4744bitflags::bitflags! {
4745    impl ColorWrites: u32 {
4746        /// Enable red channel writes
4747        const RED = 1 << 0;
4748        /// Enable green channel writes
4749        const GREEN = 1 << 1;
4750        /// Enable blue channel writes
4751        const BLUE = 1 << 2;
4752        /// Enable alpha channel writes
4753        const ALPHA = 1 << 3;
4754        /// Enable red, green, and blue channel writes
4755        const COLOR = Self::RED.bits() | Self::GREEN.bits() | Self::BLUE.bits();
4756        /// Enable writes to all channels.
4757        const ALL = Self::RED.bits() | Self::GREEN.bits() | Self::BLUE.bits() | Self::ALPHA.bits();
4758    }
4759}
4760
4761impl Default for ColorWrites {
4762    fn default() -> Self {
4763        Self::ALL
4764    }
4765}
4766
4767/// Passed to `Device::poll` to control how and if it should block.
4768#[derive(Clone, Debug)]
4769pub enum Maintain<T> {
4770    /// On wgpu-core based backends, block until the given submission has
4771    /// completed execution, and any callbacks have been invoked.
4772    ///
4773    /// On WebGPU, this has no effect. Callbacks are invoked from the
4774    /// window event loop.
4775    WaitForSubmissionIndex(T),
4776    /// Same as WaitForSubmissionIndex but waits for the most recent submission.
4777    Wait,
4778    /// Check the device for a single time without blocking.
4779    Poll,
4780}
4781
4782impl<T> Maintain<T> {
4783    /// Construct a wait variant
4784    #[must_use]
4785    pub fn wait() -> Self {
4786        // This function seems a little silly, but it is useful to allow
4787        // <https://github.com/gfx-rs/wgpu/pull/5012> to be split up, as
4788        // it has meaning in that PR.
4789        Self::Wait
4790    }
4791
4792    /// Construct a WaitForSubmissionIndex variant
4793    #[must_use]
4794    pub fn wait_for(submission_index: T) -> Self {
4795        // This function seems a little silly, but it is useful to allow
4796        // <https://github.com/gfx-rs/wgpu/pull/5012> to be split up, as
4797        // it has meaning in that PR.
4798        Self::WaitForSubmissionIndex(submission_index)
4799    }
4800
4801    /// This maintain represents a wait of some kind.
4802    #[must_use]
4803    pub fn is_wait(&self) -> bool {
4804        match *self {
4805            Self::WaitForSubmissionIndex(..) | Self::Wait => true,
4806            Self::Poll => false,
4807        }
4808    }
4809
4810    /// Map on the wait index type.
4811    #[must_use]
4812    pub fn map_index<U, F>(self, func: F) -> Maintain<U>
4813    where
4814        F: FnOnce(T) -> U,
4815    {
4816        match self {
4817            Self::WaitForSubmissionIndex(i) => Maintain::WaitForSubmissionIndex(func(i)),
4818            Self::Wait => Maintain::Wait,
4819            Self::Poll => Maintain::Poll,
4820        }
4821    }
4822}
4823
4824/// Result of a maintain operation.
4825pub enum MaintainResult {
4826    /// There are no active submissions in flight as of the beginning of the poll call.
4827    /// Other submissions may have been queued on other threads at the same time.
4828    ///
4829    /// This implies that the given poll is complete.
4830    SubmissionQueueEmpty,
4831    /// More information coming soon <https://github.com/gfx-rs/wgpu/pull/5012>
4832    Ok,
4833}
4834
4835impl MaintainResult {
4836    /// Returns true if the result is [`Self::SubmissionQueueEmpty`]`.
4837    #[must_use]
4838    pub fn is_queue_empty(&self) -> bool {
4839        matches!(self, Self::SubmissionQueueEmpty)
4840    }
4841
4842    /// Panics if the MaintainResult is not Ok.
4843    pub fn panic_on_timeout(self) {
4844        let _ = self;
4845    }
4846}
4847
4848/// State of the stencil operation (fixed-pipeline stage).
4849///
4850/// For use in [`DepthStencilState`].
4851///
4852/// Corresponds to a portion of [WebGPU `GPUDepthStencilState`](
4853/// https://gpuweb.github.io/gpuweb/#dictdef-gpudepthstencilstate).
4854#[repr(C)]
4855#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
4856#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4857pub struct StencilState {
4858    /// Front face mode.
4859    pub front: StencilFaceState,
4860    /// Back face mode.
4861    pub back: StencilFaceState,
4862    /// Stencil values are AND'd with this mask when reading and writing from the stencil buffer. Only low 8 bits are used.
4863    pub read_mask: u32,
4864    /// Stencil values are AND'd with this mask when writing to the stencil buffer. Only low 8 bits are used.
4865    pub write_mask: u32,
4866}
4867
4868impl StencilState {
4869    /// Returns true if the stencil test is enabled.
4870    #[must_use]
4871    pub fn is_enabled(&self) -> bool {
4872        (self.front != StencilFaceState::IGNORE || self.back != StencilFaceState::IGNORE)
4873            && (self.read_mask != 0 || self.write_mask != 0)
4874    }
4875    /// Returns true if the state doesn't mutate the target values.
4876    #[must_use]
4877    pub fn is_read_only(&self, cull_mode: Option<Face>) -> bool {
4878        // The rules are defined in step 7 of the "Device timeline initialization steps"
4879        // subsection of the "Render Pipeline Creation" section of WebGPU
4880        // (link to the section: https://gpuweb.github.io/gpuweb/#render-pipeline-creation)
4881
4882        if self.write_mask == 0 {
4883            return true;
4884        }
4885
4886        let front_ro = cull_mode == Some(Face::Front) || self.front.is_read_only();
4887        let back_ro = cull_mode == Some(Face::Back) || self.back.is_read_only();
4888
4889        front_ro && back_ro
4890    }
4891    /// Returns true if the stencil state uses the reference value for testing.
4892    #[must_use]
4893    pub fn needs_ref_value(&self) -> bool {
4894        self.front.needs_ref_value() || self.back.needs_ref_value()
4895    }
4896}
4897
4898/// Describes the biasing setting for the depth target.
4899///
4900/// For use in [`DepthStencilState`].
4901///
4902/// Corresponds to a portion of [WebGPU `GPUDepthStencilState`](
4903/// https://gpuweb.github.io/gpuweb/#dictdef-gpudepthstencilstate).
4904#[repr(C)]
4905#[derive(Clone, Copy, Debug, Default)]
4906#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4907pub struct DepthBiasState {
4908    /// Constant depth biasing factor, in basic units of the depth format.
4909    pub constant: i32,
4910    /// Slope depth biasing factor.
4911    pub slope_scale: f32,
4912    /// Depth bias clamp value (absolute).
4913    pub clamp: f32,
4914}
4915
4916impl DepthBiasState {
4917    /// Returns true if the depth biasing is enabled.
4918    #[must_use]
4919    pub fn is_enabled(&self) -> bool {
4920        self.constant != 0 || self.slope_scale != 0.0
4921    }
4922}
4923
4924impl Hash for DepthBiasState {
4925    fn hash<H: Hasher>(&self, state: &mut H) {
4926        self.constant.hash(state);
4927        self.slope_scale.to_bits().hash(state);
4928        self.clamp.to_bits().hash(state);
4929    }
4930}
4931
4932impl PartialEq for DepthBiasState {
4933    fn eq(&self, other: &Self) -> bool {
4934        (self.constant == other.constant)
4935            && (self.slope_scale.to_bits() == other.slope_scale.to_bits())
4936            && (self.clamp.to_bits() == other.clamp.to_bits())
4937    }
4938}
4939
4940impl Eq for DepthBiasState {}
4941
4942/// Operation to perform to the output attachment at the start of a render pass.
4943///
4944/// Corresponds to [WebGPU `GPULoadOp`](https://gpuweb.github.io/gpuweb/#enumdef-gpuloadop),
4945/// plus the corresponding clearValue.
4946#[repr(u8)]
4947#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
4948#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4949#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
4950pub enum LoadOp<V> {
4951    /// Loads the specified value for this attachment into the render pass.
4952    ///
4953    /// On some GPU hardware (primarily mobile), "clear" is significantly cheaper
4954    /// because it avoids loading data from main memory into tile-local memory.
4955    ///
4956    /// On other GPU hardware, there isn’t a significant difference.
4957    ///
4958    /// As a result, it is recommended to use "clear" rather than "load" in cases
4959    /// where the initial value doesn’t matter
4960    /// (e.g. the render target will be cleared using a skybox).
4961    Clear(V) = 0,
4962    /// Loads the existing value for this attachment into the render pass.
4963    Load = 1,
4964}
4965
4966impl<V> LoadOp<V> {
4967    /// Returns true if variants are same (ignoring clear value)
4968    pub fn eq_variant<T>(&self, other: LoadOp<T>) -> bool {
4969        matches!(
4970            (self, other),
4971            (LoadOp::Clear(_), LoadOp::Clear(_)) | (LoadOp::Load, LoadOp::Load)
4972        )
4973    }
4974}
4975
4976impl<V: Default> Default for LoadOp<V> {
4977    fn default() -> Self {
4978        Self::Clear(Default::default())
4979    }
4980}
4981
4982/// Operation to perform to the output attachment at the end of a render pass.
4983///
4984/// Corresponds to [WebGPU `GPUStoreOp`](https://gpuweb.github.io/gpuweb/#enumdef-gpustoreop).
4985#[repr(C)]
4986#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Default)]
4987#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4988#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
4989pub enum StoreOp {
4990    /// Stores the resulting value of the render pass for this attachment.
4991    #[default]
4992    Store = 0,
4993    /// Discards the resulting value of the render pass for this attachment.
4994    ///
4995    /// The attachment will be treated as uninitialized afterwards.
4996    /// (If only either Depth or Stencil texture-aspects is set to `Discard`,
4997    /// the respective other texture-aspect will be preserved.)
4998    ///
4999    /// This can be significantly faster on tile-based render hardware.
5000    ///
5001    /// Prefer this if the attachment is not read by subsequent passes.
5002    Discard = 1,
5003}
5004
5005/// Pair of load and store operations for an attachment aspect.
5006///
5007/// This type is unique to the Rust API of `wgpu`. In the WebGPU specification,
5008/// separate `loadOp` and `storeOp` fields are used instead.
5009#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
5010#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
5011pub struct Operations<V> {
5012    /// How data should be read through this attachment.
5013    pub load: LoadOp<V>,
5014    /// Whether data will be written to through this attachment.
5015    ///
5016    /// Note that resolve textures (if specified) are always written to,
5017    /// regardless of this setting.
5018    pub store: StoreOp,
5019}
5020
5021impl<V: Default> Default for Operations<V> {
5022    #[inline]
5023    fn default() -> Self {
5024        Self {
5025            load: LoadOp::<V>::default(),
5026            store: StoreOp::default(),
5027        }
5028    }
5029}
5030
5031/// Describes the depth/stencil state in a render pipeline.
5032///
5033/// Corresponds to [WebGPU `GPUDepthStencilState`](
5034/// https://gpuweb.github.io/gpuweb/#dictdef-gpudepthstencilstate).
5035#[repr(C)]
5036#[derive(Clone, Debug, Hash, PartialEq, Eq)]
5037#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5038pub struct DepthStencilState {
5039    /// Format of the depth/stencil buffer, must be special depth format. Must match the format
5040    /// of the depth/stencil attachment in [`CommandEncoder::begin_render_pass`][CEbrp].
5041    ///
5042    /// [CEbrp]: ../wgpu/struct.CommandEncoder.html#method.begin_render_pass
5043    pub format: TextureFormat,
5044    /// If disabled, depth will not be written to.
5045    pub depth_write_enabled: bool,
5046    /// Comparison function used to compare depth values in the depth test.
5047    pub depth_compare: CompareFunction,
5048    /// Stencil state.
5049    #[cfg_attr(feature = "serde", serde(default))]
5050    pub stencil: StencilState,
5051    /// Depth bias state.
5052    #[cfg_attr(feature = "serde", serde(default))]
5053    pub bias: DepthBiasState,
5054}
5055
5056impl DepthStencilState {
5057    /// Returns true if the depth testing is enabled.
5058    #[must_use]
5059    pub fn is_depth_enabled(&self) -> bool {
5060        self.depth_compare != CompareFunction::Always || self.depth_write_enabled
5061    }
5062
5063    /// Returns true if the state doesn't mutate the depth buffer.
5064    #[must_use]
5065    pub fn is_depth_read_only(&self) -> bool {
5066        !self.depth_write_enabled
5067    }
5068
5069    /// Returns true if the state doesn't mutate the stencil.
5070    #[must_use]
5071    pub fn is_stencil_read_only(&self, cull_mode: Option<Face>) -> bool {
5072        self.stencil.is_read_only(cull_mode)
5073    }
5074
5075    /// Returns true if the state doesn't mutate either depth or stencil of the target.
5076    #[must_use]
5077    pub fn is_read_only(&self, cull_mode: Option<Face>) -> bool {
5078        self.is_depth_read_only() && self.is_stencil_read_only(cull_mode)
5079    }
5080}
5081
5082/// Format of indices used with pipeline.
5083///
5084/// Corresponds to [WebGPU `GPUIndexFormat`](
5085/// https://gpuweb.github.io/gpuweb/#enumdef-gpuindexformat).
5086#[repr(C)]
5087#[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq)]
5088#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5089#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
5090pub enum IndexFormat {
5091    /// Indices are 16 bit unsigned integers.
5092    Uint16 = 0,
5093    /// Indices are 32 bit unsigned integers.
5094    #[default]
5095    Uint32 = 1,
5096}
5097
5098impl IndexFormat {
5099    /// Returns the size in bytes of the index format
5100    pub fn byte_size(&self) -> usize {
5101        match self {
5102            IndexFormat::Uint16 => 2,
5103            IndexFormat::Uint32 => 4,
5104        }
5105    }
5106}
5107
5108/// Operation to perform on the stencil value.
5109///
5110/// Corresponds to [WebGPU `GPUStencilOperation`](
5111/// https://gpuweb.github.io/gpuweb/#enumdef-gpustenciloperation).
5112#[repr(C)]
5113#[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq)]
5114#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5115#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
5116pub enum StencilOperation {
5117    /// Keep stencil value unchanged.
5118    #[default]
5119    Keep = 0,
5120    /// Set stencil value to zero.
5121    Zero = 1,
5122    /// Replace stencil value with value provided in most recent call to
5123    /// [`RenderPass::set_stencil_reference`][RPssr].
5124    ///
5125    /// [RPssr]: ../wgpu/struct.RenderPass.html#method.set_stencil_reference
5126    Replace = 2,
5127    /// Bitwise inverts stencil value.
5128    Invert = 3,
5129    /// Increments stencil value by one, clamping on overflow.
5130    IncrementClamp = 4,
5131    /// Decrements stencil value by one, clamping on underflow.
5132    DecrementClamp = 5,
5133    /// Increments stencil value by one, wrapping on overflow.
5134    IncrementWrap = 6,
5135    /// Decrements stencil value by one, wrapping on underflow.
5136    DecrementWrap = 7,
5137}
5138
5139/// Describes stencil state in a render pipeline.
5140///
5141/// If you are not using stencil state, set this to [`StencilFaceState::IGNORE`].
5142///
5143/// Corresponds to [WebGPU `GPUStencilFaceState`](
5144/// https://gpuweb.github.io/gpuweb/#dictdef-gpustencilfacestate).
5145#[repr(C)]
5146#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
5147#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5148#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
5149pub struct StencilFaceState {
5150    /// Comparison function that determines if the fail_op or pass_op is used on the stencil buffer.
5151    pub compare: CompareFunction,
5152    /// Operation that is performed when stencil test fails.
5153    pub fail_op: StencilOperation,
5154    /// Operation that is performed when depth test fails but stencil test succeeds.
5155    pub depth_fail_op: StencilOperation,
5156    /// Operation that is performed when stencil test success.
5157    pub pass_op: StencilOperation,
5158}
5159
5160impl StencilFaceState {
5161    /// Ignore the stencil state for the face.
5162    pub const IGNORE: Self = StencilFaceState {
5163        compare: CompareFunction::Always,
5164        fail_op: StencilOperation::Keep,
5165        depth_fail_op: StencilOperation::Keep,
5166        pass_op: StencilOperation::Keep,
5167    };
5168
5169    /// Returns true if the face state uses the reference value for testing or operation.
5170    #[must_use]
5171    pub fn needs_ref_value(&self) -> bool {
5172        self.compare.needs_ref_value()
5173            || self.fail_op == StencilOperation::Replace
5174            || self.depth_fail_op == StencilOperation::Replace
5175            || self.pass_op == StencilOperation::Replace
5176    }
5177
5178    /// Returns true if the face state doesn't mutate the target values.
5179    #[must_use]
5180    pub fn is_read_only(&self) -> bool {
5181        self.pass_op == StencilOperation::Keep
5182            && self.depth_fail_op == StencilOperation::Keep
5183            && self.fail_op == StencilOperation::Keep
5184    }
5185}
5186
5187impl Default for StencilFaceState {
5188    fn default() -> Self {
5189        Self::IGNORE
5190    }
5191}
5192
5193/// Comparison function used for depth and stencil operations.
5194///
5195/// Corresponds to [WebGPU `GPUCompareFunction`](
5196/// https://gpuweb.github.io/gpuweb/#enumdef-gpucomparefunction).
5197#[repr(C)]
5198#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
5199#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5200#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
5201pub enum CompareFunction {
5202    /// Function never passes
5203    Never = 1,
5204    /// Function passes if new value less than existing value
5205    Less = 2,
5206    /// Function passes if new value is equal to existing value. When using
5207    /// this compare function, make sure to mark your Vertex Shader's `@builtin(position)`
5208    /// output as `@invariant` to prevent artifacting.
5209    Equal = 3,
5210    /// Function passes if new value is less than or equal to existing value
5211    LessEqual = 4,
5212    /// Function passes if new value is greater than existing value
5213    Greater = 5,
5214    /// Function passes if new value is not equal to existing value. When using
5215    /// this compare function, make sure to mark your Vertex Shader's `@builtin(position)`
5216    /// output as `@invariant` to prevent artifacting.
5217    NotEqual = 6,
5218    /// Function passes if new value is greater than or equal to existing value
5219    GreaterEqual = 7,
5220    /// Function always passes
5221    Always = 8,
5222}
5223
5224impl CompareFunction {
5225    /// Returns true if the comparison depends on the reference value.
5226    #[must_use]
5227    pub fn needs_ref_value(self) -> bool {
5228        match self {
5229            Self::Never | Self::Always => false,
5230            _ => true,
5231        }
5232    }
5233}
5234
5235/// Whether a vertex buffer is indexed by vertex or by instance.
5236///
5237/// Consider a call to [`RenderPass::draw`] like this:
5238///
5239/// ```ignore
5240/// render_pass.draw(vertices, instances)
5241/// ```
5242///
5243/// where `vertices` is a `Range<u32>` of vertex indices, and
5244/// `instances` is a `Range<u32>` of instance indices.
5245///
5246/// For this call, `wgpu` invokes the vertex shader entry point once
5247/// for every possible `(v, i)` pair, where `v` is drawn from
5248/// `vertices` and `i` is drawn from `instances`. These invocations
5249/// may happen in any order, and will usually run in parallel.
5250///
5251/// Each vertex buffer has a step mode, established by the
5252/// [`step_mode`] field of its [`VertexBufferLayout`], given when the
5253/// pipeline was created. Buffers whose step mode is [`Vertex`] use
5254/// `v` as the index into their contents, whereas buffers whose step
5255/// mode is [`Instance`] use `i`. The indicated buffer element then
5256/// contributes zero or more attribute values for the `(v, i)` vertex
5257/// shader invocation to use, based on the [`VertexBufferLayout`]'s
5258/// [`attributes`] list.
5259///
5260/// You can visualize the results from all these vertex shader
5261/// invocations as a matrix with a row for each `i` from `instances`,
5262/// and with a column for each `v` from `vertices`. In one sense, `v`
5263/// and `i` are symmetrical: both are used to index vertex buffers and
5264/// provide attribute values.  But the key difference between `v` and
5265/// `i` is that line and triangle primitives are built from the values
5266/// of each row, along which `i` is constant and `v` varies, not the
5267/// columns.
5268///
5269/// An indexed draw call works similarly:
5270///
5271/// ```ignore
5272/// render_pass.draw_indexed(indices, base_vertex, instances)
5273/// ```
5274///
5275/// The only difference is that `v` values are drawn from the contents
5276/// of the index buffer&mdash;specifically, the subrange of the index
5277/// buffer given by `indices`&mdash;instead of simply being sequential
5278/// integers, as they are in a `draw` call.
5279///
5280/// A non-instanced call, where `instances` is `0..1`, is simply a
5281/// matrix with only one row.
5282///
5283/// Corresponds to [WebGPU `GPUVertexStepMode`](
5284/// https://gpuweb.github.io/gpuweb/#enumdef-gpuvertexstepmode).
5285///
5286/// [`RenderPass::draw`]: ../wgpu/struct.RenderPass.html#method.draw
5287/// [`VertexBufferLayout`]: ../wgpu/struct.VertexBufferLayout.html
5288/// [`step_mode`]: ../wgpu/struct.VertexBufferLayout.html#structfield.step_mode
5289/// [`attributes`]: ../wgpu/struct.VertexBufferLayout.html#structfield.attributes
5290/// [`Vertex`]: VertexStepMode::Vertex
5291/// [`Instance`]: VertexStepMode::Instance
5292#[repr(C)]
5293#[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq)]
5294#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5295#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
5296pub enum VertexStepMode {
5297    /// Vertex data is advanced every vertex.
5298    #[default]
5299    Vertex = 0,
5300    /// Vertex data is advanced every instance.
5301    Instance = 1,
5302}
5303
5304/// Vertex inputs (attributes) to shaders.
5305///
5306/// Arrays of these can be made with the [`vertex_attr_array`]
5307/// macro. Vertex attributes are assumed to be tightly packed.
5308///
5309/// Corresponds to [WebGPU `GPUVertexAttribute`](
5310/// https://gpuweb.github.io/gpuweb/#dictdef-gpuvertexattribute).
5311///
5312/// [`vertex_attr_array`]: ../wgpu/macro.vertex_attr_array.html
5313#[repr(C)]
5314#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
5315#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5316#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
5317pub struct VertexAttribute {
5318    /// Format of the input
5319    pub format: VertexFormat,
5320    /// Byte offset of the start of the input
5321    pub offset: BufferAddress,
5322    /// Location for this input. Must match the location in the shader.
5323    pub shader_location: ShaderLocation,
5324}
5325
5326/// Vertex Format for a [`VertexAttribute`] (input).
5327///
5328/// Corresponds to [WebGPU `GPUVertexFormat`](
5329/// https://gpuweb.github.io/gpuweb/#enumdef-gpuvertexformat).
5330#[repr(C)]
5331#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
5332#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5333#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
5334pub enum VertexFormat {
5335    /// One unsigned byte (u8). `u32` in shaders.
5336    Uint8 = 0,
5337    /// Two unsigned bytes (u8). `vec2<u32>` in shaders.
5338    Uint8x2 = 1,
5339    /// Four unsigned bytes (u8). `vec4<u32>` in shaders.
5340    Uint8x4 = 2,
5341    /// One signed byte (i8). `i32` in shaders.
5342    Sint8 = 3,
5343    /// Two signed bytes (i8). `vec2<i32>` in shaders.
5344    Sint8x2 = 4,
5345    /// Four signed bytes (i8). `vec4<i32>` in shaders.
5346    Sint8x4 = 5,
5347    /// One unsigned byte (u8). [0, 255] converted to float [0, 1] `f32` in shaders.
5348    Unorm8 = 6,
5349    /// Two unsigned bytes (u8). [0, 255] converted to float [0, 1] `vec2<f32>` in shaders.
5350    Unorm8x2 = 7,
5351    /// Four unsigned bytes (u8). [0, 255] converted to float [0, 1] `vec4<f32>` in shaders.
5352    Unorm8x4 = 8,
5353    /// One signed byte (i8). [-127, 127] converted to float [-1, 1] `f32` in shaders.
5354    Snorm8 = 9,
5355    /// Two signed bytes (i8). [-127, 127] converted to float [-1, 1] `vec2<f32>` in shaders.
5356    Snorm8x2 = 10,
5357    /// Four signed bytes (i8). [-127, 127] converted to float [-1, 1] `vec4<f32>` in shaders.
5358    Snorm8x4 = 11,
5359    /// One unsigned short (u16). `u32` in shaders.
5360    Uint16 = 12,
5361    /// Two unsigned shorts (u16). `vec2<u32>` in shaders.
5362    Uint16x2 = 13,
5363    /// Four unsigned shorts (u16). `vec4<u32>` in shaders.
5364    Uint16x4 = 14,
5365    /// One signed short (u16). `i32` in shaders.
5366    Sint16 = 15,
5367    /// Two signed shorts (i16). `vec2<i32>` in shaders.
5368    Sint16x2 = 16,
5369    /// Four signed shorts (i16). `vec4<i32>` in shaders.
5370    Sint16x4 = 17,
5371    /// One unsigned short (u16). [0, 65535] converted to float [0, 1] `f32` in shaders.
5372    Unorm16 = 18,
5373    /// Two unsigned shorts (u16). [0, 65535] converted to float [0, 1] `vec2<f32>` in shaders.
5374    Unorm16x2 = 19,
5375    /// Four unsigned shorts (u16). [0, 65535] converted to float [0, 1] `vec4<f32>` in shaders.
5376    Unorm16x4 = 20,
5377    /// One signed short (i16). [-32767, 32767] converted to float [-1, 1] `f32` in shaders.
5378    Snorm16 = 21,
5379    /// Two signed shorts (i16). [-32767, 32767] converted to float [-1, 1] `vec2<f32>` in shaders.
5380    Snorm16x2 = 22,
5381    /// Four signed shorts (i16). [-32767, 32767] converted to float [-1, 1] `vec4<f32>` in shaders.
5382    Snorm16x4 = 23,
5383    /// One half-precision float (no Rust equiv). `f32` in shaders.
5384    Float16 = 24,
5385    /// Two half-precision floats (no Rust equiv). `vec2<f32>` in shaders.
5386    Float16x2 = 25,
5387    /// Four half-precision floats (no Rust equiv). `vec4<f32>` in shaders.
5388    Float16x4 = 26,
5389    /// One single-precision float (f32). `f32` in shaders.
5390    Float32 = 27,
5391    /// Two single-precision floats (f32). `vec2<f32>` in shaders.
5392    Float32x2 = 28,
5393    /// Three single-precision floats (f32). `vec3<f32>` in shaders.
5394    Float32x3 = 29,
5395    /// Four single-precision floats (f32). `vec4<f32>` in shaders.
5396    Float32x4 = 30,
5397    /// One unsigned int (u32). `u32` in shaders.
5398    Uint32 = 31,
5399    /// Two unsigned ints (u32). `vec2<u32>` in shaders.
5400    Uint32x2 = 32,
5401    /// Three unsigned ints (u32). `vec3<u32>` in shaders.
5402    Uint32x3 = 33,
5403    /// Four unsigned ints (u32). `vec4<u32>` in shaders.
5404    Uint32x4 = 34,
5405    /// One signed int (i32). `i32` in shaders.
5406    Sint32 = 35,
5407    /// Two signed ints (i32). `vec2<i32>` in shaders.
5408    Sint32x2 = 36,
5409    /// Three signed ints (i32). `vec3<i32>` in shaders.
5410    Sint32x3 = 37,
5411    /// Four signed ints (i32). `vec4<i32>` in shaders.
5412    Sint32x4 = 38,
5413    /// One double-precision float (f64). `f32` in shaders. Requires [`Features::VERTEX_ATTRIBUTE_64BIT`].
5414    Float64 = 39,
5415    /// Two double-precision floats (f64). `vec2<f32>` in shaders. Requires [`Features::VERTEX_ATTRIBUTE_64BIT`].
5416    Float64x2 = 40,
5417    /// Three double-precision floats (f64). `vec3<f32>` in shaders. Requires [`Features::VERTEX_ATTRIBUTE_64BIT`].
5418    Float64x3 = 41,
5419    /// Four double-precision floats (f64). `vec4<f32>` in shaders. Requires [`Features::VERTEX_ATTRIBUTE_64BIT`].
5420    Float64x4 = 42,
5421    /// Three unsigned 10-bit integers and one 2-bit integer, packed into a 32-bit integer (u32). [0, 1024] converted to float [0, 1] `vec4<f32>` in shaders.
5422    #[cfg_attr(feature = "serde", serde(rename = "unorm10-10-10-2"))]
5423    Unorm10_10_10_2 = 43,
5424    /// Four unsigned 8-bit integers, packed into a 32-bit integer (u32). [0, 255] converted to float [0, 1] `vec4<f32>` in shaders.
5425    #[cfg_attr(feature = "serde", serde(rename = "unorm8x4-bgra"))]
5426    Unorm8x4Bgra = 44,
5427}
5428
5429impl VertexFormat {
5430    /// Returns the byte size of the format.
5431    #[must_use]
5432    pub const fn size(&self) -> u64 {
5433        match self {
5434            Self::Uint8 | Self::Sint8 | Self::Unorm8 | Self::Snorm8 => 1,
5435            Self::Uint8x2
5436            | Self::Sint8x2
5437            | Self::Unorm8x2
5438            | Self::Snorm8x2
5439            | Self::Uint16
5440            | Self::Sint16
5441            | Self::Unorm16
5442            | Self::Snorm16
5443            | Self::Float16 => 2,
5444            Self::Uint8x4
5445            | Self::Sint8x4
5446            | Self::Unorm8x4
5447            | Self::Snorm8x4
5448            | Self::Uint16x2
5449            | Self::Sint16x2
5450            | Self::Unorm16x2
5451            | Self::Snorm16x2
5452            | Self::Float16x2
5453            | Self::Float32
5454            | Self::Uint32
5455            | Self::Sint32
5456            | Self::Unorm10_10_10_2
5457            | Self::Unorm8x4Bgra => 4,
5458            Self::Uint16x4
5459            | Self::Sint16x4
5460            | Self::Unorm16x4
5461            | Self::Snorm16x4
5462            | Self::Float16x4
5463            | Self::Float32x2
5464            | Self::Uint32x2
5465            | Self::Sint32x2
5466            | Self::Float64 => 8,
5467            Self::Float32x3 | Self::Uint32x3 | Self::Sint32x3 => 12,
5468            Self::Float32x4 | Self::Uint32x4 | Self::Sint32x4 | Self::Float64x2 => 16,
5469            Self::Float64x3 => 24,
5470            Self::Float64x4 => 32,
5471        }
5472    }
5473}
5474
5475bitflags::bitflags! {
5476    /// Different ways that you can use a buffer.
5477    ///
5478    /// The usages determine what kind of memory the buffer is allocated from and what
5479    /// actions the buffer can partake in.
5480    ///
5481    /// Corresponds to [WebGPU `GPUBufferUsageFlags`](
5482    /// https://gpuweb.github.io/gpuweb/#typedefdef-gpubufferusageflags).
5483    #[repr(transparent)]
5484    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5485    #[cfg_attr(feature = "serde", serde(transparent))]
5486    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
5487    pub struct BufferUsages: u32 {
5488        /// Allow a buffer to be mapped for reading using [`Buffer::map_async`] + [`Buffer::get_mapped_range`].
5489        /// This does not include creating a buffer with [`BufferDescriptor::mapped_at_creation`] set.
5490        ///
5491        /// If [`Features::MAPPABLE_PRIMARY_BUFFERS`] isn't enabled, the only other usage a buffer
5492        /// may have is COPY_DST.
5493        const MAP_READ = 1 << 0;
5494        /// Allow a buffer to be mapped for writing using [`Buffer::map_async`] + [`Buffer::get_mapped_range_mut`].
5495        /// This does not include creating a buffer with `mapped_at_creation` set.
5496        ///
5497        /// If [`Features::MAPPABLE_PRIMARY_BUFFERS`] feature isn't enabled, the only other usage a buffer
5498        /// may have is COPY_SRC.
5499        const MAP_WRITE = 1 << 1;
5500        /// Allow a buffer to be the source buffer for a [`CommandEncoder::copy_buffer_to_buffer`] or [`CommandEncoder::copy_buffer_to_texture`]
5501        /// operation.
5502        const COPY_SRC = 1 << 2;
5503        /// Allow a buffer to be the destination buffer for a [`CommandEncoder::copy_buffer_to_buffer`], [`CommandEncoder::copy_texture_to_buffer`],
5504        /// [`CommandEncoder::clear_buffer`] or [`Queue::write_buffer`] operation.
5505        const COPY_DST = 1 << 3;
5506        /// Allow a buffer to be the index buffer in a draw operation.
5507        const INDEX = 1 << 4;
5508        /// Allow a buffer to be the vertex buffer in a draw operation.
5509        const VERTEX = 1 << 5;
5510        /// Allow a buffer to be a [`BufferBindingType::Uniform`] inside a bind group.
5511        const UNIFORM = 1 << 6;
5512        /// Allow a buffer to be a [`BufferBindingType::Storage`] inside a bind group.
5513        const STORAGE = 1 << 7;
5514        /// Allow a buffer to be the indirect buffer in an indirect draw call.
5515        const INDIRECT = 1 << 8;
5516        /// Allow a buffer to be the destination buffer for a [`CommandEncoder::resolve_query_set`] operation.
5517        const QUERY_RESOLVE = 1 << 9;
5518        /// Allows a buffer to be used as input for a bottom level acceleration structure build
5519        const BLAS_INPUT = 1 << 10;
5520        /// Allows a buffer to be used as input for a top level acceleration structure build
5521        const TLAS_INPUT = 1 << 11;
5522    }
5523}
5524
5525/// Describes a [`Buffer`](../wgpu/struct.Buffer.html).
5526///
5527/// Corresponds to [WebGPU `GPUBufferDescriptor`](
5528/// https://gpuweb.github.io/gpuweb/#dictdef-gpubufferdescriptor).
5529#[repr(C)]
5530#[derive(Clone, Debug, PartialEq, Eq, Hash)]
5531#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5532pub struct BufferDescriptor<L> {
5533    /// Debug label of a buffer. This will show up in graphics debuggers for easy identification.
5534    pub label: L,
5535    /// Size of a buffer, in bytes.
5536    pub size: BufferAddress,
5537    /// Usages of a buffer. If the buffer is used in any way that isn't specified here, the operation
5538    /// will panic.
5539    pub usage: BufferUsages,
5540    /// Allows a buffer to be mapped immediately after they are made. It does not have to be [`BufferUsages::MAP_READ`] or
5541    /// [`BufferUsages::MAP_WRITE`], all buffers are allowed to be mapped at creation.
5542    ///
5543    /// If this is `true`, [`size`](#structfield.size) must be a multiple of
5544    /// [`COPY_BUFFER_ALIGNMENT`].
5545    pub mapped_at_creation: bool,
5546}
5547
5548impl<L> BufferDescriptor<L> {
5549    /// Takes a closure and maps the label of the buffer descriptor into another.
5550    #[must_use]
5551    pub fn map_label<K>(&self, fun: impl FnOnce(&L) -> K) -> BufferDescriptor<K> {
5552        BufferDescriptor {
5553            label: fun(&self.label),
5554            size: self.size,
5555            usage: self.usage,
5556            mapped_at_creation: self.mapped_at_creation,
5557        }
5558    }
5559}
5560
5561/// Describes a [`CommandEncoder`](../wgpu/struct.CommandEncoder.html).
5562///
5563/// Corresponds to [WebGPU `GPUCommandEncoderDescriptor`](
5564/// https://gpuweb.github.io/gpuweb/#dictdef-gpucommandencoderdescriptor).
5565#[repr(C)]
5566#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5567#[derive(Clone, Debug, PartialEq, Eq, Hash)]
5568pub struct CommandEncoderDescriptor<L> {
5569    /// Debug label for the command encoder. This will show up in graphics debuggers for easy identification.
5570    pub label: L,
5571}
5572
5573impl<L> CommandEncoderDescriptor<L> {
5574    /// Takes a closure and maps the label of the command encoder descriptor into another.
5575    #[must_use]
5576    pub fn map_label<K>(&self, fun: impl FnOnce(&L) -> K) -> CommandEncoderDescriptor<K> {
5577        CommandEncoderDescriptor {
5578            label: fun(&self.label),
5579        }
5580    }
5581}
5582
5583impl<T> Default for CommandEncoderDescriptor<Option<T>> {
5584    fn default() -> Self {
5585        Self { label: None }
5586    }
5587}
5588
5589/// Behavior of the presentation engine based on frame rate.
5590#[repr(C)]
5591#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
5592#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5593pub enum PresentMode {
5594    /// Chooses FifoRelaxed -> Fifo based on availability.
5595    ///
5596    /// Because of the fallback behavior, it is supported everywhere.
5597    AutoVsync = 0,
5598    /// Chooses Immediate -> Mailbox -> Fifo (on web) based on availability.
5599    ///
5600    /// Because of the fallback behavior, it is supported everywhere.
5601    AutoNoVsync = 1,
5602    /// Presentation frames are kept in a First-In-First-Out queue approximately 3 frames
5603    /// long. Every vertical blanking period, the presentation engine will pop a frame
5604    /// off the queue to display. If there is no frame to display, it will present the same
5605    /// frame again until the next vblank.
5606    ///
5607    /// When a present command is executed on the gpu, the presented image is added on the queue.
5608    ///
5609    /// No tearing will be observed.
5610    ///
5611    /// Calls to get_current_texture will block until there is a spot in the queue.
5612    ///
5613    /// Supported on all platforms.
5614    ///
5615    /// If you don't know what mode to choose, choose this mode. This is traditionally called "Vsync On".
5616    #[default]
5617    Fifo = 2,
5618    /// Presentation frames are kept in a First-In-First-Out queue approximately 3 frames
5619    /// long. Every vertical blanking period, the presentation engine will pop a frame
5620    /// off the queue to display. If there is no frame to display, it will present the
5621    /// same frame until there is a frame in the queue. The moment there is a frame in the
5622    /// queue, it will immediately pop the frame off the queue.
5623    ///
5624    /// When a present command is executed on the gpu, the presented image is added on the queue.
5625    ///
5626    /// Tearing will be observed if frames last more than one vblank as the front buffer.
5627    ///
5628    /// Calls to get_current_texture will block until there is a spot in the queue.
5629    ///
5630    /// Supported on AMD on Vulkan.
5631    ///
5632    /// This is traditionally called "Adaptive Vsync"
5633    FifoRelaxed = 3,
5634    /// Presentation frames are not queued at all. The moment a present command
5635    /// is executed on the GPU, the presented image is swapped onto the front buffer
5636    /// immediately.
5637    ///
5638    /// Tearing can be observed.
5639    ///
5640    /// Supported on most platforms except older DX12 and Wayland.
5641    ///
5642    /// This is traditionally called "Vsync Off".
5643    Immediate = 4,
5644    /// Presentation frames are kept in a single-frame queue. Every vertical blanking period,
5645    /// the presentation engine will pop a frame from the queue. If there is no frame to display,
5646    /// it will present the same frame again until the next vblank.
5647    ///
5648    /// When a present command is executed on the gpu, the frame will be put into the queue.
5649    /// If there was already a frame in the queue, the new frame will _replace_ the old frame
5650    /// on the queue.
5651    ///
5652    /// No tearing will be observed.
5653    ///
5654    /// Supported on DX12 on Windows 10, NVidia on Vulkan and Wayland on Vulkan.
5655    ///
5656    /// This is traditionally called "Fast Vsync"
5657    Mailbox = 5,
5658}
5659
5660/// Specifies how the alpha channel of the textures should be handled during
5661/// compositing.
5662#[repr(C)]
5663#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
5664#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5665#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
5666pub enum CompositeAlphaMode {
5667    /// Chooses either `Opaque` or `Inherit` automatically,depending on the
5668    /// `alpha_mode` that the current surface can support.
5669    Auto = 0,
5670    /// The alpha channel, if it exists, of the textures is ignored in the
5671    /// compositing process. Instead, the textures is treated as if it has a
5672    /// constant alpha of 1.0.
5673    Opaque = 1,
5674    /// The alpha channel, if it exists, of the textures is respected in the
5675    /// compositing process. The non-alpha channels of the textures are
5676    /// expected to already be multiplied by the alpha channel by the
5677    /// application.
5678    PreMultiplied = 2,
5679    /// The alpha channel, if it exists, of the textures is respected in the
5680    /// compositing process. The non-alpha channels of the textures are not
5681    /// expected to already be multiplied by the alpha channel by the
5682    /// application; instead, the compositor will multiply the non-alpha
5683    /// channels of the texture by the alpha channel during compositing.
5684    PostMultiplied = 3,
5685    /// The alpha channel, if it exists, of the textures is unknown for processing
5686    /// during compositing. Instead, the application is responsible for setting
5687    /// the composite alpha blending mode using native WSI command. If not set,
5688    /// then a platform-specific default will be used.
5689    Inherit = 4,
5690}
5691
5692impl Default for CompositeAlphaMode {
5693    fn default() -> Self {
5694        Self::Auto
5695    }
5696}
5697
5698bitflags::bitflags! {
5699    /// Different ways that you can use a texture.
5700    ///
5701    /// The usages determine what kind of memory the texture is allocated from and what
5702    /// actions the texture can partake in.
5703    ///
5704    /// Corresponds to [WebGPU `GPUTextureUsageFlags`](
5705    /// https://gpuweb.github.io/gpuweb/#typedefdef-gputextureusageflags).
5706    #[repr(transparent)]
5707    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5708    #[cfg_attr(feature = "serde", serde(transparent))]
5709    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
5710    pub struct TextureUsages: u32 {
5711        //
5712        // ---- Start numbering at 1 << 0 ----
5713        //
5714        // WebGPU features:
5715        //
5716        /// Allows a texture to be the source in a [`CommandEncoder::copy_texture_to_buffer`] or
5717        /// [`CommandEncoder::copy_texture_to_texture`] operation.
5718        const COPY_SRC = 1 << 0;
5719        /// Allows a texture to be the destination in a  [`CommandEncoder::copy_buffer_to_texture`],
5720        /// [`CommandEncoder::copy_texture_to_texture`], or [`Queue::write_texture`] operation.
5721        const COPY_DST = 1 << 1;
5722        /// Allows a texture to be a [`BindingType::Texture`] in a bind group.
5723        const TEXTURE_BINDING = 1 << 2;
5724        /// Allows a texture to be a [`BindingType::StorageTexture`] in a bind group.
5725        const STORAGE_BINDING = 1 << 3;
5726        /// Allows a texture to be an output attachment of a render pass.
5727        const RENDER_ATTACHMENT = 1 << 4;
5728
5729        //
5730        // ---- Restart Numbering for Native Features ---
5731        //
5732        // Native Features:
5733        //
5734        /// Allows a texture to be used with image atomics. Requires [`Features::TEXTURE_ATOMIC`].
5735        const STORAGE_ATOMIC = 1 << 16;
5736    }
5737}
5738
5739/// Defines the capabilities of a given surface and adapter.
5740#[derive(Debug)]
5741pub struct SurfaceCapabilities {
5742    /// List of supported formats to use with the given adapter. The first format in the vector is preferred.
5743    ///
5744    /// Returns an empty vector if the surface is incompatible with the adapter.
5745    pub formats: Vec<TextureFormat>,
5746    /// List of supported presentation modes to use with the given adapter.
5747    ///
5748    /// Returns an empty vector if the surface is incompatible with the adapter.
5749    pub present_modes: Vec<PresentMode>,
5750    /// List of supported alpha modes to use with the given adapter.
5751    ///
5752    /// Will return at least one element, CompositeAlphaMode::Opaque or CompositeAlphaMode::Inherit.
5753    pub alpha_modes: Vec<CompositeAlphaMode>,
5754    /// Bitflag of supported texture usages for the surface to use with the given adapter.
5755    ///
5756    /// The usage TextureUsages::RENDER_ATTACHMENT is guaranteed.
5757    pub usages: TextureUsages,
5758}
5759
5760impl Default for SurfaceCapabilities {
5761    fn default() -> Self {
5762        Self {
5763            formats: Vec::new(),
5764            present_modes: Vec::new(),
5765            alpha_modes: vec![CompositeAlphaMode::Opaque],
5766            usages: TextureUsages::RENDER_ATTACHMENT,
5767        }
5768    }
5769}
5770
5771/// Configures a [`Surface`] for presentation.
5772///
5773/// [`Surface`]: ../wgpu/struct.Surface.html
5774#[repr(C)]
5775#[derive(Clone, Debug, PartialEq, Eq, Hash)]
5776#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5777pub struct SurfaceConfiguration<V> {
5778    /// The usage of the swap chain. The only usage guaranteed to be supported is `RENDER_ATTACHMENT`.
5779    pub usage: TextureUsages,
5780    /// The texture format of the swap chain. The only formats that are guaranteed are
5781    /// `Bgra8Unorm` and `Bgra8UnormSrgb`
5782    pub format: TextureFormat,
5783    /// Width of the swap chain. Must be the same size as the surface, and nonzero.
5784    ///
5785    /// If this is not the same size as the underlying surface (e.g. if it is
5786    /// set once, and the window is later resized), the behaviour is defined
5787    /// but platform-specific, and may change in the future (currently macOS
5788    /// scales the surface, other platforms may do something else).
5789    pub width: u32,
5790    /// Height of the swap chain. Must be the same size as the surface, and nonzero.
5791    ///
5792    /// If this is not the same size as the underlying surface (e.g. if it is
5793    /// set once, and the window is later resized), the behaviour is defined
5794    /// but platform-specific, and may change in the future (currently macOS
5795    /// scales the surface, other platforms may do something else).
5796    pub height: u32,
5797    /// Presentation mode of the swap chain. Fifo is the only mode guaranteed to be supported.
5798    /// FifoRelaxed, Immediate, and Mailbox will crash if unsupported, while AutoVsync and
5799    /// AutoNoVsync will gracefully do a designed sets of fallbacks if their primary modes are
5800    /// unsupported.
5801    pub present_mode: PresentMode,
5802    /// Desired maximum number of frames that the presentation engine should queue in advance.
5803    ///
5804    /// This is a hint to the backend implementation and will always be clamped to the supported range.
5805    /// As a consequence, either the maximum frame latency is set directly on the swap chain,
5806    /// or waits on present are scheduled to avoid exceeding the maximum frame latency if supported,
5807    /// or the swap chain size is set to (max-latency + 1).
5808    ///
5809    /// Defaults to 2 when created via `wgpu::Surface::get_default_config`.
5810    ///
5811    /// Typical values range from 3 to 1, but higher values are possible:
5812    /// * Choose 2 or higher for potentially smoother frame display, as it allows to be at least one frame
5813    ///   to be queued up. This typically avoids starving the GPU's work queue.
5814    ///   Higher values are useful for achieving a constant flow of frames to the display under varying load.
5815    /// * Choose 1 for low latency from frame recording to frame display.
5816    ///   ⚠️ If the backend does not support waiting on present, this will cause the CPU to wait for the GPU
5817    ///   to finish all work related to the previous frame when calling `wgpu::Surface::get_current_texture`,
5818    ///   causing CPU-GPU serialization (i.e. when `wgpu::Surface::get_current_texture` returns, the GPU might be idle).
5819    ///   It is currently not possible to query this. See <https://github.com/gfx-rs/wgpu/issues/2869>.
5820    /// * A value of 0 is generally not supported and always clamped to a higher value.
5821    pub desired_maximum_frame_latency: u32,
5822    /// Specifies how the alpha channel of the textures should be handled during compositing.
5823    pub alpha_mode: CompositeAlphaMode,
5824    /// Specifies what view formats will be allowed when calling create_view() on texture returned by get_current_texture().
5825    ///
5826    /// View formats of the same format as the texture are always allowed.
5827    ///
5828    /// Note: currently, only the srgb-ness is allowed to change. (ex: Rgba8Unorm texture + Rgba8UnormSrgb view)
5829    pub view_formats: V,
5830}
5831
5832impl<V: Clone> SurfaceConfiguration<V> {
5833    /// Map view_formats of the texture descriptor into another.
5834    pub fn map_view_formats<M>(&self, fun: impl FnOnce(V) -> M) -> SurfaceConfiguration<M> {
5835        SurfaceConfiguration {
5836            usage: self.usage,
5837            format: self.format,
5838            width: self.width,
5839            height: self.height,
5840            present_mode: self.present_mode,
5841            desired_maximum_frame_latency: self.desired_maximum_frame_latency,
5842            alpha_mode: self.alpha_mode,
5843            view_formats: fun(self.view_formats.clone()),
5844        }
5845    }
5846}
5847
5848/// Status of the received surface image.
5849#[repr(C)]
5850#[derive(Debug)]
5851pub enum SurfaceStatus {
5852    /// No issues.
5853    Good,
5854    /// The swap chain is operational, but it does no longer perfectly
5855    /// match the surface. A re-configuration is needed.
5856    Suboptimal,
5857    /// Unable to get the next frame, timed out.
5858    Timeout,
5859    /// The surface under the swap chain has changed.
5860    Outdated,
5861    /// The surface under the swap chain is lost.
5862    Lost,
5863    /// The surface status is not known since `get_current_texture` previously failed.
5864    Unknown,
5865}
5866
5867/// Nanosecond timestamp used by the presentation engine.
5868///
5869/// The specific clock depends on the window system integration (WSI) API used.
5870///
5871/// <table>
5872/// <tr>
5873///     <td>WSI</td>
5874///     <td>Clock</td>
5875/// </tr>
5876/// <tr>
5877///     <td>IDXGISwapchain</td>
5878///     <td><a href="https://docs.microsoft.com/en-us/windows/win32/api/profileapi/nf-profileapi-queryperformancecounter">QueryPerformanceCounter</a></td>
5879/// </tr>
5880/// <tr>
5881///     <td>IPresentationManager</td>
5882///     <td><a href="https://docs.microsoft.com/en-us/windows/win32/api/realtimeapiset/nf-realtimeapiset-queryinterrupttimeprecise">QueryInterruptTimePrecise</a></td>
5883/// </tr>
5884/// <tr>
5885///     <td>CAMetalLayer</td>
5886///     <td><a href="https://developer.apple.com/documentation/kernel/1462446-mach_absolute_time">mach_absolute_time</a></td>
5887/// </tr>
5888/// <tr>
5889///     <td>VK_GOOGLE_display_timing</td>
5890///     <td><a href="https://linux.die.net/man/3/clock_gettime">clock_gettime(CLOCK_MONOTONIC)</a></td>
5891/// </tr>
5892/// </table>
5893#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
5894pub struct PresentationTimestamp(
5895    /// Timestamp in nanoseconds.
5896    pub u128,
5897);
5898
5899impl PresentationTimestamp {
5900    /// A timestamp that is invalid due to the platform not having a timestamp system.
5901    pub const INVALID_TIMESTAMP: Self = Self(u128::MAX);
5902
5903    /// Returns true if this timestamp is the invalid timestamp.
5904    #[must_use]
5905    pub fn is_invalid(self) -> bool {
5906        self == Self::INVALID_TIMESTAMP
5907    }
5908}
5909
5910/// RGBA double precision color.
5911///
5912/// This is not to be used as a generic color type, only for specific wgpu interfaces.
5913#[repr(C)]
5914#[derive(Clone, Copy, Debug, Default, PartialEq)]
5915#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
5916#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
5917pub struct Color {
5918    /// Red component of the color
5919    pub r: f64,
5920    /// Green component of the color
5921    pub g: f64,
5922    /// Blue component of the color
5923    pub b: f64,
5924    /// Alpha component of the color
5925    pub a: f64,
5926}
5927
5928#[allow(missing_docs)]
5929impl Color {
5930    pub const TRANSPARENT: Self = Self {
5931        r: 0.0,
5932        g: 0.0,
5933        b: 0.0,
5934        a: 0.0,
5935    };
5936    pub const BLACK: Self = Self {
5937        r: 0.0,
5938        g: 0.0,
5939        b: 0.0,
5940        a: 1.0,
5941    };
5942    pub const WHITE: Self = Self {
5943        r: 1.0,
5944        g: 1.0,
5945        b: 1.0,
5946        a: 1.0,
5947    };
5948    pub const RED: Self = Self {
5949        r: 1.0,
5950        g: 0.0,
5951        b: 0.0,
5952        a: 1.0,
5953    };
5954    pub const GREEN: Self = Self {
5955        r: 0.0,
5956        g: 1.0,
5957        b: 0.0,
5958        a: 1.0,
5959    };
5960    pub const BLUE: Self = Self {
5961        r: 0.0,
5962        g: 0.0,
5963        b: 1.0,
5964        a: 1.0,
5965    };
5966}
5967
5968/// Dimensionality of a texture.
5969///
5970/// Corresponds to [WebGPU `GPUTextureDimension`](
5971/// https://gpuweb.github.io/gpuweb/#enumdef-gputexturedimension).
5972#[repr(C)]
5973#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
5974#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5975pub enum TextureDimension {
5976    /// 1D texture
5977    #[cfg_attr(feature = "serde", serde(rename = "1d"))]
5978    D1,
5979    /// 2D texture
5980    #[cfg_attr(feature = "serde", serde(rename = "2d"))]
5981    D2,
5982    /// 3D texture
5983    #[cfg_attr(feature = "serde", serde(rename = "3d"))]
5984    D3,
5985}
5986
5987/// Origin of a copy from a 2D image.
5988///
5989/// Corresponds to [WebGPU `GPUOrigin2D`](
5990/// https://gpuweb.github.io/gpuweb/#dictdef-gpuorigin2ddict).
5991#[repr(C)]
5992#[derive(Clone, Copy, PartialEq, Eq, Hash)]
5993#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5994#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
5995pub struct Origin2d {
5996    #[allow(missing_docs)]
5997    pub x: u32,
5998    #[allow(missing_docs)]
5999    pub y: u32,
6000}
6001
6002impl Origin2d {
6003    /// Zero origin.
6004    pub const ZERO: Self = Self { x: 0, y: 0 };
6005
6006    /// Adds the third dimension to this origin
6007    #[must_use]
6008    pub fn to_3d(self, z: u32) -> Origin3d {
6009        Origin3d {
6010            x: self.x,
6011            y: self.y,
6012            z,
6013        }
6014    }
6015}
6016
6017impl core::fmt::Debug for Origin2d {
6018    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
6019        (self.x, self.y).fmt(f)
6020    }
6021}
6022
6023/// Origin of a copy to/from a texture.
6024///
6025/// Corresponds to [WebGPU `GPUOrigin3D`](
6026/// https://gpuweb.github.io/gpuweb/#dictdef-gpuorigin3ddict).
6027#[repr(C)]
6028#[derive(Clone, Copy, PartialEq, Eq, Hash)]
6029#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6030#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
6031pub struct Origin3d {
6032    /// X position of the origin
6033    pub x: u32,
6034    /// Y position of the origin
6035    pub y: u32,
6036    /// Z position of the origin
6037    pub z: u32,
6038}
6039
6040impl Origin3d {
6041    /// Zero origin.
6042    pub const ZERO: Self = Self { x: 0, y: 0, z: 0 };
6043
6044    /// Removes the third dimension from this origin
6045    #[must_use]
6046    pub fn to_2d(self) -> Origin2d {
6047        Origin2d {
6048            x: self.x,
6049            y: self.y,
6050        }
6051    }
6052}
6053
6054impl Default for Origin3d {
6055    fn default() -> Self {
6056        Self::ZERO
6057    }
6058}
6059
6060impl core::fmt::Debug for Origin3d {
6061    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
6062        (self.x, self.y, self.z).fmt(f)
6063    }
6064}
6065
6066/// Extent of a texture related operation.
6067///
6068/// Corresponds to [WebGPU `GPUExtent3D`](
6069/// https://gpuweb.github.io/gpuweb/#dictdef-gpuextent3ddict).
6070#[repr(C)]
6071#[derive(Clone, Copy, PartialEq, Eq, Hash)]
6072#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6073#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
6074pub struct Extent3d {
6075    /// Width of the extent
6076    pub width: u32,
6077    /// Height of the extent
6078    pub height: u32,
6079    /// The depth of the extent or the number of array layers
6080    #[cfg_attr(feature = "serde", serde(default = "default_depth"))]
6081    pub depth_or_array_layers: u32,
6082}
6083
6084impl core::fmt::Debug for Extent3d {
6085    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
6086        (self.width, self.height, self.depth_or_array_layers).fmt(f)
6087    }
6088}
6089
6090#[cfg(feature = "serde")]
6091fn default_depth() -> u32 {
6092    1
6093}
6094
6095impl Default for Extent3d {
6096    fn default() -> Self {
6097        Self {
6098            width: 1,
6099            height: 1,
6100            depth_or_array_layers: 1,
6101        }
6102    }
6103}
6104
6105impl Extent3d {
6106    /// Calculates the [physical size] backing a texture of the given
6107    /// format and extent.  This includes padding to the block width
6108    /// and height of the format.
6109    ///
6110    /// This is the texture extent that you must upload at when uploading to _mipmaps_ of compressed textures.
6111    ///
6112    /// [physical size]: https://gpuweb.github.io/gpuweb/#physical-miplevel-specific-texture-extent
6113    #[must_use]
6114    pub fn physical_size(&self, format: TextureFormat) -> Self {
6115        let (block_width, block_height) = format.block_dimensions();
6116
6117        let width = self.width.div_ceil(block_width) * block_width;
6118        let height = self.height.div_ceil(block_height) * block_height;
6119
6120        Self {
6121            width,
6122            height,
6123            depth_or_array_layers: self.depth_or_array_layers,
6124        }
6125    }
6126
6127    /// Calculates the maximum possible count of mipmaps.
6128    ///
6129    /// Treats the depth as part of the mipmaps. If calculating
6130    /// for a 2DArray texture, which does not mipmap depth, set depth to 1.
6131    #[must_use]
6132    pub fn max_mips(&self, dim: TextureDimension) -> u32 {
6133        match dim {
6134            TextureDimension::D1 => 1,
6135            TextureDimension::D2 => {
6136                let max_dim = self.width.max(self.height);
6137                32 - max_dim.leading_zeros()
6138            }
6139            TextureDimension::D3 => {
6140                let max_dim = self.width.max(self.height.max(self.depth_or_array_layers));
6141                32 - max_dim.leading_zeros()
6142            }
6143        }
6144    }
6145
6146    /// Calculates the extent at a given mip level.
6147    /// Does *not* account for memory size being a multiple of block size.
6148    ///
6149    /// <https://gpuweb.github.io/gpuweb/#logical-miplevel-specific-texture-extent>
6150    #[must_use]
6151    pub fn mip_level_size(&self, level: u32, dim: TextureDimension) -> Self {
6152        Self {
6153            width: u32::max(1, self.width >> level),
6154            height: match dim {
6155                TextureDimension::D1 => 1,
6156                _ => u32::max(1, self.height >> level),
6157            },
6158            depth_or_array_layers: match dim {
6159                TextureDimension::D1 => 1,
6160                TextureDimension::D2 => self.depth_or_array_layers,
6161                TextureDimension::D3 => u32::max(1, self.depth_or_array_layers >> level),
6162            },
6163        }
6164    }
6165}
6166
6167#[test]
6168fn test_physical_size() {
6169    let format = TextureFormat::Bc1RgbaUnormSrgb; // 4x4 blocks
6170    assert_eq!(
6171        Extent3d {
6172            width: 7,
6173            height: 7,
6174            depth_or_array_layers: 1
6175        }
6176        .physical_size(format),
6177        Extent3d {
6178            width: 8,
6179            height: 8,
6180            depth_or_array_layers: 1
6181        }
6182    );
6183    // Doesn't change, already aligned
6184    assert_eq!(
6185        Extent3d {
6186            width: 8,
6187            height: 8,
6188            depth_or_array_layers: 1
6189        }
6190        .physical_size(format),
6191        Extent3d {
6192            width: 8,
6193            height: 8,
6194            depth_or_array_layers: 1
6195        }
6196    );
6197    let format = TextureFormat::Astc {
6198        block: AstcBlock::B8x5,
6199        channel: AstcChannel::Unorm,
6200    }; // 8x5 blocks
6201    assert_eq!(
6202        Extent3d {
6203            width: 7,
6204            height: 7,
6205            depth_or_array_layers: 1
6206        }
6207        .physical_size(format),
6208        Extent3d {
6209            width: 8,
6210            height: 10,
6211            depth_or_array_layers: 1
6212        }
6213    );
6214}
6215
6216#[test]
6217fn test_max_mips() {
6218    // 1D
6219    assert_eq!(
6220        Extent3d {
6221            width: 240,
6222            height: 1,
6223            depth_or_array_layers: 1
6224        }
6225        .max_mips(TextureDimension::D1),
6226        1
6227    );
6228    // 2D
6229    assert_eq!(
6230        Extent3d {
6231            width: 1,
6232            height: 1,
6233            depth_or_array_layers: 1
6234        }
6235        .max_mips(TextureDimension::D2),
6236        1
6237    );
6238    assert_eq!(
6239        Extent3d {
6240            width: 60,
6241            height: 60,
6242            depth_or_array_layers: 1
6243        }
6244        .max_mips(TextureDimension::D2),
6245        6
6246    );
6247    assert_eq!(
6248        Extent3d {
6249            width: 240,
6250            height: 1,
6251            depth_or_array_layers: 1000
6252        }
6253        .max_mips(TextureDimension::D2),
6254        8
6255    );
6256    // 3D
6257    assert_eq!(
6258        Extent3d {
6259            width: 16,
6260            height: 30,
6261            depth_or_array_layers: 60
6262        }
6263        .max_mips(TextureDimension::D3),
6264        6
6265    );
6266}
6267
6268/// Describes a `TextureView`.
6269///
6270/// For use with `Texture::create_view`.
6271///
6272/// Corresponds to [WebGPU `GPUTextureViewDescriptor`](
6273/// https://gpuweb.github.io/gpuweb/#dictdef-gputextureviewdescriptor).
6274#[derive(Clone, Debug, Default, Eq, PartialEq)]
6275pub struct TextureViewDescriptor<L> {
6276    /// Debug label of the texture view. This will show up in graphics debuggers for easy identification.
6277    pub label: L,
6278    /// Format of the texture view. Either must be the same as the texture format or in the list
6279    /// of `view_formats` in the texture's descriptor.
6280    pub format: Option<TextureFormat>,
6281    /// The dimension of the texture view. For 1D textures, this must be `D1`. For 2D textures it must be one of
6282    /// `D2`, `D2Array`, `Cube`, and `CubeArray`. For 3D textures it must be `D3`
6283    pub dimension: Option<TextureViewDimension>,
6284    /// The allowed usage(s) for the texture view. Must be a subset of the usage flags of the texture.
6285    /// If not provided, defaults to the full set of usage flags of the texture.
6286    pub usage: Option<TextureUsages>,
6287    /// Aspect of the texture. Color textures must be [`TextureAspect::All`].
6288    pub aspect: TextureAspect,
6289    /// Base mip level.
6290    pub base_mip_level: u32,
6291    /// Mip level count.
6292    /// If `Some(count)`, `base_mip_level + count` must be less or equal to underlying texture mip count.
6293    /// If `None`, considered to include the rest of the mipmap levels, but at least 1 in total.
6294    pub mip_level_count: Option<u32>,
6295    /// Base array layer.
6296    pub base_array_layer: u32,
6297    /// Layer count.
6298    /// If `Some(count)`, `base_array_layer + count` must be less or equal to the underlying array count.
6299    /// If `None`, considered to include the rest of the array layers, but at least 1 in total.
6300    pub array_layer_count: Option<u32>,
6301}
6302
6303/// Describes a [`Texture`](../wgpu/struct.Texture.html).
6304///
6305/// Corresponds to [WebGPU `GPUTextureDescriptor`](
6306/// https://gpuweb.github.io/gpuweb/#dictdef-gputexturedescriptor).
6307#[repr(C)]
6308#[derive(Clone, Debug, PartialEq, Eq, Hash)]
6309#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6310pub struct TextureDescriptor<L, V> {
6311    /// Debug label of the texture. This will show up in graphics debuggers for easy identification.
6312    pub label: L,
6313    /// Size of the texture. All components must be greater than zero. For a
6314    /// regular 1D/2D texture, the unused sizes will be 1. For 2DArray textures,
6315    /// Z is the number of 2D textures in that array.
6316    pub size: Extent3d,
6317    /// Mip count of texture. For a texture with no extra mips, this must be 1.
6318    pub mip_level_count: u32,
6319    /// Sample count of texture. If this is not 1, texture must have [`BindingType::Texture::multisampled`] set to true.
6320    pub sample_count: u32,
6321    /// Dimensions of the texture.
6322    pub dimension: TextureDimension,
6323    /// Format of the texture.
6324    pub format: TextureFormat,
6325    /// Allowed usages of the texture. If used in other ways, the operation will panic.
6326    pub usage: TextureUsages,
6327    /// Specifies what view formats will be allowed when calling create_view() on this texture.
6328    ///
6329    /// View formats of the same format as the texture are always allowed.
6330    ///
6331    /// Note: currently, only the srgb-ness is allowed to change. (ex: Rgba8Unorm texture + Rgba8UnormSrgb view)
6332    pub view_formats: V,
6333}
6334
6335impl<L, V> TextureDescriptor<L, V> {
6336    /// Takes a closure and maps the label of the texture descriptor into another.
6337    #[must_use]
6338    pub fn map_label<K>(&self, fun: impl FnOnce(&L) -> K) -> TextureDescriptor<K, V>
6339    where
6340        V: Clone,
6341    {
6342        TextureDescriptor {
6343            label: fun(&self.label),
6344            size: self.size,
6345            mip_level_count: self.mip_level_count,
6346            sample_count: self.sample_count,
6347            dimension: self.dimension,
6348            format: self.format,
6349            usage: self.usage,
6350            view_formats: self.view_formats.clone(),
6351        }
6352    }
6353
6354    /// Maps the label and view_formats of the texture descriptor into another.
6355    #[must_use]
6356    pub fn map_label_and_view_formats<K, M>(
6357        &self,
6358        l_fun: impl FnOnce(&L) -> K,
6359        v_fun: impl FnOnce(V) -> M,
6360    ) -> TextureDescriptor<K, M>
6361    where
6362        V: Clone,
6363    {
6364        TextureDescriptor {
6365            label: l_fun(&self.label),
6366            size: self.size,
6367            mip_level_count: self.mip_level_count,
6368            sample_count: self.sample_count,
6369            dimension: self.dimension,
6370            format: self.format,
6371            usage: self.usage,
6372            view_formats: v_fun(self.view_formats.clone()),
6373        }
6374    }
6375
6376    /// Calculates the extent at a given mip level.
6377    ///
6378    /// If the given mip level is larger than possible, returns None.
6379    ///
6380    /// Treats the depth as part of the mipmaps. If calculating
6381    /// for a 2DArray texture, which does not mipmap depth, set depth to 1.
6382    ///
6383    /// ```rust
6384    /// # use wgpu_types as wgpu;
6385    /// # type TextureDescriptor<'a> = wgpu::TextureDescriptor<(), &'a [wgpu::TextureFormat]>;
6386    /// let desc  = TextureDescriptor {
6387    ///   label: (),
6388    ///   size: wgpu::Extent3d { width: 100, height: 60, depth_or_array_layers: 1 },
6389    ///   mip_level_count: 7,
6390    ///   sample_count: 1,
6391    ///   dimension: wgpu::TextureDimension::D3,
6392    ///   format: wgpu::TextureFormat::Rgba8Sint,
6393    ///   usage: wgpu::TextureUsages::empty(),
6394    ///   view_formats: &[],
6395    /// };
6396    ///
6397    /// assert_eq!(desc.mip_level_size(0), Some(wgpu::Extent3d { width: 100, height: 60, depth_or_array_layers: 1 }));
6398    /// assert_eq!(desc.mip_level_size(1), Some(wgpu::Extent3d { width: 50, height: 30, depth_or_array_layers: 1 }));
6399    /// assert_eq!(desc.mip_level_size(2), Some(wgpu::Extent3d { width: 25, height: 15, depth_or_array_layers: 1 }));
6400    /// assert_eq!(desc.mip_level_size(3), Some(wgpu::Extent3d { width: 12, height: 7, depth_or_array_layers: 1 }));
6401    /// assert_eq!(desc.mip_level_size(4), Some(wgpu::Extent3d { width: 6, height: 3, depth_or_array_layers: 1 }));
6402    /// assert_eq!(desc.mip_level_size(5), Some(wgpu::Extent3d { width: 3, height: 1, depth_or_array_layers: 1 }));
6403    /// assert_eq!(desc.mip_level_size(6), Some(wgpu::Extent3d { width: 1, height: 1, depth_or_array_layers: 1 }));
6404    /// assert_eq!(desc.mip_level_size(7), None);
6405    /// ```
6406    #[must_use]
6407    pub fn mip_level_size(&self, level: u32) -> Option<Extent3d> {
6408        if level >= self.mip_level_count {
6409            return None;
6410        }
6411
6412        Some(self.size.mip_level_size(level, self.dimension))
6413    }
6414
6415    /// Computes the render extent of this texture.
6416    ///
6417    /// <https://gpuweb.github.io/gpuweb/#abstract-opdef-compute-render-extent>
6418    #[must_use]
6419    pub fn compute_render_extent(&self, mip_level: u32) -> Extent3d {
6420        Extent3d {
6421            width: u32::max(1, self.size.width >> mip_level),
6422            height: u32::max(1, self.size.height >> mip_level),
6423            depth_or_array_layers: 1,
6424        }
6425    }
6426
6427    /// Returns the number of array layers.
6428    ///
6429    /// <https://gpuweb.github.io/gpuweb/#abstract-opdef-array-layer-count>
6430    #[must_use]
6431    pub fn array_layer_count(&self) -> u32 {
6432        match self.dimension {
6433            TextureDimension::D1 | TextureDimension::D3 => 1,
6434            TextureDimension::D2 => self.size.depth_or_array_layers,
6435        }
6436    }
6437}
6438
6439/// Describes a `Sampler`.
6440///
6441/// For use with `Device::create_sampler`.
6442///
6443/// Corresponds to [WebGPU `GPUSamplerDescriptor`](
6444/// https://gpuweb.github.io/gpuweb/#dictdef-gpusamplerdescriptor).
6445#[derive(Clone, Debug, PartialEq)]
6446#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6447pub struct SamplerDescriptor<L> {
6448    /// Debug label of the sampler. This will show up in graphics debuggers for easy identification.
6449    pub label: L,
6450    /// How to deal with out of bounds accesses in the u (i.e. x) direction
6451    pub address_mode_u: AddressMode,
6452    /// How to deal with out of bounds accesses in the v (i.e. y) direction
6453    pub address_mode_v: AddressMode,
6454    /// How to deal with out of bounds accesses in the w (i.e. z) direction
6455    pub address_mode_w: AddressMode,
6456    /// How to filter the texture when it needs to be magnified (made larger)
6457    pub mag_filter: FilterMode,
6458    /// How to filter the texture when it needs to be minified (made smaller)
6459    pub min_filter: FilterMode,
6460    /// How to filter between mip map levels
6461    pub mipmap_filter: FilterMode,
6462    /// Minimum level of detail (i.e. mip level) to use
6463    pub lod_min_clamp: f32,
6464    /// Maximum level of detail (i.e. mip level) to use
6465    pub lod_max_clamp: f32,
6466    /// If this is enabled, this is a comparison sampler using the given comparison function.
6467    pub compare: Option<CompareFunction>,
6468    /// Must be at least 1. If this is not 1, all filter modes must be linear.
6469    pub anisotropy_clamp: u16,
6470    /// Border color to use when address_mode is [`AddressMode::ClampToBorder`]
6471    pub border_color: Option<SamplerBorderColor>,
6472}
6473
6474impl<L: Default> Default for SamplerDescriptor<L> {
6475    fn default() -> Self {
6476        Self {
6477            label: Default::default(),
6478            address_mode_u: Default::default(),
6479            address_mode_v: Default::default(),
6480            address_mode_w: Default::default(),
6481            mag_filter: Default::default(),
6482            min_filter: Default::default(),
6483            mipmap_filter: Default::default(),
6484            lod_min_clamp: 0.0,
6485            lod_max_clamp: 32.0,
6486            compare: None,
6487            anisotropy_clamp: 1,
6488            border_color: None,
6489        }
6490    }
6491}
6492
6493/// Kind of data the texture holds.
6494///
6495/// Corresponds to [WebGPU `GPUTextureAspect`](
6496/// https://gpuweb.github.io/gpuweb/#enumdef-gputextureaspect).
6497#[repr(C)]
6498#[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq)]
6499#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6500#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
6501pub enum TextureAspect {
6502    /// Depth, Stencil, and Color.
6503    #[default]
6504    All,
6505    /// Stencil.
6506    StencilOnly,
6507    /// Depth.
6508    DepthOnly,
6509    /// Plane 0.
6510    Plane0,
6511    /// Plane 1.
6512    Plane1,
6513    /// Plane 2.
6514    Plane2,
6515}
6516
6517/// How edges should be handled in texture addressing.
6518///
6519/// Corresponds to [WebGPU `GPUAddressMode`](
6520/// https://gpuweb.github.io/gpuweb/#enumdef-gpuaddressmode).
6521#[repr(C)]
6522#[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq)]
6523#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6524#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
6525pub enum AddressMode {
6526    /// Clamp the value to the edge of the texture
6527    ///
6528    /// -0.25 -> 0.0
6529    /// 1.25  -> 1.0
6530    #[default]
6531    ClampToEdge = 0,
6532    /// Repeat the texture in a tiling fashion
6533    ///
6534    /// -0.25 -> 0.75
6535    /// 1.25 -> 0.25
6536    Repeat = 1,
6537    /// Repeat the texture, mirroring it every repeat
6538    ///
6539    /// -0.25 -> 0.25
6540    /// 1.25 -> 0.75
6541    MirrorRepeat = 2,
6542    /// Clamp the value to the border of the texture
6543    /// Requires feature [`Features::ADDRESS_MODE_CLAMP_TO_BORDER`]
6544    ///
6545    /// -0.25 -> border
6546    /// 1.25 -> border
6547    ClampToBorder = 3,
6548}
6549
6550/// Texel mixing mode when sampling between texels.
6551///
6552/// Corresponds to [WebGPU `GPUFilterMode`](
6553/// https://gpuweb.github.io/gpuweb/#enumdef-gpufiltermode).
6554#[repr(C)]
6555#[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq)]
6556#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6557#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
6558pub enum FilterMode {
6559    /// Nearest neighbor sampling.
6560    ///
6561    /// This creates a pixelated effect when used as a mag filter
6562    #[default]
6563    Nearest = 0,
6564    /// Linear Interpolation
6565    ///
6566    /// This makes textures smooth but blurry when used as a mag filter.
6567    Linear = 1,
6568}
6569
6570/// A range of push constant memory to pass to a shader stage.
6571#[derive(Clone, Debug, PartialEq, Eq, Hash)]
6572#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6573pub struct PushConstantRange {
6574    /// Stage push constant range is visible from. Each stage can only be served by at most one range.
6575    /// One range can serve multiple stages however.
6576    pub stages: ShaderStages,
6577    /// Range in push constant memory to use for the stage. Must be less than [`Limits::max_push_constant_size`].
6578    /// Start and end must be aligned to the 4s.
6579    pub range: Range<u32>,
6580}
6581
6582/// Describes a [`CommandBuffer`](../wgpu/struct.CommandBuffer.html).
6583///
6584/// Corresponds to [WebGPU `GPUCommandBufferDescriptor`](
6585/// https://gpuweb.github.io/gpuweb/#dictdef-gpucommandbufferdescriptor).
6586#[repr(C)]
6587#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
6588#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6589pub struct CommandBufferDescriptor<L> {
6590    /// Debug label of this command buffer.
6591    pub label: L,
6592}
6593
6594impl<L> CommandBufferDescriptor<L> {
6595    /// Takes a closure and maps the label of the command buffer descriptor into another.
6596    #[must_use]
6597    pub fn map_label<K>(&self, fun: impl FnOnce(&L) -> K) -> CommandBufferDescriptor<K> {
6598        CommandBufferDescriptor {
6599            label: fun(&self.label),
6600        }
6601    }
6602}
6603
6604/// Describes the depth/stencil attachment for render bundles.
6605///
6606/// Corresponds to a portion of [WebGPU `GPURenderBundleEncoderDescriptor`](
6607/// https://gpuweb.github.io/gpuweb/#dictdef-gpurenderbundleencoderdescriptor).
6608#[repr(C)]
6609#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
6610#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
6611pub struct RenderBundleDepthStencil {
6612    /// Format of the attachment.
6613    pub format: TextureFormat,
6614    /// If the depth aspect of the depth stencil attachment is going to be written to.
6615    ///
6616    /// This must match the [`RenderPassDepthStencilAttachment::depth_ops`] of the renderpass this render bundle is executed in.
6617    /// If depth_ops is `Some(..)` this must be false. If it is `None` this must be true.
6618    ///
6619    /// [`RenderPassDepthStencilAttachment::depth_ops`]: ../wgpu/struct.RenderPassDepthStencilAttachment.html#structfield.depth_ops
6620    pub depth_read_only: bool,
6621
6622    /// If the stencil aspect of the depth stencil attachment is going to be written to.
6623    ///
6624    /// This must match the [`RenderPassDepthStencilAttachment::stencil_ops`] of the renderpass this render bundle is executed in.
6625    /// If depth_ops is `Some(..)` this must be false. If it is `None` this must be true.
6626    ///
6627    /// [`RenderPassDepthStencilAttachment::stencil_ops`]: ../wgpu/struct.RenderPassDepthStencilAttachment.html#structfield.stencil_ops
6628    pub stencil_read_only: bool,
6629}
6630
6631/// Describes a [`RenderBundle`](../wgpu/struct.RenderBundle.html).
6632///
6633/// Corresponds to [WebGPU `GPURenderBundleDescriptor`](
6634/// https://gpuweb.github.io/gpuweb/#dictdef-gpurenderbundledescriptor).
6635#[repr(C)]
6636#[derive(Clone, Debug, PartialEq, Eq, Hash)]
6637#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6638pub struct RenderBundleDescriptor<L> {
6639    /// Debug label of the render bundle encoder. This will show up in graphics debuggers for easy identification.
6640    pub label: L,
6641}
6642
6643impl<L> RenderBundleDescriptor<L> {
6644    /// Takes a closure and maps the label of the render bundle descriptor into another.
6645    #[must_use]
6646    pub fn map_label<K>(&self, fun: impl FnOnce(&L) -> K) -> RenderBundleDescriptor<K> {
6647        RenderBundleDescriptor {
6648            label: fun(&self.label),
6649        }
6650    }
6651}
6652
6653impl<T> Default for RenderBundleDescriptor<Option<T>> {
6654    fn default() -> Self {
6655        Self { label: None }
6656    }
6657}
6658
6659/// Layout of a texture in a buffer's memory.
6660///
6661/// The bytes per row and rows per image can be hard to figure out so here are some examples:
6662///
6663/// | Resolution | Format | Bytes per block | Pixels per block | Bytes per row                          | Rows per image               |
6664/// |------------|--------|-----------------|------------------|----------------------------------------|------------------------------|
6665/// | 256x256    | RGBA8  | 4               | 1 * 1 * 1        | 256 * 4 = Some(1024)                   | None                         |
6666/// | 32x16x8    | RGBA8  | 4               | 1 * 1 * 1        | 32 * 4 = 128 padded to 256 = Some(256) | None                         |
6667/// | 256x256    | BC3    | 16              | 4 * 4 * 1        | 16 * (256 / 4) = 1024 = Some(1024)     | None                         |
6668/// | 64x64x8    | BC3    | 16              | 4 * 4 * 1        | 16 * (64 / 4) = 256 = Some(256)        | 64 / 4 = 16 = Some(16)       |
6669///
6670/// Corresponds to [WebGPU `GPUTexelCopyBufferLayout`](
6671/// https://gpuweb.github.io/gpuweb/#dictdef-gpuimagedatalayout).
6672#[repr(C)]
6673#[derive(Clone, Copy, Debug, Default)]
6674#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
6675pub struct TexelCopyBufferLayout {
6676    /// Offset into the buffer that is the start of the texture. Must be a multiple of texture block size.
6677    /// For non-compressed textures, this is 1.
6678    pub offset: BufferAddress,
6679    /// Bytes per "row" in an image.
6680    ///
6681    /// A row is one row of pixels or of compressed blocks in the x direction.
6682    ///
6683    /// This value is required if there are multiple rows (i.e. height or depth is more than one pixel or pixel block for compressed textures)
6684    ///
6685    /// Must be a multiple of 256 for [`CommandEncoder::copy_buffer_to_texture`][CEcbtt]
6686    /// and [`CommandEncoder::copy_texture_to_buffer`][CEcttb]. You must manually pad the
6687    /// image such that this is a multiple of 256. It will not affect the image data.
6688    ///
6689    /// [`Queue::write_texture`][Qwt] does not have this requirement.
6690    ///
6691    /// Must be a multiple of the texture block size. For non-compressed textures, this is 1.
6692    ///
6693    /// [CEcbtt]: ../wgpu/struct.CommandEncoder.html#method.copy_buffer_to_texture
6694    /// [CEcttb]: ../wgpu/struct.CommandEncoder.html#method.copy_texture_to_buffer
6695    /// [Qwt]: ../wgpu/struct.Queue.html#method.write_texture
6696    pub bytes_per_row: Option<u32>,
6697    /// "Rows" that make up a single "image".
6698    ///
6699    /// A row is one row of pixels or of compressed blocks in the x direction.
6700    ///
6701    /// An image is one layer in the z direction of a 3D image or 2DArray texture.
6702    ///
6703    /// The amount of rows per image may be larger than the actual amount of rows of data.
6704    ///
6705    /// Required if there are multiple images (i.e. the depth is more than one).
6706    pub rows_per_image: Option<u32>,
6707}
6708
6709/// Old name for a [`TexelCopyBufferLayout`].
6710#[deprecated(
6711    since = "24.0.0",
6712    note = "This has been renamed to `TexelCopyBufferLayout`, and will be removed in 25.0.0."
6713)]
6714pub type ImageDataLayout = TexelCopyBufferLayout;
6715
6716/// Specific type of a buffer binding.
6717///
6718/// Corresponds to [WebGPU `GPUBufferBindingType`](
6719/// https://gpuweb.github.io/gpuweb/#enumdef-gpubufferbindingtype).
6720#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Hash)]
6721#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6722pub enum BufferBindingType {
6723    /// A buffer for uniform values.
6724    ///
6725    /// Example WGSL syntax:
6726    /// ```rust,ignore
6727    /// struct Globals {
6728    ///     a_uniform: vec2<f32>,
6729    ///     another_uniform: vec2<f32>,
6730    /// }
6731    /// @group(0) @binding(0)
6732    /// var<uniform> globals: Globals;
6733    /// ```
6734    ///
6735    /// Example GLSL syntax:
6736    /// ```cpp,ignore
6737    /// layout(std140, binding = 0)
6738    /// uniform Globals {
6739    ///     vec2 aUniform;
6740    ///     vec2 anotherUniform;
6741    /// };
6742    /// ```
6743    #[default]
6744    Uniform,
6745    /// A storage buffer.
6746    ///
6747    /// Example WGSL syntax:
6748    /// ```rust,ignore
6749    /// @group(0) @binding(0)
6750    /// var<storage, read_write> my_element: array<vec4<f32>>;
6751    /// ```
6752    ///
6753    /// Example GLSL syntax:
6754    /// ```cpp,ignore
6755    /// layout (set=0, binding=0) buffer myStorageBuffer {
6756    ///     vec4 myElement[];
6757    /// };
6758    /// ```
6759    Storage {
6760        /// If `true`, the buffer can only be read in the shader,
6761        /// and it:
6762        /// - may or may not be annotated with `read` (WGSL).
6763        /// - must be annotated with `readonly` (GLSL).
6764        ///
6765        /// Example WGSL syntax:
6766        /// ```rust,ignore
6767        /// @group(0) @binding(0)
6768        /// var<storage, read> my_element: array<vec4<f32>>;
6769        /// ```
6770        ///
6771        /// Example GLSL syntax:
6772        /// ```cpp,ignore
6773        /// layout (set=0, binding=0) readonly buffer myStorageBuffer {
6774        ///     vec4 myElement[];
6775        /// };
6776        /// ```
6777        read_only: bool,
6778    },
6779}
6780
6781/// Specific type of a sample in a texture binding.
6782///
6783/// Corresponds to [WebGPU `GPUTextureSampleType`](
6784/// https://gpuweb.github.io/gpuweb/#enumdef-gputexturesampletype).
6785#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
6786#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6787pub enum TextureSampleType {
6788    /// Sampling returns floats.
6789    ///
6790    /// Example WGSL syntax:
6791    /// ```rust,ignore
6792    /// @group(0) @binding(0)
6793    /// var t: texture_2d<f32>;
6794    /// ```
6795    ///
6796    /// Example GLSL syntax:
6797    /// ```cpp,ignore
6798    /// layout(binding = 0)
6799    /// uniform texture2D t;
6800    /// ```
6801    Float {
6802        /// If this is `false`, the texture can't be sampled with
6803        /// a filtering sampler.
6804        ///
6805        /// Even if this is `true`, it's possible to sample with
6806        /// a **non-filtering** sampler.
6807        filterable: bool,
6808    },
6809    /// Sampling does the depth reference comparison.
6810    ///
6811    /// This is also compatible with a non-filtering sampler.
6812    ///
6813    /// Example WGSL syntax:
6814    /// ```rust,ignore
6815    /// @group(0) @binding(0)
6816    /// var t: texture_depth_2d;
6817    /// ```
6818    ///
6819    /// Example GLSL syntax:
6820    /// ```cpp,ignore
6821    /// layout(binding = 0)
6822    /// uniform texture2DShadow t;
6823    /// ```
6824    Depth,
6825    /// Sampling returns signed integers.
6826    ///
6827    /// Example WGSL syntax:
6828    /// ```rust,ignore
6829    /// @group(0) @binding(0)
6830    /// var t: texture_2d<i32>;
6831    /// ```
6832    ///
6833    /// Example GLSL syntax:
6834    /// ```cpp,ignore
6835    /// layout(binding = 0)
6836    /// uniform itexture2D t;
6837    /// ```
6838    Sint,
6839    /// Sampling returns unsigned integers.
6840    ///
6841    /// Example WGSL syntax:
6842    /// ```rust,ignore
6843    /// @group(0) @binding(0)
6844    /// var t: texture_2d<u32>;
6845    /// ```
6846    ///
6847    /// Example GLSL syntax:
6848    /// ```cpp,ignore
6849    /// layout(binding = 0)
6850    /// uniform utexture2D t;
6851    /// ```
6852    Uint,
6853}
6854
6855impl Default for TextureSampleType {
6856    fn default() -> Self {
6857        Self::Float { filterable: true }
6858    }
6859}
6860
6861/// Specific type of a sample in a texture binding.
6862///
6863/// For use in [`BindingType::StorageTexture`].
6864///
6865/// Corresponds to [WebGPU `GPUStorageTextureAccess`](
6866/// https://gpuweb.github.io/gpuweb/#enumdef-gpustoragetextureaccess).
6867#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
6868#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6869#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
6870pub enum StorageTextureAccess {
6871    /// The texture can only be written in the shader and it:
6872    /// - may or may not be annotated with `write` (WGSL).
6873    /// - must be annotated with `writeonly` (GLSL).
6874    ///
6875    /// Example WGSL syntax:
6876    /// ```rust,ignore
6877    /// @group(0) @binding(0)
6878    /// var my_storage_image: texture_storage_2d<r32float, write>;
6879    /// ```
6880    ///
6881    /// Example GLSL syntax:
6882    /// ```cpp,ignore
6883    /// layout(set=0, binding=0, r32f) writeonly uniform image2D myStorageImage;
6884    /// ```
6885    WriteOnly,
6886    /// The texture can only be read in the shader and it must be annotated with `read` (WGSL) or
6887    /// `readonly` (GLSL).
6888    ///
6889    /// [`Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES`] must be enabled to use this access
6890    /// mode. This is a native-only extension.
6891    ///
6892    /// Example WGSL syntax:
6893    /// ```rust,ignore
6894    /// @group(0) @binding(0)
6895    /// var my_storage_image: texture_storage_2d<r32float, read>;
6896    /// ```
6897    ///
6898    /// Example GLSL syntax:
6899    /// ```cpp,ignore
6900    /// layout(set=0, binding=0, r32f) readonly uniform image2D myStorageImage;
6901    /// ```
6902    ReadOnly,
6903    /// The texture can be both read and written in the shader and must be annotated with
6904    /// `read_write` in WGSL.
6905    ///
6906    /// [`Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES`] must be enabled to use this access
6907    /// mode.  This is a nonstandard, native-only extension.
6908    ///
6909    /// Example WGSL syntax:
6910    /// ```rust,ignore
6911    /// @group(0) @binding(0)
6912    /// var my_storage_image: texture_storage_2d<r32float, read_write>;
6913    /// ```
6914    ///
6915    /// Example GLSL syntax:
6916    /// ```cpp,ignore
6917    /// layout(set=0, binding=0, r32f) uniform image2D myStorageImage;
6918    /// ```
6919    ReadWrite,
6920    /// The texture can be both read and written in the shader via atomics and must be annotated
6921    /// with `read_write` in WGSL.
6922    ///
6923    /// [`Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES`] must be enabled to use this access
6924    /// mode.  This is a nonstandard, native-only extension.
6925    ///
6926    /// Example WGSL syntax:
6927    /// ```rust,ignore
6928    /// @group(0) @binding(0)
6929    /// var my_storage_image: texture_storage_2d<r32uint, atomic>;
6930    /// ```
6931    Atomic,
6932}
6933
6934/// Specific type of a sampler binding.
6935///
6936/// For use in [`BindingType::Sampler`].
6937///
6938/// Corresponds to [WebGPU `GPUSamplerBindingType`](
6939/// https://gpuweb.github.io/gpuweb/#enumdef-gpusamplerbindingtype).
6940#[repr(C)]
6941#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
6942#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6943#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
6944pub enum SamplerBindingType {
6945    /// The sampling result is produced based on more than a single color sample from a texture,
6946    /// e.g. when bilinear interpolation is enabled.
6947    Filtering,
6948    /// The sampling result is produced based on a single color sample from a texture.
6949    NonFiltering,
6950    /// Use as a comparison sampler instead of a normal sampler.
6951    /// For more info take a look at the analogous functionality in OpenGL: <https://www.khronos.org/opengl/wiki/Sampler_Object#Comparison_mode>.
6952    Comparison,
6953}
6954
6955/// Specific type of a binding.
6956///
6957/// For use in [`BindGroupLayoutEntry`].
6958///
6959/// Corresponds to WebGPU's mutually exclusive fields within [`GPUBindGroupLayoutEntry`](
6960/// https://gpuweb.github.io/gpuweb/#dictdef-gpubindgrouplayoutentry).
6961#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
6962#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6963pub enum BindingType {
6964    /// A buffer binding.
6965    ///
6966    /// Corresponds to [WebGPU `GPUBufferBindingLayout`](
6967    /// https://gpuweb.github.io/gpuweb/#dictdef-gpubufferbindinglayout).
6968    Buffer {
6969        /// Sub-type of the buffer binding.
6970        ty: BufferBindingType,
6971
6972        /// Indicates that the binding has a dynamic offset.
6973        ///
6974        /// One offset must be passed to [`RenderPass::set_bind_group`][RPsbg]
6975        /// for each dynamic binding in increasing order of binding number.
6976        ///
6977        /// [RPsbg]: ../wgpu/struct.RenderPass.html#method.set_bind_group
6978        #[cfg_attr(feature = "serde", serde(default))]
6979        has_dynamic_offset: bool,
6980
6981        /// The minimum size for a [`BufferBinding`] matching this entry, in bytes.
6982        ///
6983        /// If this is `Some(size)`:
6984        ///
6985        /// - When calling [`create_bind_group`], the resource at this bind point
6986        ///   must be a [`BindingResource::Buffer`] whose effective size is at
6987        ///   least `size`.
6988        ///
6989        /// - When calling [`create_render_pipeline`] or [`create_compute_pipeline`],
6990        ///   `size` must be at least the [minimum buffer binding size] for the
6991        ///   shader module global at this bind point: large enough to hold the
6992        ///   global's value, along with one element of a trailing runtime-sized
6993        ///   array, if present.
6994        ///
6995        /// If this is `None`:
6996        ///
6997        /// - Each draw or dispatch command checks that the buffer range at this
6998        ///   bind point satisfies the [minimum buffer binding size].
6999        ///
7000        /// [`BufferBinding`]: ../wgpu/struct.BufferBinding.html
7001        /// [`create_bind_group`]: ../wgpu/struct.Device.html#method.create_bind_group
7002        /// [`BindingResource::Buffer`]: ../wgpu/enum.BindingResource.html#variant.Buffer
7003        /// [minimum buffer binding size]: https://www.w3.org/TR/webgpu/#minimum-buffer-binding-size
7004        /// [`create_render_pipeline`]: ../wgpu/struct.Device.html#method.create_render_pipeline
7005        /// [`create_compute_pipeline`]: ../wgpu/struct.Device.html#method.create_compute_pipeline
7006        #[cfg_attr(feature = "serde", serde(default))]
7007        min_binding_size: Option<BufferSize>,
7008    },
7009    /// A sampler that can be used to sample a texture.
7010    ///
7011    /// Example WGSL syntax:
7012    /// ```rust,ignore
7013    /// @group(0) @binding(0)
7014    /// var s: sampler;
7015    /// ```
7016    ///
7017    /// Example GLSL syntax:
7018    /// ```cpp,ignore
7019    /// layout(binding = 0)
7020    /// uniform sampler s;
7021    /// ```
7022    ///
7023    /// Corresponds to [WebGPU `GPUSamplerBindingLayout`](
7024    /// https://gpuweb.github.io/gpuweb/#dictdef-gpusamplerbindinglayout).
7025    Sampler(SamplerBindingType),
7026    /// A texture binding.
7027    ///
7028    /// Example WGSL syntax:
7029    /// ```rust,ignore
7030    /// @group(0) @binding(0)
7031    /// var t: texture_2d<f32>;
7032    /// ```
7033    ///
7034    /// Example GLSL syntax:
7035    /// ```cpp,ignore
7036    /// layout(binding = 0)
7037    /// uniform texture2D t;
7038    /// ```
7039    ///
7040    /// Corresponds to [WebGPU `GPUTextureBindingLayout`](
7041    /// https://gpuweb.github.io/gpuweb/#dictdef-gputexturebindinglayout).
7042    Texture {
7043        /// Sample type of the texture binding.
7044        sample_type: TextureSampleType,
7045        /// Dimension of the texture view that is going to be sampled.
7046        view_dimension: TextureViewDimension,
7047        /// True if the texture has a sample count greater than 1. If this is true,
7048        /// the texture must be declared as `texture_multisampled_2d` or
7049        /// `texture_depth_multisampled_2d` in the shader, and read using `textureLoad`.
7050        multisampled: bool,
7051    },
7052    /// A storage texture.
7053    ///
7054    /// Example WGSL syntax:
7055    /// ```rust,ignore
7056    /// @group(0) @binding(0)
7057    /// var my_storage_image: texture_storage_2d<r32float, write>;
7058    /// ```
7059    ///
7060    /// Example GLSL syntax:
7061    /// ```cpp,ignore
7062    /// layout(set=0, binding=0, r32f) writeonly uniform image2D myStorageImage;
7063    /// ```
7064    /// Note that the texture format must be specified in the shader, along with the
7065    /// access mode. For WGSL, the format must be one of the enumerants in the list
7066    /// of [storage texel formats](https://gpuweb.github.io/gpuweb/wgsl/#storage-texel-formats).
7067    ///
7068    /// Corresponds to [WebGPU `GPUStorageTextureBindingLayout`](
7069    /// https://gpuweb.github.io/gpuweb/#dictdef-gpustoragetexturebindinglayout).
7070    StorageTexture {
7071        /// Allowed access to this texture.
7072        access: StorageTextureAccess,
7073        /// Format of the texture.
7074        format: TextureFormat,
7075        /// Dimension of the texture view that is going to be sampled.
7076        view_dimension: TextureViewDimension,
7077    },
7078
7079    /// A ray-tracing acceleration structure binding.
7080    ///
7081    /// Example WGSL syntax:
7082    /// ```rust,ignore
7083    /// @group(0) @binding(0)
7084    /// var as: acceleration_structure;
7085    /// ```
7086    ///
7087    /// Example GLSL syntax:
7088    /// ```cpp,ignore
7089    /// layout(binding = 0)
7090    /// uniform accelerationStructureEXT as;
7091    /// ```
7092    AccelerationStructure,
7093}
7094
7095impl BindingType {
7096    /// Returns true for buffer bindings with dynamic offset enabled.
7097    #[must_use]
7098    pub fn has_dynamic_offset(&self) -> bool {
7099        match *self {
7100            Self::Buffer {
7101                has_dynamic_offset, ..
7102            } => has_dynamic_offset,
7103            _ => false,
7104        }
7105    }
7106}
7107
7108/// Describes a single binding inside a bind group.
7109///
7110/// Corresponds to [WebGPU `GPUBindGroupLayoutEntry`](
7111/// https://gpuweb.github.io/gpuweb/#dictdef-gpubindgrouplayoutentry).
7112#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
7113#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7114pub struct BindGroupLayoutEntry {
7115    /// Binding index. Must match shader index and be unique inside a BindGroupLayout. A binding
7116    /// of index 1, would be described as `layout(set = 0, binding = 1) uniform` in shaders.
7117    pub binding: u32,
7118    /// Which shader stages can see this binding.
7119    pub visibility: ShaderStages,
7120    /// The type of the binding
7121    pub ty: BindingType,
7122    /// If this value is Some, indicates this entry is an array. Array size must be 1 or greater.
7123    ///
7124    /// If this value is Some and `ty` is `BindingType::Texture`, [`Features::TEXTURE_BINDING_ARRAY`] must be supported.
7125    ///
7126    /// If this value is Some and `ty` is any other variant, bind group creation will fail.
7127    #[cfg_attr(feature = "serde", serde(default))]
7128    pub count: Option<NonZeroU32>,
7129}
7130
7131/// View of a buffer which can be used to copy to/from a texture.
7132///
7133/// Corresponds to [WebGPU `GPUTexelCopyBufferInfo`](
7134/// https://gpuweb.github.io/gpuweb/#dictdef-gpuimagecopybuffer).
7135#[repr(C)]
7136#[derive(Copy, Clone, Debug)]
7137#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7138pub struct TexelCopyBufferInfo<B> {
7139    /// The buffer to be copied to/from.
7140    pub buffer: B,
7141    /// The layout of the texture data in this buffer.
7142    pub layout: TexelCopyBufferLayout,
7143}
7144
7145/// Old name for a [`TexelCopyBufferInfo`].
7146#[deprecated(
7147    since = "24.0.0",
7148    note = "This has been renamed to `TexelCopyBufferInfo`, and will be removed in 25.0.0."
7149)]
7150pub type ImageCopyBuffer<B> = TexelCopyBufferInfo<B>;
7151
7152/// View of a texture which can be used to copy to/from a buffer/texture.
7153///
7154/// Corresponds to [WebGPU `GPUTexelCopyTextureInfo`](
7155/// https://gpuweb.github.io/gpuweb/#dictdef-gpuimagecopytexture).
7156#[repr(C)]
7157#[derive(Copy, Clone, Debug)]
7158#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7159pub struct TexelCopyTextureInfo<T> {
7160    /// The texture to be copied to/from.
7161    pub texture: T,
7162    /// The target mip level of the texture.
7163    pub mip_level: u32,
7164    /// The base texel of the texture in the selected `mip_level`. Together
7165    /// with the `copy_size` argument to copy functions, defines the
7166    /// sub-region of the texture to copy.
7167    #[cfg_attr(feature = "serde", serde(default))]
7168    pub origin: Origin3d,
7169    /// The copy aspect.
7170    #[cfg_attr(feature = "serde", serde(default))]
7171    pub aspect: TextureAspect,
7172}
7173
7174impl<T> TexelCopyTextureInfo<T> {
7175    /// Adds color space and premultiplied alpha information to make this
7176    /// descriptor tagged.
7177    pub fn to_tagged(
7178        self,
7179        color_space: PredefinedColorSpace,
7180        premultiplied_alpha: bool,
7181    ) -> CopyExternalImageDestInfo<T> {
7182        CopyExternalImageDestInfo {
7183            texture: self.texture,
7184            mip_level: self.mip_level,
7185            origin: self.origin,
7186            aspect: self.aspect,
7187            color_space,
7188            premultiplied_alpha,
7189        }
7190    }
7191}
7192
7193/// Old name for a [`TexelCopyTextureInfo`].
7194#[deprecated(
7195    since = "24.0.0",
7196    note = "This has been renamed to `TexelCopyTextureInfo`, and will be removed in 25.0.0."
7197)]
7198pub type ImageCopyTexture<T> = TexelCopyTextureInfo<T>;
7199
7200/// View of an external texture that can be used to copy to a texture.
7201///
7202/// Corresponds to [WebGPU `GPUCopyExternalImageSourceInfo`](
7203/// https://gpuweb.github.io/gpuweb/#dictdef-gpuimagecopyexternalimage).
7204#[cfg(target_arch = "wasm32")]
7205#[derive(Clone, Debug)]
7206pub struct CopyExternalImageSourceInfo {
7207    /// The texture to be copied from. The copy source data is captured at the moment
7208    /// the copy is issued.
7209    pub source: ExternalImageSource,
7210    /// The base texel used for copying from the external image. Together
7211    /// with the `copy_size` argument to copy functions, defines the
7212    /// sub-region of the image to copy.
7213    ///
7214    /// Relative to the top left of the image.
7215    ///
7216    /// Must be [`Origin2d::ZERO`] if [`DownlevelFlags::UNRESTRICTED_EXTERNAL_TEXTURE_COPIES`] is not supported.
7217    pub origin: Origin2d,
7218    /// If the Y coordinate of the image should be flipped. Even if this is
7219    /// true, `origin` is still relative to the top left.
7220    pub flip_y: bool,
7221}
7222
7223/// Old name for a [`CopyExternalImageSourceInfo`].
7224#[deprecated(
7225    since = "24.0.0",
7226    note = "This has been renamed to `CopyExternalImageSourceInfo`, and will be removed in 25.0.0."
7227)]
7228#[cfg(target_arch = "wasm32")]
7229pub type ImageCopyExternalImage = CopyExternalImageSourceInfo;
7230
7231/// Source of an external texture copy.
7232///
7233/// Corresponds to the [implicit union type on WebGPU `GPUCopyExternalImageSourceInfo.source`](
7234/// https://gpuweb.github.io/gpuweb/#dom-gpuimagecopyexternalimage-source).
7235#[cfg(target_arch = "wasm32")]
7236#[derive(Clone, Debug)]
7237pub enum ExternalImageSource {
7238    /// Copy from a previously-decoded image bitmap.
7239    ImageBitmap(web_sys::ImageBitmap),
7240    /// Copy from an image element.
7241    HTMLImageElement(web_sys::HtmlImageElement),
7242    /// Copy from a current frame of a video element.
7243    HTMLVideoElement(web_sys::HtmlVideoElement),
7244    /// Copy from an image.
7245    ImageData(web_sys::ImageData),
7246    /// Copy from a on-screen canvas.
7247    HTMLCanvasElement(web_sys::HtmlCanvasElement),
7248    /// Copy from a off-screen canvas.
7249    ///
7250    /// Requires [`DownlevelFlags::UNRESTRICTED_EXTERNAL_TEXTURE_COPIES`]
7251    OffscreenCanvas(web_sys::OffscreenCanvas),
7252    /// Copy from a video frame.
7253    #[cfg(web_sys_unstable_apis)]
7254    VideoFrame(web_sys::VideoFrame),
7255}
7256
7257#[cfg(target_arch = "wasm32")]
7258impl ExternalImageSource {
7259    /// Gets the pixel, not css, width of the source.
7260    pub fn width(&self) -> u32 {
7261        match self {
7262            ExternalImageSource::ImageBitmap(b) => b.width(),
7263            ExternalImageSource::HTMLImageElement(i) => i.width(),
7264            ExternalImageSource::HTMLVideoElement(v) => v.video_width(),
7265            ExternalImageSource::ImageData(i) => i.width(),
7266            ExternalImageSource::HTMLCanvasElement(c) => c.width(),
7267            ExternalImageSource::OffscreenCanvas(c) => c.width(),
7268            #[cfg(web_sys_unstable_apis)]
7269            ExternalImageSource::VideoFrame(v) => v.display_width(),
7270        }
7271    }
7272
7273    /// Gets the pixel, not css, height of the source.
7274    pub fn height(&self) -> u32 {
7275        match self {
7276            ExternalImageSource::ImageBitmap(b) => b.height(),
7277            ExternalImageSource::HTMLImageElement(i) => i.height(),
7278            ExternalImageSource::HTMLVideoElement(v) => v.video_height(),
7279            ExternalImageSource::ImageData(i) => i.height(),
7280            ExternalImageSource::HTMLCanvasElement(c) => c.height(),
7281            ExternalImageSource::OffscreenCanvas(c) => c.height(),
7282            #[cfg(web_sys_unstable_apis)]
7283            ExternalImageSource::VideoFrame(v) => v.display_height(),
7284        }
7285    }
7286}
7287
7288#[cfg(target_arch = "wasm32")]
7289impl core::ops::Deref for ExternalImageSource {
7290    type Target = js_sys::Object;
7291
7292    fn deref(&self) -> &Self::Target {
7293        match self {
7294            Self::ImageBitmap(b) => b,
7295            Self::HTMLImageElement(i) => i,
7296            Self::HTMLVideoElement(v) => v,
7297            Self::ImageData(i) => i,
7298            Self::HTMLCanvasElement(c) => c,
7299            Self::OffscreenCanvas(c) => c,
7300            #[cfg(web_sys_unstable_apis)]
7301            Self::VideoFrame(v) => v,
7302        }
7303    }
7304}
7305
7306#[cfg(all(
7307    target_arch = "wasm32",
7308    feature = "fragile-send-sync-non-atomic-wasm",
7309    not(target_feature = "atomics")
7310))]
7311unsafe impl Send for ExternalImageSource {}
7312#[cfg(all(
7313    target_arch = "wasm32",
7314    feature = "fragile-send-sync-non-atomic-wasm",
7315    not(target_feature = "atomics")
7316))]
7317unsafe impl Sync for ExternalImageSource {}
7318
7319/// Color spaces supported on the web.
7320///
7321/// Corresponds to [HTML Canvas `PredefinedColorSpace`](
7322/// https://html.spec.whatwg.org/multipage/canvas.html#predefinedcolorspace).
7323#[derive(Copy, Clone, Debug, PartialEq, Eq)]
7324#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7325#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
7326pub enum PredefinedColorSpace {
7327    /// sRGB color space
7328    Srgb,
7329    /// Display-P3 color space
7330    DisplayP3,
7331}
7332
7333/// View of a texture which can be used to copy to a texture, including
7334/// color space and alpha premultiplication information.
7335///
7336/// Corresponds to [WebGPU `GPUCopyExternalImageDestInfo`](
7337/// https://gpuweb.github.io/gpuweb/#dictdef-gpuimagecopytexturetagged).
7338#[derive(Copy, Clone, Debug)]
7339#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7340pub struct CopyExternalImageDestInfo<T> {
7341    /// The texture to be copied to/from.
7342    pub texture: T,
7343    /// The target mip level of the texture.
7344    pub mip_level: u32,
7345    /// The base texel of the texture in the selected `mip_level`.
7346    pub origin: Origin3d,
7347    /// The copy aspect.
7348    pub aspect: TextureAspect,
7349    /// The color space of this texture.
7350    pub color_space: PredefinedColorSpace,
7351    /// The premultiplication of this texture
7352    pub premultiplied_alpha: bool,
7353}
7354
7355impl<T> CopyExternalImageDestInfo<T> {
7356    /// Removes the colorspace information from the type.
7357    pub fn to_untagged(self) -> TexelCopyTextureInfo<T> {
7358        TexelCopyTextureInfo {
7359            texture: self.texture,
7360            mip_level: self.mip_level,
7361            origin: self.origin,
7362            aspect: self.aspect,
7363        }
7364    }
7365}
7366
7367/// Old name for a [`CopyExternalImageDestInfo`].
7368#[deprecated(
7369    since = "24.0.0",
7370    note = "This has been renamed to `CopyExternalImageDestInfo`, and will be removed in 25.0.0."
7371)]
7372pub type ImageCopyTextureTagged<T> = CopyExternalImageDestInfo<T>;
7373
7374/// Subresource range within an image
7375#[repr(C)]
7376#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
7377#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7378#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
7379pub struct ImageSubresourceRange {
7380    /// Aspect of the texture. Color textures must be [`TextureAspect::All`][TAA].
7381    ///
7382    /// [TAA]: ../wgpu/enum.TextureAspect.html#variant.All
7383    pub aspect: TextureAspect,
7384    /// Base mip level.
7385    pub base_mip_level: u32,
7386    /// Mip level count.
7387    /// If `Some(count)`, `base_mip_level + count` must be less or equal to underlying texture mip count.
7388    /// If `None`, considered to include the rest of the mipmap levels, but at least 1 in total.
7389    pub mip_level_count: Option<u32>,
7390    /// Base array layer.
7391    pub base_array_layer: u32,
7392    /// Layer count.
7393    /// If `Some(count)`, `base_array_layer + count` must be less or equal to the underlying array count.
7394    /// If `None`, considered to include the rest of the array layers, but at least 1 in total.
7395    pub array_layer_count: Option<u32>,
7396}
7397
7398impl ImageSubresourceRange {
7399    /// Returns if the given range represents a full resource, with a texture of the given
7400    /// layer count and mip count.
7401    ///
7402    /// ```rust
7403    /// # use wgpu_types as wgpu;
7404    ///
7405    /// let range_none = wgpu::ImageSubresourceRange {
7406    ///     aspect: wgpu::TextureAspect::All,
7407    ///     base_mip_level: 0,
7408    ///     mip_level_count: None,
7409    ///     base_array_layer: 0,
7410    ///     array_layer_count: None,
7411    /// };
7412    /// assert_eq!(range_none.is_full_resource(wgpu::TextureFormat::Stencil8, 5, 10), true);
7413    ///
7414    /// let range_some = wgpu::ImageSubresourceRange {
7415    ///     aspect: wgpu::TextureAspect::All,
7416    ///     base_mip_level: 0,
7417    ///     mip_level_count: Some(5),
7418    ///     base_array_layer: 0,
7419    ///     array_layer_count: Some(10),
7420    /// };
7421    /// assert_eq!(range_some.is_full_resource(wgpu::TextureFormat::Stencil8, 5, 10), true);
7422    ///
7423    /// let range_mixed = wgpu::ImageSubresourceRange {
7424    ///     aspect: wgpu::TextureAspect::StencilOnly,
7425    ///     base_mip_level: 0,
7426    ///     // Only partial resource
7427    ///     mip_level_count: Some(3),
7428    ///     base_array_layer: 0,
7429    ///     array_layer_count: None,
7430    /// };
7431    /// assert_eq!(range_mixed.is_full_resource(wgpu::TextureFormat::Stencil8, 5, 10), false);
7432    /// ```
7433    #[must_use]
7434    pub fn is_full_resource(
7435        &self,
7436        format: TextureFormat,
7437        mip_levels: u32,
7438        array_layers: u32,
7439    ) -> bool {
7440        // Mip level count and array layer count need to deal with both the None and Some(count) case.
7441        let mip_level_count = self.mip_level_count.unwrap_or(mip_levels);
7442        let array_layer_count = self.array_layer_count.unwrap_or(array_layers);
7443
7444        let aspect_eq = Some(format) == format.aspect_specific_format(self.aspect);
7445
7446        let base_mip_level_eq = self.base_mip_level == 0;
7447        let mip_level_count_eq = mip_level_count == mip_levels;
7448
7449        let base_array_layer_eq = self.base_array_layer == 0;
7450        let array_layer_count_eq = array_layer_count == array_layers;
7451
7452        aspect_eq
7453            && base_mip_level_eq
7454            && mip_level_count_eq
7455            && base_array_layer_eq
7456            && array_layer_count_eq
7457    }
7458
7459    /// Returns the mip level range of a subresource range describes for a specific texture.
7460    #[must_use]
7461    pub fn mip_range(&self, mip_level_count: u32) -> Range<u32> {
7462        self.base_mip_level..match self.mip_level_count {
7463            Some(mip_level_count) => self.base_mip_level + mip_level_count,
7464            None => mip_level_count,
7465        }
7466    }
7467
7468    /// Returns the layer range of a subresource range describes for a specific texture.
7469    #[must_use]
7470    pub fn layer_range(&self, array_layer_count: u32) -> Range<u32> {
7471        self.base_array_layer..match self.array_layer_count {
7472            Some(array_layer_count) => self.base_array_layer + array_layer_count,
7473            None => array_layer_count,
7474        }
7475    }
7476}
7477
7478/// Color variation to use when sampler addressing mode is [`AddressMode::ClampToBorder`]
7479#[repr(C)]
7480#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
7481#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7482pub enum SamplerBorderColor {
7483    /// [0, 0, 0, 0]
7484    TransparentBlack,
7485    /// [0, 0, 0, 1]
7486    OpaqueBlack,
7487    /// [1, 1, 1, 1]
7488    OpaqueWhite,
7489
7490    /// On the Metal backend, this is equivalent to `TransparentBlack` for
7491    /// textures that have an alpha component, and equivalent to `OpaqueBlack`
7492    /// for textures that do not have an alpha component. On other backends,
7493    /// this is equivalent to `TransparentBlack`. Requires
7494    /// [`Features::ADDRESS_MODE_CLAMP_TO_ZERO`]. Not supported on the web.
7495    Zero,
7496}
7497
7498/// Describes how to create a QuerySet.
7499///
7500/// Corresponds to [WebGPU `GPUQuerySetDescriptor`](
7501/// https://gpuweb.github.io/gpuweb/#dictdef-gpuquerysetdescriptor).
7502#[derive(Clone, Debug)]
7503#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7504pub struct QuerySetDescriptor<L> {
7505    /// Debug label for the query set.
7506    pub label: L,
7507    /// Kind of query that this query set should contain.
7508    pub ty: QueryType,
7509    /// Total count of queries the set contains. Must not be zero.
7510    /// Must not be greater than [`QUERY_SET_MAX_QUERIES`].
7511    pub count: u32,
7512}
7513
7514impl<L> QuerySetDescriptor<L> {
7515    /// Takes a closure and maps the label of the query set descriptor into another.
7516    #[must_use]
7517    pub fn map_label<'a, K>(&'a self, fun: impl FnOnce(&'a L) -> K) -> QuerySetDescriptor<K> {
7518        QuerySetDescriptor {
7519            label: fun(&self.label),
7520            ty: self.ty,
7521            count: self.count,
7522        }
7523    }
7524}
7525
7526/// Type of query contained in a QuerySet.
7527///
7528/// Corresponds to [WebGPU `GPUQueryType`](
7529/// https://gpuweb.github.io/gpuweb/#enumdef-gpuquerytype).
7530#[derive(Copy, Clone, Debug)]
7531#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7532pub enum QueryType {
7533    /// Query returns a single 64-bit number, serving as an occlusion boolean.
7534    Occlusion,
7535    /// Query returns up to 5 64-bit numbers based on the given flags.
7536    ///
7537    /// See [`PipelineStatisticsTypes`]'s documentation for more information
7538    /// on how they get resolved.
7539    ///
7540    /// [`Features::PIPELINE_STATISTICS_QUERY`] must be enabled to use this query type.
7541    PipelineStatistics(PipelineStatisticsTypes),
7542    /// Query returns a 64-bit number indicating the GPU-timestamp
7543    /// where all previous commands have finished executing.
7544    ///
7545    /// Must be multiplied by [`Queue::get_timestamp_period`][Qgtp] to get
7546    /// the value in nanoseconds. Absolute values have no meaning,
7547    /// but timestamps can be subtracted to get the time it takes
7548    /// for a string of operations to complete.
7549    ///
7550    /// [`Features::TIMESTAMP_QUERY`] must be enabled to use this query type.
7551    ///
7552    /// [Qgtp]: ../wgpu/struct.Queue.html#method.get_timestamp_period
7553    Timestamp,
7554}
7555
7556bitflags::bitflags! {
7557    /// Flags for which pipeline data should be recorded.
7558    ///
7559    /// The amount of values written when resolved depends
7560    /// on the amount of flags. If 3 flags are enabled, 3
7561    /// 64-bit values will be written per-query.
7562    ///
7563    /// The order they are written is the order they are declared
7564    /// in this bitflags. If you enabled `CLIPPER_PRIMITIVES_OUT`
7565    /// and `COMPUTE_SHADER_INVOCATIONS`, it would write 16 bytes,
7566    /// the first 8 bytes being the primitive out value, the last 8
7567    /// bytes being the compute shader invocation count.
7568    #[repr(transparent)]
7569    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7570    #[cfg_attr(feature = "serde", serde(transparent))]
7571    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
7572    pub struct PipelineStatisticsTypes : u8 {
7573        /// Amount of times the vertex shader is ran. Accounts for
7574        /// the vertex cache when doing indexed rendering.
7575        const VERTEX_SHADER_INVOCATIONS = 1 << 0;
7576        /// Amount of times the clipper is invoked. This
7577        /// is also the amount of triangles output by the vertex shader.
7578        const CLIPPER_INVOCATIONS = 1 << 1;
7579        /// Amount of primitives that are not culled by the clipper.
7580        /// This is the amount of triangles that are actually on screen
7581        /// and will be rasterized and rendered.
7582        const CLIPPER_PRIMITIVES_OUT = 1 << 2;
7583        /// Amount of times the fragment shader is ran. Accounts for
7584        /// fragment shaders running in 2x2 blocks in order to get
7585        /// derivatives.
7586        const FRAGMENT_SHADER_INVOCATIONS = 1 << 3;
7587        /// Amount of times a compute shader is invoked. This will
7588        /// be equivalent to the dispatch count times the workgroup size.
7589        const COMPUTE_SHADER_INVOCATIONS = 1 << 4;
7590    }
7591}
7592
7593/// Argument buffer layout for draw_indirect commands.
7594#[repr(C)]
7595#[derive(Copy, Clone, Debug, Default)]
7596pub struct DrawIndirectArgs {
7597    /// The number of vertices to draw.
7598    pub vertex_count: u32,
7599    /// The number of instances to draw.
7600    pub instance_count: u32,
7601    /// The Index of the first vertex to draw.
7602    pub first_vertex: u32,
7603    /// The instance ID of the first instance to draw.
7604    ///
7605    /// Has to be 0, unless [`Features::INDIRECT_FIRST_INSTANCE`](crate::Features::INDIRECT_FIRST_INSTANCE) is enabled.
7606    pub first_instance: u32,
7607}
7608
7609impl DrawIndirectArgs {
7610    /// Returns the bytes representation of the struct, ready to be written in a buffer.
7611    #[must_use]
7612    pub fn as_bytes(&self) -> &[u8] {
7613        unsafe {
7614            core::mem::transmute(core::slice::from_raw_parts(
7615                core::ptr::from_ref(self).cast::<u8>(),
7616                size_of::<Self>(),
7617            ))
7618        }
7619    }
7620}
7621
7622/// Argument buffer layout for draw_indexed_indirect commands.
7623#[repr(C)]
7624#[derive(Copy, Clone, Debug, Default)]
7625pub struct DrawIndexedIndirectArgs {
7626    /// The number of indices to draw.
7627    pub index_count: u32,
7628    /// The number of instances to draw.
7629    pub instance_count: u32,
7630    /// The first index within the index buffer.
7631    pub first_index: u32,
7632    /// The value added to the vertex index before indexing into the vertex buffer.
7633    pub base_vertex: i32,
7634    /// The instance ID of the first instance to draw.
7635    ///
7636    /// Has to be 0, unless [`Features::INDIRECT_FIRST_INSTANCE`](crate::Features::INDIRECT_FIRST_INSTANCE) is enabled.
7637    pub first_instance: u32,
7638}
7639
7640impl DrawIndexedIndirectArgs {
7641    /// Returns the bytes representation of the struct, ready to be written in a buffer.
7642    #[must_use]
7643    pub fn as_bytes(&self) -> &[u8] {
7644        unsafe {
7645            core::mem::transmute(core::slice::from_raw_parts(
7646                core::ptr::from_ref(self).cast::<u8>(),
7647                size_of::<Self>(),
7648            ))
7649        }
7650    }
7651}
7652
7653/// Argument buffer layout for dispatch_indirect commands.
7654#[repr(C)]
7655#[derive(Copy, Clone, Debug, Default)]
7656pub struct DispatchIndirectArgs {
7657    /// The number of work groups in X dimension.
7658    pub x: u32,
7659    /// The number of work groups in Y dimension.
7660    pub y: u32,
7661    /// The number of work groups in Z dimension.
7662    pub z: u32,
7663}
7664
7665impl DispatchIndirectArgs {
7666    /// Returns the bytes representation of the struct, ready to be written into a buffer.
7667    #[must_use]
7668    pub fn as_bytes(&self) -> &[u8] {
7669        unsafe {
7670            core::mem::transmute(core::slice::from_raw_parts(
7671                core::ptr::from_ref(self).cast::<u8>(),
7672                size_of::<Self>(),
7673            ))
7674        }
7675    }
7676}
7677
7678/// Describes how shader bound checks should be performed.
7679#[derive(Copy, Clone, Debug)]
7680#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7681pub struct ShaderRuntimeChecks {
7682    /// Enforce bounds checks in shaders, even if the underlying driver doesn't
7683    /// support doing so natively.
7684    ///
7685    /// When this is `true`, `wgpu` promises that shaders can only read or
7686    /// write the accessible region of a bindgroup's buffer bindings. If
7687    /// the underlying graphics platform cannot implement these bounds checks
7688    /// itself, `wgpu` will inject bounds checks before presenting the
7689    /// shader to the platform.
7690    ///
7691    /// When this is `false`, `wgpu` only enforces such bounds checks if the
7692    /// underlying platform provides a way to do so itself. `wgpu` does not
7693    /// itself add any bounds checks to generated shader code.
7694    ///
7695    /// Note that `wgpu` users may try to initialize only those portions of
7696    /// buffers that they anticipate might be read from. Passing `false` here
7697    /// may allow shaders to see wider regions of the buffers than expected,
7698    /// making such deferred initialization visible to the application.
7699    pub bounds_checks: bool,
7700    ///
7701    /// If false, the caller MUST ensure that all passed shaders do not contain any infinite loops.
7702    ///
7703    /// If it does, backend compilers MAY treat such a loop as unreachable code and draw
7704    /// conclusions about other safety-critical code paths. This option SHOULD NOT be disabled
7705    /// when running untrusted code.
7706    pub force_loop_bounding: bool,
7707}
7708
7709impl ShaderRuntimeChecks {
7710    /// Creates a new configuration where the shader is fully checked.
7711    #[must_use]
7712    pub fn checked() -> Self {
7713        unsafe { Self::all(true) }
7714    }
7715
7716    /// Creates a new configuration where none of the checks are performed.
7717    ///
7718    /// # Safety
7719    ///
7720    /// See the documentation for the `set_*` methods for the safety requirements
7721    /// of each sub-configuration.
7722    #[must_use]
7723    pub fn unchecked() -> Self {
7724        unsafe { Self::all(false) }
7725    }
7726
7727    /// Creates a new configuration where all checks are enabled or disabled. To safely
7728    /// create a configuration with all checks enabled, use [`ShaderRuntimeChecks::checked`].
7729    ///
7730    /// # Safety
7731    ///
7732    /// See the documentation for the `set_*` methods for the safety requirements
7733    /// of each sub-configuration.
7734    #[must_use]
7735    pub unsafe fn all(all_checks: bool) -> Self {
7736        Self {
7737            bounds_checks: all_checks,
7738            force_loop_bounding: all_checks,
7739        }
7740    }
7741}
7742
7743impl Default for ShaderRuntimeChecks {
7744    fn default() -> Self {
7745        Self::checked()
7746    }
7747}
7748
7749#[derive(Clone, Debug, PartialEq, Eq)]
7750#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7751/// Descriptor for all size defining attributes of a single triangle geometry inside a bottom level acceleration structure.
7752pub struct BlasTriangleGeometrySizeDescriptor {
7753    /// Format of a vertex position, must be [VertexFormat::Float32x3]
7754    /// with just [Features::EXPERIMENTAL_RAY_TRACING_ACCELERATION_STRUCTURE]
7755    /// but later features may add more formats.
7756    pub vertex_format: VertexFormat,
7757    /// Number of vertices.
7758    pub vertex_count: u32,
7759    /// Format of an index. Only needed if an index buffer is used.
7760    /// If `index_format` is provided `index_count` is required.
7761    pub index_format: Option<IndexFormat>,
7762    /// Number of indices. Only needed if an index buffer is used.
7763    /// If `index_count` is provided `index_format` is required.
7764    pub index_count: Option<u32>,
7765    /// Flags for the geometry.
7766    pub flags: AccelerationStructureGeometryFlags,
7767}
7768
7769#[derive(Clone, Debug)]
7770#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7771/// Descriptor for all size defining attributes of all geometries inside a bottom level acceleration structure.
7772pub enum BlasGeometrySizeDescriptors {
7773    /// Triangle geometry version.
7774    Triangles {
7775        /// Descriptor for each triangle geometry.
7776        descriptors: Vec<BlasTriangleGeometrySizeDescriptor>,
7777    },
7778}
7779
7780#[repr(u8)]
7781#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
7782#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7783/// Update mode for acceleration structure builds.
7784pub enum AccelerationStructureUpdateMode {
7785    /// Always perform a full build.
7786    Build,
7787    /// If possible, perform an incremental update.
7788    ///
7789    /// Not advised for major topology changes.
7790    /// (Useful for e.g. skinning)
7791    PreferUpdate,
7792}
7793
7794#[repr(C)]
7795#[derive(Clone, Debug, PartialEq, Eq, Hash)]
7796#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7797/// Descriptor for creating a bottom level acceleration structure.
7798pub struct CreateBlasDescriptor<L> {
7799    /// Label for the bottom level acceleration structure.
7800    pub label: L,
7801    /// Flags for the bottom level acceleration structure.
7802    pub flags: AccelerationStructureFlags,
7803    /// Update mode for the bottom level acceleration structure.
7804    pub update_mode: AccelerationStructureUpdateMode,
7805}
7806
7807impl<L> CreateBlasDescriptor<L> {
7808    /// Takes a closure and maps the label of the blas descriptor into another.
7809    pub fn map_label<K>(&self, fun: impl FnOnce(&L) -> K) -> CreateBlasDescriptor<K> {
7810        CreateBlasDescriptor {
7811            label: fun(&self.label),
7812            flags: self.flags,
7813            update_mode: self.update_mode,
7814        }
7815    }
7816}
7817
7818#[repr(C)]
7819#[derive(Clone, Debug, PartialEq, Eq, Hash)]
7820#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7821/// Descriptor for creating a top level acceleration structure.
7822pub struct CreateTlasDescriptor<L> {
7823    /// Label for the top level acceleration structure.
7824    pub label: L,
7825    /// Number of instances that can be stored in the acceleration structure.
7826    pub max_instances: u32,
7827    /// Flags for the bottom level acceleration structure.
7828    pub flags: AccelerationStructureFlags,
7829    /// Update mode for the bottom level acceleration structure.
7830    pub update_mode: AccelerationStructureUpdateMode,
7831}
7832
7833impl<L> CreateTlasDescriptor<L> {
7834    /// Takes a closure and maps the label of the blas descriptor into another.
7835    pub fn map_label<K>(&self, fun: impl FnOnce(&L) -> K) -> CreateTlasDescriptor<K> {
7836        CreateTlasDescriptor {
7837            label: fun(&self.label),
7838            flags: self.flags,
7839            update_mode: self.update_mode,
7840            max_instances: self.max_instances,
7841        }
7842    }
7843}
7844
7845bitflags::bitflags!(
7846    /// Flags for acceleration structures
7847    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7848    #[cfg_attr(feature = "serde", serde(transparent))]
7849    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
7850    pub struct AccelerationStructureFlags: u8 {
7851        /// Allow for incremental updates (no change in size), currently this is unimplemented
7852        /// and will build as normal (this is fine, update vs build should be unnoticeable)
7853        const ALLOW_UPDATE = 1 << 0;
7854        /// Allow the acceleration structure to be compacted in a copy operation, the function
7855        /// to compact is not currently implemented.
7856        const ALLOW_COMPACTION = 1 << 1;
7857        /// Optimize for fast ray tracing performance, recommended if the geometry is unlikely
7858        /// to change (e.g. in a game: non-interactive scene geometry)
7859        const PREFER_FAST_TRACE = 1 << 2;
7860        /// Optimize for fast build time, recommended if geometry is likely to change frequently
7861        /// (e.g. in a game: player model).
7862        const PREFER_FAST_BUILD = 1 << 3;
7863        /// Optimize for low memory footprint (both while building and in the output BLAS).
7864        const LOW_MEMORY = 1 << 4;
7865    }
7866);
7867
7868bitflags::bitflags!(
7869    /// Flags for acceleration structure geometries
7870    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7871    #[cfg_attr(feature = "serde", serde(transparent))]
7872    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
7873    pub struct AccelerationStructureGeometryFlags: u8 {
7874        /// Is OPAQUE (is there no alpha test) recommended as currently in naga there is no
7875        /// candidate intersections yet so currently BLASes without this flag will not have hits.
7876        /// Not enabling this makes the BLAS unable to be interacted with in WGSL.
7877        const OPAQUE = 1 << 0;
7878        /// NO_DUPLICATE_ANY_HIT_INVOCATION, not useful unless using hal with wgpu, ray-tracing
7879        /// pipelines are not supported in wgpu so any-hit shaders do not exist. For when any-hit
7880        /// shaders are implemented (or experienced users who combine this with an underlying library:
7881        /// for any primitive (triangle or AABB) multiple any-hit shaders sometimes may be invoked
7882        /// (especially in AABBs like a sphere), if this flag in present only one hit on a primitive may
7883        /// invoke an any-hit shader.
7884        const NO_DUPLICATE_ANY_HIT_INVOCATION = 1 << 1;
7885    }
7886);
7887
7888/// Alignment requirement for transform buffers used in acceleration structure builds
7889pub const TRANSFORM_BUFFER_ALIGNMENT: BufferAddress = 16;
7890
7891/// Alignment requirement for instance buffers used in acceleration structure builds (`build_acceleration_structures_unsafe_tlas`)
7892pub const INSTANCE_BUFFER_ALIGNMENT: BufferAddress = 16;
7893
7894pub use send_sync::*;
7895
7896#[doc(hidden)]
7897mod send_sync {
7898    pub trait WasmNotSendSync: WasmNotSend + WasmNotSync {}
7899    impl<T: WasmNotSend + WasmNotSync> WasmNotSendSync for T {}
7900    #[cfg(any(
7901        not(target_arch = "wasm32"),
7902        all(
7903            feature = "fragile-send-sync-non-atomic-wasm",
7904            not(target_feature = "atomics")
7905        )
7906    ))]
7907    pub trait WasmNotSend: Send {}
7908    #[cfg(any(
7909        not(target_arch = "wasm32"),
7910        all(
7911            feature = "fragile-send-sync-non-atomic-wasm",
7912            not(target_feature = "atomics")
7913        )
7914    ))]
7915    impl<T: Send> WasmNotSend for T {}
7916    #[cfg(not(any(
7917        not(target_arch = "wasm32"),
7918        all(
7919            feature = "fragile-send-sync-non-atomic-wasm",
7920            not(target_feature = "atomics")
7921        )
7922    )))]
7923    pub trait WasmNotSend {}
7924    #[cfg(not(any(
7925        not(target_arch = "wasm32"),
7926        all(
7927            feature = "fragile-send-sync-non-atomic-wasm",
7928            not(target_feature = "atomics")
7929        )
7930    )))]
7931    impl<T> WasmNotSend for T {}
7932
7933    #[cfg(any(
7934        not(target_arch = "wasm32"),
7935        all(
7936            feature = "fragile-send-sync-non-atomic-wasm",
7937            not(target_feature = "atomics")
7938        )
7939    ))]
7940    pub trait WasmNotSync: Sync {}
7941    #[cfg(any(
7942        not(target_arch = "wasm32"),
7943        all(
7944            feature = "fragile-send-sync-non-atomic-wasm",
7945            not(target_feature = "atomics")
7946        )
7947    ))]
7948    impl<T: Sync> WasmNotSync for T {}
7949    #[cfg(not(any(
7950        not(target_arch = "wasm32"),
7951        all(
7952            feature = "fragile-send-sync-non-atomic-wasm",
7953            not(target_feature = "atomics")
7954        )
7955    )))]
7956    pub trait WasmNotSync {}
7957    #[cfg(not(any(
7958        not(target_arch = "wasm32"),
7959        all(
7960            feature = "fragile-send-sync-non-atomic-wasm",
7961            not(target_feature = "atomics")
7962        )
7963    )))]
7964    impl<T> WasmNotSync for T {}
7965}
7966
7967/// Reason for "lose the device".
7968///
7969/// Corresponds to [WebGPU `GPUDeviceLostReason`](https://gpuweb.github.io/gpuweb/#enumdef-gpudevicelostreason).
7970#[repr(u8)]
7971#[derive(Debug, Copy, Clone, Eq, PartialEq)]
7972#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7973pub enum DeviceLostReason {
7974    /// Triggered by driver
7975    Unknown = 0,
7976    /// After Device::destroy
7977    Destroyed = 1,
7978}