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