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