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