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