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