wgpu_types/
lib.rs

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