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