wgpu_types/
lib.rs

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