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