wgpu_types/
lib.rs

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