wgpu_types/
lib.rs

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