wgpu_types/
features.rs

1//! # Features
2//!
3//! Types identifying optional features of WebGPU and wgpu. Availability varies
4//! by hardware and can be checked when requesting an adapter and device.
5//!
6//! The `wgpu` Rust API always uses the `Features` bit flag type to represent a
7//! set of features. However, the WebGPU-defined JavaScript API uses
8//! `kebab-case` feature name strings, so some utilities are provided for
9//! working with those names. See [`Features::as_str`] and [`<Features as
10//! FromStr>::from_str`].
11//!
12//! The [`bitflags`] crate names flags by stringifying the
13//! `SCREAMING_SNAKE_CASE` identifier. These names are returned by
14//! [`Features::iter_names`] and parsed by [`Features::from_name`].
15//! [`bitflags`] does not currently support customized flag naming.
16//! See <https://github.com/bitflags/bitflags/issues/470>.
17
18use crate::{link_to_wgpu_docs, link_to_wgpu_item, VertexFormat};
19#[cfg(feature = "serde")]
20use alloc::fmt;
21use alloc::vec::Vec;
22#[cfg(feature = "serde")]
23use bitflags::parser::{ParseError, ParseHex, WriteHex};
24#[cfg(feature = "serde")]
25use bitflags::Bits;
26use bitflags::Flags;
27#[cfg(feature = "serde")]
28use core::mem::size_of;
29use core::str::FromStr;
30#[cfg(feature = "serde")]
31use serde::{Deserialize, Serialize};
32
33pub use webgpu_impl::*;
34mod webgpu_impl {
35    //! Constant values for [`super::FeaturesWebGPU`], separated so they can be picked up by
36    //! `cbindgen` in `mozilla-central` (where Firefox is developed).
37    #![allow(missing_docs)]
38
39    #[doc(hidden)]
40    pub const WEBGPU_FEATURE_DEPTH_CLIP_CONTROL: u64 = 1 << 0;
41
42    #[doc(hidden)]
43    pub const WEBGPU_FEATURE_DEPTH32FLOAT_STENCIL8: u64 = 1 << 1;
44
45    #[doc(hidden)]
46    pub const WEBGPU_FEATURE_TEXTURE_COMPRESSION_BC: u64 = 1 << 2;
47
48    #[doc(hidden)]
49    pub const WEBGPU_FEATURE_TEXTURE_COMPRESSION_BC_SLICED_3D: u64 = 1 << 3;
50
51    #[doc(hidden)]
52    pub const WEBGPU_FEATURE_TEXTURE_COMPRESSION_ETC2: u64 = 1 << 4;
53
54    #[doc(hidden)]
55    pub const WEBGPU_FEATURE_TEXTURE_COMPRESSION_ASTC: u64 = 1 << 5;
56
57    #[doc(hidden)]
58    pub const WEBGPU_FEATURE_TEXTURE_COMPRESSION_ASTC_SLICED_3D: u64 = 1 << 6;
59
60    #[doc(hidden)]
61    pub const WEBGPU_FEATURE_TIMESTAMP_QUERY: u64 = 1 << 7;
62
63    #[doc(hidden)]
64    pub const WEBGPU_FEATURE_INDIRECT_FIRST_INSTANCE: u64 = 1 << 8;
65
66    #[doc(hidden)]
67    pub const WEBGPU_FEATURE_SHADER_F16: u64 = 1 << 9;
68
69    #[doc(hidden)]
70    pub const WEBGPU_FEATURE_RG11B10UFLOAT_RENDERABLE: u64 = 1 << 10;
71
72    #[doc(hidden)]
73    pub const WEBGPU_FEATURE_BGRA8UNORM_STORAGE: u64 = 1 << 11;
74
75    #[doc(hidden)]
76    pub const WEBGPU_FEATURE_FLOAT32_FILTERABLE: u64 = 1 << 12;
77
78    #[doc(hidden)]
79    pub const WEBGPU_FEATURE_FLOAT32_BLENDABLE: u64 = 1 << 13;
80
81    #[doc(hidden)]
82    pub const WEBGPU_FEATURE_DUAL_SOURCE_BLENDING: u64 = 1 << 14;
83
84    #[doc(hidden)]
85    pub const WEBGPU_FEATURE_CLIP_DISTANCES: u64 = 1 << 15;
86
87    #[doc(hidden)]
88    pub const WEBGPU_FEATURE_IMMEDIATES: u64 = 1 << 16;
89
90    #[doc(hidden)]
91    pub const WEBGPU_FEATURE_PRIMITIVE_INDEX: u64 = 1 << 17;
92}
93
94macro_rules! bitflags_array_impl {
95    ($impl_name:ident $inner_name:ident $name:ident $op:tt $($struct_names:ident)*) => (
96        impl core::ops::$impl_name for $name {
97            type Output = Self;
98
99            #[inline]
100            fn $inner_name(self, other: Self) -> Self {
101                Self {
102                    $($struct_names: self.$struct_names $op other.$struct_names,)*
103                }
104            }
105        }
106    )
107}
108
109macro_rules! bitflags_array_impl_assign {
110    ($impl_name:ident $inner_name:ident $name:ident $op:tt $($struct_names:ident)*) => (
111        impl core::ops::$impl_name for $name {
112            #[inline]
113            fn $inner_name(&mut self, other: Self) {
114                $(self.$struct_names $op other.$struct_names;)*
115            }
116        }
117    )
118}
119
120macro_rules! bit_array_impl {
121    ($impl_name:ident $inner_name:ident $name:ident $op:tt) => (
122        impl core::ops::$impl_name for $name {
123            type Output = Self;
124
125            #[inline]
126            fn $inner_name(mut self, other: Self) -> Self {
127                for (inner, other) in self.0.iter_mut().zip(other.0.iter()) {
128                    *inner $op *other;
129                }
130                self
131            }
132        }
133    )
134}
135
136macro_rules! bitflags_independent_two_arg {
137    ($(#[$meta:meta])* $func_name:ident $($struct_names:ident)*) => (
138        $(#[$meta])*
139        pub const fn $func_name(self, other:Self) -> Self {
140            Self { $($struct_names: self.$struct_names.$func_name(other.$struct_names),)* }
141        }
142    )
143}
144
145// For the most part this macro should not be modified, most configuration should be possible
146// without changing this macro.
147/// Macro for creating sets of bitflags, we need this because there are almost more flags than bits
148/// in a u64, we can't use a u128 because of FFI, and the number of flags is increasing.
149macro_rules! bitflags_array {
150    (
151        $(#[$outer:meta])*
152        pub struct $name:ident: [$T:ty; $Len:expr];
153
154        $(
155            $(#[$bit_outer:meta])*
156            $vis:vis struct $inner_name:ident $lower_inner_name:ident {
157                $(
158                    $(#[doc $($args:tt)*])*
159                    #[name($str_name:literal $(, $alias:literal)*)]
160                    const $Flag:tt = $value:expr;
161                )*
162            }
163        )*
164    ) => {
165        $(
166            bitflags::bitflags! {
167                $(#[$bit_outer])*
168                $vis struct $inner_name: $T {
169                    $(
170                        $(#[doc $($args)*])*
171                        const $Flag = $value;
172                    )*
173                }
174            }
175        )*
176
177        $(#[$outer])*
178        pub struct $name {
179            $(
180                #[allow(missing_docs)]
181                $vis $lower_inner_name: $inner_name,
182            )*
183        }
184
185        /// Bits from `Features` in array form
186        #[derive(Default, Copy, Clone, Debug, PartialEq, Eq)]
187        #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
188        pub struct FeatureBits(pub [$T; $Len]);
189
190        bitflags_array_impl! { BitOr bitor $name | $($lower_inner_name)* }
191        bitflags_array_impl! { BitAnd bitand $name & $($lower_inner_name)* }
192        bitflags_array_impl! { BitXor bitxor $name ^ $($lower_inner_name)* }
193        impl core::ops::Not for $name {
194            type Output = Self;
195
196            #[inline]
197            fn not(self) -> Self {
198                Self {
199                   $($lower_inner_name: !self.$lower_inner_name,)*
200                }
201            }
202        }
203        bitflags_array_impl! { Sub sub $name - $($lower_inner_name)* }
204
205        #[cfg(feature = "serde")]
206        impl Serialize for $name {
207            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
208            where
209                S: serde::Serializer,
210            {
211                bitflags::serde::serialize(self, serializer)
212            }
213        }
214
215        #[cfg(feature = "serde")]
216        impl<'de> Deserialize<'de> for $name {
217            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
218            where
219                D: serde::Deserializer<'de>,
220            {
221                bitflags::serde::deserialize(deserializer)
222            }
223        }
224
225        impl core::fmt::Display for $name {
226            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
227                let mut iter = self.iter_names();
228                // simple look ahead
229                let mut next = iter.next();
230                while let Some((name, _)) = next {
231                    f.write_str(name)?;
232                    next = iter.next();
233                    if next.is_some() {
234                        f.write_str(" | ")?;
235                    }
236                }
237                Ok(())
238            }
239        }
240
241        bitflags_array_impl_assign! { BitOrAssign bitor_assign $name |= $($lower_inner_name)* }
242        bitflags_array_impl_assign! { BitAndAssign bitand_assign $name &= $($lower_inner_name)* }
243        bitflags_array_impl_assign! { BitXorAssign bitxor_assign $name ^= $($lower_inner_name)* }
244
245        bit_array_impl! { BitOr bitor FeatureBits |= }
246        bit_array_impl! { BitAnd bitand FeatureBits &= }
247        bit_array_impl! { BitXor bitxor FeatureBits ^= }
248
249        impl core::ops::Not for FeatureBits {
250            type Output = Self;
251
252            #[inline]
253            fn not(self) -> Self {
254                let [$($lower_inner_name,)*] = self.0;
255                Self([$(!$lower_inner_name,)*])
256            }
257        }
258
259        #[cfg(feature = "serde")]
260        impl WriteHex for FeatureBits {
261            fn write_hex<W: fmt::Write>(&self, mut writer: W) -> fmt::Result {
262                let [$($lower_inner_name,)*] = self.0;
263                let mut wrote = false;
264                let mut stager = alloc::string::String::with_capacity(size_of::<$T>() * 2);
265                // we don't want to write it if it's just zero as there may be multiple zeros
266                // resulting in something like "00" being written out. We do want to write it if
267                // there has already been something written though.
268                $(if ($lower_inner_name != 0) || wrote {
269                    // First we write to a staging string, then we add any zeros (e.g if #1
270                    // is f and a u8 and #2 is a then the two combined would be f0a which requires
271                    // a 0 inserted)
272                    $lower_inner_name.write_hex(&mut stager)?;
273                    if (stager.len() != size_of::<$T>() * 2) && wrote {
274                        let zeros_to_write = (size_of::<$T>() * 2) - stager.len();
275                        for _ in 0..zeros_to_write {
276                            writer.write_char('0')?
277                        }
278                    }
279                    writer.write_str(&stager)?;
280                    stager.clear();
281                    wrote = true;
282                })*
283                if !wrote {
284                    writer.write_str("0")?;
285                }
286                Ok(())
287            }
288        }
289
290        #[cfg(feature = "serde")]
291        impl ParseHex for FeatureBits {
292            fn parse_hex(input: &str) -> Result<Self, ParseError> {
293
294                let mut unset = Self::EMPTY;
295                let mut end = input.len();
296                if end == 0 {
297                    return Err(ParseError::empty_flag())
298                }
299                // we iterate starting at the least significant places and going up
300                for (idx, _) in [$(stringify!($lower_inner_name),)*].iter().enumerate().rev() {
301                    // A byte is two hex places - u8 (1 byte) = 0x00 (2 hex places).
302                    let checked_start = end.checked_sub(size_of::<$T>() * 2);
303                    let start = checked_start.unwrap_or(0);
304
305                    let cur_input = &input[start..end];
306                    unset.0[idx] = <$T>::from_str_radix(cur_input, 16)
307                        .map_err(|_|ParseError::invalid_hex_flag(cur_input))?;
308
309                    end = start;
310
311                    if let None = checked_start {
312                        break;
313                    }
314                }
315                Ok(unset)
316            }
317        }
318
319        impl bitflags::Bits for FeatureBits {
320            const EMPTY: Self = $name::empty().bits();
321
322            const ALL: Self = $name::all().bits();
323        }
324
325        impl Flags for $name {
326            const FLAGS: &'static [bitflags::Flag<Self>] = $name::FLAGS;
327
328            type Bits = FeatureBits;
329
330            fn bits(&self) -> FeatureBits {
331                FeatureBits([
332                    $(self.$lower_inner_name.bits(),)*
333                ])
334            }
335
336            fn from_bits_retain(bits: FeatureBits) -> Self {
337                let [$($lower_inner_name,)*] = bits.0;
338                Self {
339                    $($lower_inner_name: $inner_name::from_bits_retain($lower_inner_name),)*
340                }
341            }
342
343            fn empty() -> Self {
344                Self::empty()
345            }
346
347            fn all() -> Self {
348                Self::all()
349            }
350        }
351
352        impl $name {
353            pub(crate) const FLAGS: &'static [bitflags::Flag<Self>] = &[
354                $(
355                    $(
356                        bitflags::Flag::new(stringify!($Flag), $name::$Flag),
357                    )*
358                )*
359            ];
360
361            /// Gets the set flags as a container holding an array of bits.
362            pub const fn bits(&self) -> FeatureBits {
363                FeatureBits([
364                    $(self.$lower_inner_name.bits(),)*
365                ])
366            }
367
368            /// Returns self with no flags set.
369            pub const fn empty() -> Self {
370                Self {
371                    $($lower_inner_name: $inner_name::empty(),)*
372                }
373            }
374
375            /// Returns self with all flags set.
376            pub const fn all() -> Self {
377                Self {
378                    $($lower_inner_name: $inner_name::all(),)*
379                }
380            }
381
382            /// Whether all the bits set in `other` are all set in `self`
383            pub const fn contains(self, other:Self) -> bool {
384                // we need an annoying true to catch the last && >:(
385                $(self.$lower_inner_name.contains(other.$lower_inner_name) &&)* true
386            }
387
388            /// Returns whether any bit set in `self` matched any bit set in `other`.
389            pub const fn intersects(self, other:Self) -> bool {
390                $(self.$lower_inner_name.intersects(other.$lower_inner_name) ||)* false
391            }
392
393            /// Returns whether there is no flag set.
394            pub const fn is_empty(self) -> bool {
395                $(self.$lower_inner_name.is_empty() &&)* true
396            }
397
398            /// Returns whether the struct has all flags set.
399            pub const fn is_all(self) -> bool {
400                $(self.$lower_inner_name.is_all() &&)* true
401            }
402
403            bitflags_independent_two_arg! {
404                /// Bitwise or - `self | other`
405                union $($lower_inner_name)*
406            }
407
408            bitflags_independent_two_arg! {
409                /// Bitwise and - `self & other`
410                intersection $($lower_inner_name)*
411            }
412
413            bitflags_independent_two_arg! {
414                /// Bitwise and of the complement of other - `self & !other`
415                difference $($lower_inner_name)*
416            }
417
418            bitflags_independent_two_arg! {
419                /// Bitwise xor - `self ^ other`
420                symmetric_difference $($lower_inner_name)*
421            }
422
423            /// Bitwise not - `!self`
424            pub const fn complement(self) -> Self {
425                Self {
426                    $($lower_inner_name: self.$lower_inner_name.complement(),)*
427                }
428            }
429
430            /// Calls [`Self::insert`] if `set` is true and otherwise calls [`Self::remove`].
431            pub fn set(&mut self, other:Self, set: bool) {
432                $(self.$lower_inner_name.set(other.$lower_inner_name, set);)*
433            }
434
435            /// Inserts specified flag(s) into self
436            pub fn insert(&mut self, other:Self) {
437                $(self.$lower_inner_name.insert(other.$lower_inner_name);)*
438            }
439
440            /// Removes specified flag(s) from self
441            pub fn remove(&mut self, other:Self) {
442                $(self.$lower_inner_name.remove(other.$lower_inner_name);)*
443            }
444
445            /// Toggles specified flag(s) in self
446            pub fn toggle(&mut self, other:Self) {
447                $(self.$lower_inner_name.toggle(other.$lower_inner_name);)*
448            }
449
450            /// Takes in [`FeatureBits`] and returns None if there are invalid bits or otherwise Self with
451            /// those bits set
452            pub const fn from_bits(bits:FeatureBits) -> Option<Self> {
453                let [$($lower_inner_name,)*] = bits.0;
454                // The ? operator does not work in a const context.
455                Some(Self {
456                    $(
457                        $lower_inner_name: match $inner_name::from_bits($lower_inner_name) {
458                            Some(some) => some,
459                            None => return None,
460                        },
461                    )*
462                })
463            }
464
465            /// Takes in [`FeatureBits`] and returns Self with only valid bits (all other bits removed)
466            pub const fn from_bits_truncate(bits:FeatureBits) -> Self {
467                let [$($lower_inner_name,)*] = bits.0;
468                Self { $($lower_inner_name: $inner_name::from_bits_truncate($lower_inner_name),)* }
469            }
470
471            /// Takes in [`FeatureBits`] and returns Self with all bits that were set without removing
472            /// invalid bits
473            pub const fn from_bits_retain(bits:FeatureBits) -> Self {
474                let [$($lower_inner_name,)*] = bits.0;
475                Self { $($lower_inner_name: $inner_name::from_bits_retain($lower_inner_name),)* }
476            }
477
478            /// Takes in a bitflags flag name (in `SCREAMING_SNAKE_CASE`) and returns Self
479            /// if it matches or none if the name does not match the name of any of the
480            /// flags. Name is capitalisation dependent.
481            ///
482            /// [`impl FromStr`] can be used to recognize kebab-case names, like are used in
483            /// the WebGPU spec.
484            pub fn from_name(name: &str) -> Option<Self> {
485                match name {
486                    $(
487                        $(
488                            stringify!($Flag) => Some(Self::$Flag),
489                        )*
490                    )*
491                    _ => None,
492                }
493            }
494
495            /// Combines the features from the internal flags into the entire features struct
496            pub fn from_internal_flags($($lower_inner_name: $inner_name,)*) -> Self {
497                Self {
498                    $($lower_inner_name,)*
499                }
500            }
501
502            /// Returns an iterator over the set flags.
503            pub const fn iter(&self) -> bitflags::iter::Iter<$name> {
504                bitflags::iter::Iter::__private_const_new($name::FLAGS, *self, *self)
505            }
506
507            /// Returns an iterator over the set flags and their names.
508            ///
509            /// These are bitflags names in `SCREAMING_SNAKE_CASE`.
510            pub const fn iter_names(&self) -> bitflags::iter::IterNames<$name> {
511                bitflags::iter::IterNames::__private_const_new($name::FLAGS, *self, *self)
512            }
513
514            /// If the argument is a single [`Features`] flag, returns the corresponding
515            /// `kebab-case` feature name, otherwise `None`.
516            #[must_use]
517            pub fn as_str(&self) -> Option<&'static str> {
518                Some(match *self {
519                    $($(Self::$Flag => $str_name,)*)*
520                    _ => return None,
521                })
522            }
523
524            $(
525                $(
526                    $(#[doc $($args)*])*
527                    #[allow(clippy::needless_update, reason = "only useless if there is 1 member")]
528                    pub const $Flag: Self = Self {
529                        $lower_inner_name: $inner_name::from_bits_truncate($value),
530                        ..Self::empty()
531                    };
532                )*
533            )*
534        }
535
536        // Parses kebab-case feature names (i.e. the names given in the spec, for features
537        // in FeaturesWebGPU, and otherwise the `wgpu-` prefixed names).
538        impl FromStr for $name {
539            type Err = ();
540
541            fn from_str(s: &str) -> Result<Self, Self::Err> {
542                Ok(match s {
543                    $($($str_name $(| $alias)* => Self::$Flag,)*)*
544                    _ => return Err(()),
545                })
546            }
547        }
548
549        $(
550            impl From<$inner_name> for Features {
551                #[allow(clippy::needless_update, reason = "only useless if there is 1 member")]
552                fn from($lower_inner_name: $inner_name) -> Self {
553                    Self {
554                        $lower_inner_name,
555                        ..Self::empty()
556                    }
557                }
558            }
559        )*
560    };
561}
562
563impl From<FeatureBits> for Features {
564    fn from(value: FeatureBits) -> Self {
565        Self::from_bits_retain(value)
566    }
567}
568
569impl From<Features> for FeatureBits {
570    fn from(value: Features) -> Self {
571        value.bits()
572    }
573}
574
575bitflags_array! {
576    /// Features that are not guaranteed to be supported.
577    ///
578    /// These are either part of the webgpu standard, or are extension features supported by
579    /// wgpu when targeting native.
580    ///
581    /// If you want to use a feature, you need to first verify that the adapter supports
582    /// the feature. If the adapter does not support the feature, requesting a device with it enabled
583    /// will panic.
584    ///
585    /// Corresponds to [WebGPU `GPUFeatureName`](
586    /// https://gpuweb.github.io/gpuweb/#enumdef-gpufeaturename).
587    #[repr(C)]
588    #[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash)]
589    pub struct Features: [u64; 2];
590
591    /// Features that are not guaranteed to be supported.
592    ///
593    /// Most of these are native-only extension features supported by wgpu only when targeting
594    /// native. A few are intended to align with a proposed WebGPU extension, and one
595    /// (`EXTERNAL_TEXTURE`) controls WebGPU-specified behavior that is not optional in the
596    /// standard, but that we don't want to make a [`crate::DownlevelFlags`] until the
597    /// implementation is more complete. For all features see [`Features`].
598    ///
599    /// If you want to use a feature, you need to first verify that the adapter supports
600    /// the feature. If the adapter does not support the feature, requesting a device with it enabled
601    /// will panic.
602    ///
603    /// Corresponds to [WebGPU `GPUFeatureName`](
604    /// https://gpuweb.github.io/gpuweb/#enumdef-gpufeaturename).
605    #[repr(transparent)]
606    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
607    #[cfg_attr(feature = "serde", serde(transparent))]
608    #[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash)]
609    pub struct FeaturesWGPU features_wgpu {
610        /// Allows shaders to use f32 atomic load, store, add, sub, and exchange.
611        ///
612        /// Supported platforms:
613        /// - Metal (with MSL 3.0+ and Apple7+/Mac2)
614        /// - Vulkan (with [VK_EXT_shader_atomic_float])
615        ///
616        /// This is a native only feature.
617        ///
618        /// [VK_EXT_shader_atomic_float]: https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_EXT_shader_atomic_float.html
619        #[name("wgpu-shader-float32-atomic")]
620        const SHADER_FLOAT32_ATOMIC = 1 << 0;
621
622        // The features starting with a ? are features that might become part of the spec or
623        // at the very least we can implement as native features; since they should cover all
624        // possible formats and capabilities across backends.
625        //
626        // ? const FORMATS_TIER_1 = 1 << ??; (https://github.com/gpuweb/gpuweb/issues/3837)
627        // ? const RW_STORAGE_TEXTURE_TIER_1 = 1 << ??; (https://github.com/gpuweb/gpuweb/issues/3838)
628        // ? const NORM16_FILTERABLE = 1 << ??; (https://github.com/gpuweb/gpuweb/issues/3839)
629        // ? const NORM16_RESOLVE = 1 << ??; (https://github.com/gpuweb/gpuweb/issues/3839)
630        // ? const 32BIT_FORMAT_MULTISAMPLE = 1 << ??; (https://github.com/gpuweb/gpuweb/issues/3844)
631        // ? const 32BIT_FORMAT_RESOLVE = 1 << ??; (https://github.com/gpuweb/gpuweb/issues/3844)
632        // ? const TEXTURE_COMPRESSION_ASTC_HDR = 1 << ??; (https://github.com/gpuweb/gpuweb/issues/3856)
633        // TEXTURE_FORMAT_16BIT_NORM & TEXTURE_COMPRESSION_ASTC_HDR will most likely become web features as well
634        // TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES might not be necessary if we have all the texture features implemented
635
636        // Texture Formats:
637
638        /// Enables normalized `16-bit` texture formats.
639        ///
640        /// Supported platforms:
641        /// - Vulkan
642        /// - DX12
643        /// - Metal
644        ///
645        /// This is a native only feature.
646        #[name("wgpu-texture-format-16-bit-norm", "texture-format-16-bit-norm")]
647        const TEXTURE_FORMAT_16BIT_NORM = 1 << 1;
648        /// Enables ASTC HDR family of compressed textures.
649        ///
650        /// Compressed textures sacrifice some quality in exchange for significantly reduced
651        /// bandwidth usage.
652        ///
653        /// Support for this feature guarantees availability of [`TextureUsages::COPY_SRC | TextureUsages::COPY_DST | TextureUsages::TEXTURE_BINDING`] for ASTC formats with the HDR channel type.
654        /// [`Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES`] may enable additional usages.
655        ///
656        /// Supported Platforms:
657        /// - Metal
658        /// - Vulkan
659        /// - OpenGL
660        ///
661        /// This is a native only feature.
662        #[name("wgpu-texture-compression-astc-hdr", "texture-compression-astc-hdr")]
663        const TEXTURE_COMPRESSION_ASTC_HDR = 1 << 2;
664        /// Enables device specific texture format features.
665        ///
666        /// See `TextureFormatFeatures` for a listing of the features in question.
667        ///
668        /// By default only texture format properties as defined by the WebGPU specification are allowed.
669        /// Enabling this feature flag extends the features of each format to the ones supported by the current device.
670        /// Note that without this flag, read/write storage access is not allowed at all.
671        ///
672        /// This extension does not enable additional formats.
673        ///
674        /// This is a native only feature.
675        #[name("wgpu-texture-adapter-specific-format-features", "texture-adapter-specific-format-features")]
676        const TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES = 1 << 3;
677
678        // API:
679
680        /// Enables use of Pipeline Statistics Queries. These queries tell the count of various operations
681        /// performed between the start and stop call. Call [`RenderPass::begin_pipeline_statistics_query`] to start
682        /// a query, then call [`RenderPass::end_pipeline_statistics_query`] to stop one.
683        ///
684        /// They must be resolved using [`CommandEncoder::resolve_query_set`] into a buffer.
685        /// The rules on how these resolve into buffers are detailed in the documentation for [`PipelineStatisticsTypes`].
686        ///
687        /// Supported Platforms:
688        /// - Vulkan
689        /// - DX12
690        ///
691        /// This is a native only feature with a [proposal](https://github.com/gpuweb/gpuweb/blob/0008bd30da2366af88180b511a5d0d0c1dffbc36/proposals/pipeline-statistics-query.md) for the web.
692        ///
693        #[doc = link_to_wgpu_docs!(["`RenderPass::begin_pipeline_statistics_query`"]: "struct.RenderPass.html#method.begin_pipeline_statistics_query")]
694        #[doc = link_to_wgpu_docs!(["`RenderPass::end_pipeline_statistics_query`"]: "struct.RenderPass.html#method.end_pipeline_statistics_query")]
695        #[doc = link_to_wgpu_docs!(["`CommandEncoder::resolve_query_set`"]: "struct.CommandEncoder.html#method.resolve_query_set")]
696        /// [`PipelineStatisticsTypes`]: super::PipelineStatisticsTypes
697        #[name("wgpu-pipeline-statistics-query", "pipeline-statistics-query")]
698        const PIPELINE_STATISTICS_QUERY = 1 << 4;
699        /// Allows for timestamp queries directly on command encoders.
700        ///
701        /// Implies [`Features::TIMESTAMP_QUERY`] is supported.
702        ///
703        /// Additionally allows for timestamp writes on command encoders
704        /// using [`CommandEncoder::write_timestamp`].
705        ///
706        /// Supported platforms:
707        /// - Vulkan
708        /// - DX12
709        /// - Metal
710        /// - OpenGL (with GL_ARB_timer_query)
711        ///
712        /// This is a native only feature.
713        ///
714        #[doc = link_to_wgpu_docs!(["`CommandEncoder::write_timestamp`"]: "struct.CommandEncoder.html#method.write_timestamp")]
715        #[name("wgpu-timestamp-query-inside-encoders")]
716        const TIMESTAMP_QUERY_INSIDE_ENCODERS = 1 << 5;
717        /// Allows for timestamp queries directly on command encoders.
718        ///
719        /// Implies [`Features::TIMESTAMP_QUERY`] & [`Features::TIMESTAMP_QUERY_INSIDE_ENCODERS`] is supported.
720        ///
721        /// Additionally allows for timestamp queries to be used inside render & compute passes using:
722        /// - [`RenderPass::write_timestamp`]
723        /// - [`ComputePass::write_timestamp`]
724        ///
725        /// Supported platforms:
726        /// - Vulkan
727        /// - DX12
728        /// - Metal (AMD & Intel, not Apple GPUs)
729        /// - OpenGL (with GL_ARB_timer_query)
730        ///
731        /// This is generally not available on tile-based rasterization GPUs.
732        ///
733        /// 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.
734        ///
735        #[doc = link_to_wgpu_docs!(["`RenderPass::write_timestamp`"]: "struct.RenderPass.html#method.write_timestamp")]
736        #[doc = link_to_wgpu_docs!(["`ComputePass::write_timestamp`"]: "struct.ComputePass.html#method.write_timestamp")]
737        #[name("wgpu-timestamp-query-inside-passes", "timestamp-query-inside-passes")]
738        const TIMESTAMP_QUERY_INSIDE_PASSES = 1 << 6;
739        /// Webgpu only allows the MAP_READ and MAP_WRITE buffer usage to be matched with
740        /// COPY_DST and COPY_SRC respectively. This removes this requirement.
741        ///
742        /// This is only beneficial on systems that share memory between CPU and GPU. If enabled
743        /// on a system that doesn't, this can severely hinder performance. Only use if you understand
744        /// the consequences.
745        ///
746        /// Supported platforms:
747        /// - Vulkan
748        /// - DX12
749        /// - Metal
750        ///
751        /// This is a native only feature.
752        #[name("wgpu-mappable-primary-buffers", "mappable-primary-buffers")]
753        const MAPPABLE_PRIMARY_BUFFERS = 1 << 7;
754        /// Allows the user to create uniform arrays of textures in shaders:
755        ///
756        /// ex.
757        /// - `var textures: binding_array<texture_2d<f32>, 10>` (WGSL)
758        /// - `uniform texture2D textures[10]` (GLSL)
759        ///
760        /// If [`Features::STORAGE_RESOURCE_BINDING_ARRAY`] is supported as well as this, the user
761        /// may also create uniform arrays of storage textures.
762        ///
763        /// ex.
764        /// - `var textures: array<texture_storage_2d<r32float, write>, 10>` (WGSL)
765        /// - `uniform image2D textures[10]` (GLSL)
766        ///
767        /// This capability allows them to exist and to be indexed by dynamically uniform
768        /// values.
769        ///
770        /// Supported platforms:
771        /// - DX12
772        /// - Metal (with MSL 2.0+ on macOS 10.13+)
773        /// - Vulkan
774        ///
775        /// This is a native only feature.
776        #[name("wgpu-texture-binding-array", "texture-binding-array")]
777        const TEXTURE_BINDING_ARRAY = 1 << 8;
778        /// Allows the user to create arrays of buffers in shaders:
779        ///
780        /// ex.
781        /// - `var<uniform> buffer_array: array<MyBuffer, 10>` (WGSL)
782        /// - `uniform myBuffer { ... } buffer_array[10]` (GLSL)
783        ///
784        /// This capability allows them to exist and to be indexed by dynamically uniform
785        /// values.
786        ///
787        /// If [`Features::STORAGE_RESOURCE_BINDING_ARRAY`] is supported as well as this, the user
788        /// may also create arrays of storage buffers.
789        ///
790        /// ex.
791        /// - `var<storage> buffer_array: array<MyBuffer, 10>` (WGSL)
792        /// - `buffer myBuffer { ... } buffer_array[10]` (GLSL)
793        ///
794        /// Supported platforms:
795        /// - Vulkan
796        ///
797        /// This is a native only feature.
798        #[name("wgpu-buffer-binding-array", "buffer-binding-array")]
799        const BUFFER_BINDING_ARRAY = 1 << 9;
800        /// Allows the user to create uniform arrays of storage buffers or textures in shaders,
801        /// if resp. [`Features::BUFFER_BINDING_ARRAY`] or [`Features::TEXTURE_BINDING_ARRAY`]
802        /// is supported.
803        ///
804        /// This capability allows them to exist and to be indexed by dynamically uniform
805        /// values.
806        ///
807        /// Supported platforms:
808        /// - Metal (with MSL 2.2+ on macOS 10.13+)
809        /// - Vulkan
810        ///
811        /// This is a native only feature.
812        #[name("wgpu-storage-resource-binding-array", "storage-resource-binding-array")]
813        const STORAGE_RESOURCE_BINDING_ARRAY = 1 << 10;
814        /// Allows shaders to index sampled texture and storage buffer resource arrays with dynamically non-uniform values:
815        ///
816        /// ex. `texture_array[vertex_data]`
817        ///
818        /// In order to use this capability, the corresponding GLSL extension must be enabled like so:
819        ///
820        /// `#extension GL_EXT_nonuniform_qualifier : require`
821        ///
822        /// and then used either as `nonuniformEXT` qualifier in variable declaration:
823        ///
824        /// ex. `layout(location = 0) nonuniformEXT flat in int vertex_data;`
825        ///
826        /// or as `nonuniformEXT` constructor:
827        ///
828        /// ex. `texture_array[nonuniformEXT(vertex_data)]`
829        ///
830        /// WGSL and HLSL do not need any extension.
831        ///
832        /// Supported platforms:
833        /// - DX12
834        /// - Metal (with MSL 2.0+ on macOS 10.13+)
835        /// - Vulkan 1.2+ (or VK_EXT_descriptor_indexing)'s shaderSampledImageArrayNonUniformIndexing & shaderStorageBufferArrayNonUniformIndexing feature)
836        ///
837        /// This is a native only feature.
838        #[name("wgpu-sampled-texture-and-storage-buffer-array-non-uniform-indexing", "sampled-texture-and-storage-buffer-array-non-uniform-indexing")]
839        const SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING = 1 << 11;
840        /// Allows shaders to index storage texture resource arrays with dynamically non-uniform values:
841        ///
842        /// ex. `texture_array[vertex_data]`
843        ///
844        /// Supported platforms:
845        /// - DX12
846        /// - Metal (with MSL 2.0+ on macOS 10.13+)
847        /// - Vulkan 1.2+ (or VK_EXT_descriptor_indexing)'s shaderStorageTextureArrayNonUniformIndexing feature)
848        ///
849        /// This is a native only feature.
850        #[name("wgpu-storage-texture-array-non-uniform-indexing", "storage-texture-array-non-uniform-indexing")]
851        const STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING = 1 << 12;
852        /// Allows the user to create bind groups containing arrays with less bindings than the BindGroupLayout.
853        ///
854        /// Supported platforms:
855        /// - Vulkan
856        /// - DX12
857        ///
858        /// This is a native only feature.
859        #[name("wgpu-partially-bound-binding-array", "partially-bound-binding-array")]
860        const PARTIALLY_BOUND_BINDING_ARRAY = 1 << 13;
861        /// Allows the user to call [`RenderPass::multi_draw_indirect_count`] and [`RenderPass::multi_draw_indexed_indirect_count`].
862        ///
863        /// This allows the use of a buffer containing the actual number of draw calls. This feature being present also implies
864        /// that all calls to [`RenderPass::multi_draw_indirect`] and [`RenderPass::multi_draw_indexed_indirect`] are not being emulated
865        /// with a series of `draw_indirect` calls.
866        ///
867        /// Supported platforms:
868        /// - DX12
869        /// - Vulkan 1.2+ (or VK_KHR_draw_indirect_count)
870        ///
871        /// This is a native only feature.
872        ///
873        #[doc = link_to_wgpu_docs!(["`RenderPass::multi_draw_indirect`"]: "struct.RenderPass.html#method.multi_draw_indirect")]
874        #[doc = link_to_wgpu_docs!(["`RenderPass::multi_draw_indexed_indirect`"]: "struct.RenderPass.html#method.multi_draw_indexed_indirect")]
875        #[doc = link_to_wgpu_docs!(["`RenderPass::multi_draw_indirect_count`"]: "struct.RenderPass.html#method.multi_draw_indirect_count")]
876        #[doc = link_to_wgpu_docs!(["`RenderPass::multi_draw_indexed_indirect_count`"]: "struct.RenderPass.html#method.multi_draw_indexed_indirect_count")]
877        #[name("wgpu-multi-draw-indirect-count", "multi-draw-indirect-count")]
878        const MULTI_DRAW_INDIRECT_COUNT = 1 << 15;
879        /// Allows the use of [`AddressMode::ClampToBorder`] with a border color
880        /// of [`SamplerBorderColor::Zero`].
881        ///
882        /// Supported platforms:
883        /// - DX12
884        /// - Vulkan
885        /// - Metal
886        /// - OpenGL
887        ///
888        /// This is a native only feature.
889        ///
890        /// [`AddressMode::ClampToBorder`]: super::AddressMode::ClampToBorder
891        /// [`SamplerBorderColor::Zero`]: super::SamplerBorderColor::Zero
892        #[name("wgpu-address-mode-clamp-to-zero", "address-mode-clamp-to-zero")]
893        const ADDRESS_MODE_CLAMP_TO_ZERO = 1 << 17;
894        /// Allows the use of [`AddressMode::ClampToBorder`] with a border color
895        /// other than [`SamplerBorderColor::Zero`].
896        ///
897        /// Supported platforms:
898        /// - DX12
899        /// - Vulkan
900        /// - Metal (macOS 10.12+ only)
901        /// - OpenGL
902        ///
903        /// This is a native only feature.
904        ///
905        /// [`AddressMode::ClampToBorder`]: super::AddressMode::ClampToBorder
906        /// [`SamplerBorderColor::Zero`]: super::SamplerBorderColor::Zero
907        #[name("wgpu-address-mode-clamp-to-border", "address-mode-clamp-to-border")]
908        const ADDRESS_MODE_CLAMP_TO_BORDER = 1 << 18;
909        /// Allows the user to set [`PolygonMode::Line`] in [`PrimitiveState::polygon_mode`]
910        ///
911        /// This allows drawing polygons/triangles as lines (wireframe) instead of filled
912        ///
913        /// Supported platforms:
914        /// - DX12
915        /// - Vulkan
916        /// - Metal
917        ///
918        /// This is a native only feature.
919        ///
920        /// [`PrimitiveState::polygon_mode`]: super::PrimitiveState
921        /// [`PolygonMode::Line`]: super::PolygonMode::Line
922        #[name("wgpu-polygon-mode-line", "polygon-mode-line")]
923        const POLYGON_MODE_LINE = 1 << 19;
924        /// Allows the user to set [`PolygonMode::Point`] in [`PrimitiveState::polygon_mode`]
925        ///
926        /// This allows only drawing the vertices of polygons/triangles instead of filled
927        ///
928        /// Supported platforms:
929        /// - Vulkan
930        ///
931        /// This is a native only feature.
932        ///
933        /// [`PrimitiveState::polygon_mode`]: super::PrimitiveState
934        /// [`PolygonMode::Point`]: super::PolygonMode::Point
935        #[name("wgpu-polygon-mode-point", "polygon-mode-point")]
936        const POLYGON_MODE_POINT = 1 << 20;
937        /// Allows the user to set a overestimation-conservative-rasterization in [`PrimitiveState::conservative`]
938        ///
939        /// Processing of degenerate triangles/lines is hardware specific.
940        /// Only triangles are supported.
941        ///
942        /// Supported platforms:
943        /// - Vulkan
944        ///
945        /// This is a native only feature.
946        ///
947        /// [`PrimitiveState::conservative`]: super::PrimitiveState::conservative
948        #[name("wgpu-conservative-rasterization", "conservative-rasterization")]
949        const CONSERVATIVE_RASTERIZATION = 1 << 21;
950        /// Enables bindings of writable storage buffers and textures visible to vertex shaders.
951        ///
952        /// Note: some (tiled-based) platforms do not support vertex shaders with any side-effects.
953        ///
954        /// Supported Platforms:
955        /// - All
956        ///
957        /// This is a native only feature.
958        #[name("wgpu-vertex-writable-storage", "vertex-writable-storage")]
959        const VERTEX_WRITABLE_STORAGE = 1 << 22;
960        /// Enables clear to zero for textures.
961        ///
962        /// Supported platforms:
963        /// - All
964        ///
965        /// This is a native only feature.
966        #[name("wgpu-clear-texture", "clear-texture")]
967        const CLEAR_TEXTURE = 1 << 23;
968        /// Enables multiview render passes and `builtin(view_index)` in vertex/mesh shaders.
969        ///
970        /// Supported platforms:
971        /// - Vulkan
972        /// - Metal
973        /// - DX12
974        /// - OpenGL (web only)
975        ///
976        /// This is a native only feature.
977        #[name("wgpu-multiview", "multiview")]
978        const MULTIVIEW = 1 << 26;
979        /// Enables using 64-bit types for vertex attributes.
980        ///
981        /// Requires SHADER_FLOAT64.
982        ///
983        /// Supported Platforms: N/A
984        ///
985        /// This is a native only feature.
986        #[name("wgpu-vertex-attribute-64-bit", "vertex-attribute-64-bit")]
987        const VERTEX_ATTRIBUTE_64BIT = 1 << 27;
988        /// Enables image atomic fetch add, and, xor, or, min, and max for R32Uint and R32Sint textures.
989        ///
990        /// Supported platforms:
991        /// - Vulkan
992        /// - DX12
993        /// - Metal (with MSL 3.1+)
994        ///
995        /// This is a native only feature.
996        #[name("wgpu-texture-atomic")]
997        const TEXTURE_ATOMIC = 1 << 28;
998        /// Allows for creation of textures of format [`TextureFormat::NV12`]
999        ///
1000        /// Supported platforms:
1001        /// - DX12
1002        /// - Vulkan
1003        ///
1004        /// This is a native only feature.
1005        ///
1006        /// [`TextureFormat::NV12`]: super::TextureFormat::NV12
1007        #[name("wgpu-texture-format-nv12")]
1008        const TEXTURE_FORMAT_NV12 = 1 << 29;
1009        /// Allows for creation of textures of format [`TextureFormat::P010`]
1010        ///
1011        /// Supported platforms:
1012        /// - DX12
1013        /// - Vulkan
1014        ///
1015        /// This is a native only feature.
1016        ///
1017        /// [`TextureFormat::P010`]: super::TextureFormat::P010
1018        #[name("wgpu-texture-format-p010")]
1019        const TEXTURE_FORMAT_P010 = 1 << 30;
1020
1021        /// Allows for the creation and usage of `ExternalTexture`s, and bind
1022        /// group layouts containing external texture `BindingType`s.
1023        ///
1024        /// Conceptually this should really be a [`crate::DownlevelFlags`] as
1025        /// it corresponds to WebGPU's [`GPUExternalTexture`](
1026        /// https://www.w3.org/TR/webgpu/#gpuexternaltexture).
1027        /// However, the implementation is currently in-progress, and until it
1028        /// is complete we do not want applications to ignore adapters due to
1029        /// a missing downlevel flag, when they may not require this feature at
1030        /// all.
1031        ///
1032        /// Supported platforms:
1033        /// - DX12
1034        /// - Metal
1035        #[name("wgpu-external-texture", "external-texture")]
1036        const EXTERNAL_TEXTURE = 1 << 31;
1037
1038        // Shader:
1039
1040        /// ***THIS IS EXPERIMENTAL:*** Features enabled by this may have
1041        /// major bugs in it and are expected to be subject to breaking changes, suggestions
1042        /// for the API exposed by this should be posted on [the ray-tracing issue](https://github.com/gfx-rs/wgpu/issues/1040)
1043        ///
1044        /// Allows for the creation of ray-tracing queries within shaders.
1045        ///
1046        /// Supported platforms:
1047        /// - Vulkan
1048        ///
1049        /// This is a native-only feature.
1050        #[name("wgpu-ray-query")]
1051        const EXPERIMENTAL_RAY_QUERY = 1 << 32;
1052        /// Enables 64-bit floating point types in SPIR-V shaders.
1053        ///
1054        /// Note: even when supported by GPU hardware, 64-bit floating point operations are
1055        /// frequently between 16 and 64 _times_ slower than equivalent operations on 32-bit floats.
1056        ///
1057        /// Supported Platforms:
1058        /// - Vulkan
1059        ///
1060        /// This is a native only feature.
1061        #[name("wgpu-shader-f64", "shader-f64")]
1062        const SHADER_F64 = 1 << 33;
1063        /// Allows shaders to use `i16` and `u16` 16-bit integer types.
1064        ///
1065        /// Requires `enable wgpu_int16;` in WGSL shaders.
1066        ///
1067        /// Supported platforms:
1068        /// - Vulkan (with `shaderInt16` and `VK_KHR_16bit_storage`)
1069        /// - Metal (always available)
1070        /// - DX12 (with `Native16BitShaderOpsSupported`, SM 6.2+)
1071        ///
1072        /// This is a native only feature.
1073        #[name("wgpu-shader-i16", "shader-i16")]
1074        const SHADER_I16 = 1 << 34;
1075
1076        // Bit 35 is used by VULKAN_EXTERNAL_MEMORY_FD.
1077
1078        /// Allows shaders to use the `early_depth_test` attribute.
1079        ///
1080        /// The attribute is applied to the fragment shader entry point. It can be used in two
1081        /// ways:
1082        ///
1083        ///   1. Force early depth/stencil tests:
1084        ///
1085        ///      - `@early_depth_test(force)` (WGSL)
1086        ///
1087        ///      - `layout(early_fragment_tests) in;` (GLSL)
1088        ///
1089        ///   2. Provide a conservative depth specifier that allows an additional early
1090        ///      depth test under certain conditions:
1091        ///
1092        ///      - `@early_depth_test(greater_equal/less_equal/unchanged)` (WGSL)
1093        ///
1094        ///      - `layout(depth_<greater/less/unchanged>) out float gl_FragDepth;` (GLSL)
1095        ///
1096        /// See [`EarlyDepthTest`] for more details.
1097        ///
1098        /// Supported platforms:
1099        /// - Vulkan
1100        /// - GLES 3.1+
1101        ///
1102        /// This is a native only feature.
1103        ///
1104        /// [`EarlyDepthTest`]: https://docs.rs/naga/latest/naga/ir/enum.EarlyDepthTest.html
1105        #[name("wgpu-shader-early-depth-test", "shader-early-depth-test")]
1106        const SHADER_EARLY_DEPTH_TEST = 1 << 36;
1107        /// Allows shaders to use i64 and u64.
1108        ///
1109        /// Supported platforms:
1110        /// - Vulkan
1111        /// - DX12 (DXC only)
1112        /// - Metal (with MSL 2.3+)
1113        ///
1114        /// This is a native only feature.
1115        #[name("wgpu-shader-int64")]
1116        const SHADER_INT64 = 1 << 37;
1117        /// Allows compute and fragment shaders to use the subgroup operation
1118        /// built-ins and perform subgroup operations (except barriers).
1119        ///
1120        /// Supported Platforms:
1121        /// - Vulkan
1122        /// - DX12
1123        /// - Metal
1124        ///
1125        /// The `subgroups` feature has been added to WebGPU, but there may be
1126        /// differences between the standard and the `wgpu` implementation,
1127        /// so it remains a native-only feature in wgpu for now.
1128        /// See <https://github.com/gfx-rs/wgpu/issues/5555>.
1129        ///
1130        /// Because it is expected to move to the WebGPU feature set in the
1131        /// not-too-distant future, the name omits the `wgpu-` prefix.
1132        #[name("subgroups")]
1133        const SUBGROUP = 1 << 38;
1134        /// Allows vertex shaders to use the subgroup operation built-ins and
1135        /// perform subgroup operations (except barriers).
1136        ///
1137        /// Supported Platforms:
1138        /// - Vulkan
1139        ///
1140        /// This is a native only feature.
1141        #[name("wgpu-subgroup-vertex")]
1142        const SUBGROUP_VERTEX = 1 << 39;
1143        /// Allows compute shaders to use the subgroup barrier.
1144        ///
1145        /// Requires [`Features::SUBGROUP`]. Without it, enables nothing.
1146        ///
1147        /// Supported Platforms:
1148        /// - Vulkan
1149        /// - Metal
1150        ///
1151        /// This is a native only feature.
1152        #[name("wgpu-subgroup-barrier")]
1153        const SUBGROUP_BARRIER = 1 << 40;
1154        /// Allows the use of pipeline cache objects
1155        ///
1156        /// Supported platforms:
1157        /// - Vulkan
1158        ///
1159        /// Unimplemented Platforms:
1160        /// - DX12
1161        /// - Metal
1162        #[name("wgpu-pipeline-cache")]
1163        const PIPELINE_CACHE = 1 << 41;
1164        /// Allows shaders to use i64 and u64 atomic min and max.
1165        ///
1166        /// Supported platforms:
1167        /// - Vulkan (with VK_KHR_shader_atomic_int64)
1168        /// - DX12 (with SM 6.6+)
1169        /// - Metal (with MSL 2.4+)
1170        ///
1171        /// This is a native only feature.
1172        #[name("wgpu-shader-int64-atomic-min-max")]
1173        const SHADER_INT64_ATOMIC_MIN_MAX = 1 << 42;
1174        /// Allows shaders to use all i64 and u64 atomic operations.
1175        ///
1176        /// Supported platforms:
1177        /// - Vulkan (with VK_KHR_shader_atomic_int64)
1178        /// - DX12 (with SM 6.6+)
1179        ///
1180        /// This is a native only feature.
1181        #[name("wgpu-shader-int64-atomic-all-ops")]
1182        const SHADER_INT64_ATOMIC_ALL_OPS = 1 << 43;
1183        /// Allows using the [VK_GOOGLE_display_timing] Vulkan extension.
1184        ///
1185        /// This is used for frame pacing to reduce latency, and is generally only available on Android.
1186        ///
1187        /// This feature does not have a `wgpu`-level API, and so users of wgpu wishing
1188        /// to use this functionality must access it using various `as_hal` functions,
1189        /// primarily [`Surface::as_hal()`], to then use.
1190        ///
1191        /// Supported platforms:
1192        /// - Vulkan (with [VK_GOOGLE_display_timing])
1193        ///
1194        /// This is a native only feature.
1195        ///
1196        /// [VK_GOOGLE_display_timing]: https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_GOOGLE_display_timing.html
1197        #[doc = link_to_wgpu_docs!(["`Surface::as_hal()`"]: "struct.Surface.html#method.as_hal")]
1198        #[name("wgpu-vulkan-google-display-timing")]
1199        const VULKAN_GOOGLE_DISPLAY_TIMING = 1 << 44;
1200
1201        /// Allows using the [VK_KHR_external_memory_win32] Vulkan extension.
1202        ///
1203        /// Supported platforms:
1204        /// - Vulkan (with [VK_KHR_external_memory_win32])
1205        ///
1206        /// This is a native only feature.
1207        ///
1208        /// [VK_KHR_external_memory_win32]: https://registry.khronos.org/vulkan/specs/latest/man/html/VK_KHR_external_memory_win32.html
1209        #[name("wgpu-vulkan-external-memory-win32")]
1210        const VULKAN_EXTERNAL_MEMORY_WIN32 = 1 << 45;
1211
1212        /// Allows using the [VK_KHR_external_memory_fd] Vulkan extension.
1213        ///
1214        /// Supported platforms:
1215        /// - Vulkan (with [VK_KHR_external_memory_fd])
1216        ///
1217        /// This is a native only feature.
1218        ///
1219        /// [VK_KHR_external_memory_fd]: https://registry.khronos.org/vulkan/specs/latest/man/html/VK_KHR_external_memory_fd.html
1220        #[name("wgpu-vulkan-external-memory-fd")]
1221        const VULKAN_EXTERNAL_MEMORY_FD = 1 << 35;
1222
1223        /// Allows using the [VK_EXT_external_memory_dma_buf] Vulkan extension
1224        /// for importing DMA-buf textures on Linux.
1225        ///
1226        /// Requires [VK_EXT_image_drm_format_modifier] for specifying the
1227        /// DRM format modifier and plane layout during import.
1228        ///
1229        /// Supported platforms:
1230        /// - Vulkan (with [VK_EXT_external_memory_dma_buf] and [VK_EXT_image_drm_format_modifier])
1231        ///
1232        /// This is a native only feature.
1233        ///
1234        /// [VK_EXT_external_memory_dma_buf]: https://registry.khronos.org/vulkan/specs/latest/man/html/VK_EXT_external_memory_dma_buf.html
1235        /// [VK_EXT_image_drm_format_modifier]: https://registry.khronos.org/vulkan/specs/latest/man/html/VK_EXT_image_drm_format_modifier.html
1236        #[name("wgpu-vulkan-external-memory-dma-buf")]
1237        const VULKAN_EXTERNAL_MEMORY_DMA_BUF = 1 << 63;
1238
1239        /// Enables R64Uint image atomic min and max.
1240        ///
1241        /// Supported platforms:
1242        /// - Vulkan (with VK_EXT_shader_image_atomic_int64)
1243        /// - DX12 (with SM 6.6+)
1244        /// - Metal (with MSL 3.1+)
1245        ///
1246        /// This is a native only feature.
1247        #[name("wgpu-texture-int64-atomic")]
1248        const TEXTURE_INT64_ATOMIC = 1 << 46;
1249
1250        /// Allows uniform buffers to be bound as binding arrays.
1251        ///
1252        /// This allows:
1253        /// - Shaders to contain `var<uniform> buffer: binding_array<UniformBuffer>;`
1254        /// - The `count` field of `BindGroupLayoutEntry`s with `Uniform` buffers, to be set to `Some`.
1255        ///
1256        /// Supported platforms:
1257        /// - None (<https://github.com/gfx-rs/wgpu/issues/7149>)
1258        ///
1259        /// Potential Platforms:
1260        /// - DX12
1261        /// - Metal
1262        /// - Vulkan 1.2+ (or VK_EXT_descriptor_indexing)'s `shaderUniformBufferArrayNonUniformIndexing` feature)
1263        ///
1264        /// This is a native only feature.
1265        #[name("wgpu-uniform-buffer-binding-arrays", "uniform-buffer-binding-arrays")]
1266        const UNIFORM_BUFFER_BINDING_ARRAYS = 1 << 47;
1267
1268        /// Enables mesh shaders and task shaders in mesh shader pipelines. This extension does NOT imply support for
1269        /// compiling mesh shaders at runtime.
1270        ///
1271        /// Supported platforms:
1272        /// - Vulkan (with [VK_EXT_mesh_shader](https://registry.khronos.org/vulkan/specs/latest/man/html/VK_EXT_mesh_shader.html))
1273        /// - DX12
1274        /// - Metal
1275        ///
1276        /// Naga is only supported on vulkan. On other platforms you will have to use passthrough shaders.
1277        ///
1278        /// It is recommended to use [`Device::create_shader_module_trusted`] with [`ShaderRuntimeChecks::unchecked()`]
1279        /// to avoid workgroup memory zero initialization, which can be expensive due to zero initialization being
1280        /// single-threaded currently.
1281        ///
1282        /// Some Mesa drivers including LLVMPIPE but not RADV fail to run the naga generated code.
1283        /// [This may be our bug and will be investigated.](https://github.com/gfx-rs/wgpu/issues/8727)
1284        /// However, due to the nature of the failure, the fact that it is unique, and the random changes
1285        /// that make it go away, this is believed to be a Mesa bug. See
1286        /// [this Mesa issue.](https://gitlab.freedesktop.org/mesa/mesa/-/issues/14376)
1287        ///
1288        /// This is a native only feature.
1289        ///
1290        /// [`Device::create_shader_module_trusted`]: https://docs.rs/wgpu/latest/wgpu/struct.Device.html#method.create_shader_module_trusted
1291        /// [`ShaderRuntimeChecks::unchecked()`]: crate::ShaderRuntimeChecks::unchecked
1292        #[name("wgpu-mesh-shader")]
1293        const EXPERIMENTAL_MESH_SHADER = 1 << 48;
1294
1295        /// ***THIS IS EXPERIMENTAL:*** Features enabled by this may have
1296        /// major bugs in them and are expected to be subject to breaking changes, suggestions
1297        /// for the API exposed by this should be posted on [the ray-tracing issue](https://github.com/gfx-rs/wgpu/issues/6762)
1298        ///
1299        /// Allows for returning of the hit triangle's vertex position when tracing with an
1300        /// acceleration structure marked with [`AccelerationStructureFlags::ALLOW_RAY_HIT_VERTEX_RETURN`].
1301        ///
1302        /// Supported platforms:
1303        /// - Vulkan
1304        ///
1305        /// This is a native only feature
1306        ///
1307        /// [`AccelerationStructureFlags::ALLOW_RAY_HIT_VERTEX_RETURN`]: super::AccelerationStructureFlags::ALLOW_RAY_HIT_VERTEX_RETURN
1308        #[name("wgpu-ray-hit-vertex-return")]
1309        const EXPERIMENTAL_RAY_HIT_VERTEX_RETURN = 1 << 49;
1310
1311        /// Enables multiview in mesh shader pipelines
1312        ///
1313        /// Supported platforms:
1314        /// - Vulkan (with [VK_EXT_mesh_shader](https://registry.khronos.org/vulkan/specs/latest/man/html/VK_EXT_mesh_shader.html))
1315        ///
1316        /// Potential Platforms:
1317        /// - DX12
1318        /// - Metal
1319        ///
1320        /// This is a native only feature.
1321        #[name("wgpu-mesh-shader-multiview")]
1322        const EXPERIMENTAL_MESH_SHADER_MULTIVIEW = 1 << 50;
1323
1324        /// Allows usage of additional vertex formats in [BlasTriangleGeometrySizeDescriptor::vertex_format]
1325        ///
1326        /// Supported platforms
1327        /// - Vulkan
1328        /// - DX12
1329        ///
1330        /// [BlasTriangleGeometrySizeDescriptor::vertex_format]: super::BlasTriangleGeometrySizeDescriptor
1331        #[name("wgpu-extended-acceleration-structure-vertex-formats")]
1332        const EXTENDED_ACCELERATION_STRUCTURE_VERTEX_FORMATS = 1 << 51;
1333
1334        /// Enables creating shaders from passthrough with reflection info (unsafe)
1335        ///
1336        /// Allows using [`Device::create_shader_module_passthrough`].
1337        /// Shader code isn't parsed or interpreted in any way. It is the user's
1338        /// responsibility to ensure the code and reflection (if passed) are correct.
1339        ///
1340        /// Supported platforms
1341        /// - Vulkan
1342        /// - DX12
1343        /// - Metal
1344        /// - WebGPU
1345        ///
1346        /// Ideally, in the future, all platforms will be supported. For more info, see
1347        /// [this comment](https://github.com/gfx-rs/wgpu/issues/3103#issuecomment-2833058367).
1348        ///
1349        #[doc = link_to_wgpu_docs!(["`Device::create_shader_module_passthrough`"]: "struct.Device.html#method.create_shader_module_passthrough")]
1350        #[name("wgpu-passthrough-shaders", "passthrough-shaders")]
1351        const PASSTHROUGH_SHADERS = 1 << 52;
1352
1353        /// Enables shader barycentric coordinates.
1354        ///
1355        /// Supported platforms:
1356        /// - Vulkan (with VK_KHR_fragment_shader_barycentric)
1357        /// - DX12 (with SM 6.1+)
1358        /// - Metal (with MSL 2.2+)
1359        ///
1360        /// This is a native only feature.
1361        #[name("wgpu-shader-barycentrics")]
1362        const SHADER_BARYCENTRICS = 1 << 53;
1363
1364        /// Enables using multiview where not all texture array layers are rendered to in a single render pass/render pipeline. Making
1365        /// use of this feature also requires enabling `Features::MULTIVIEW`.
1366        ///
1367        /// Supported platforms
1368        /// - Vulkan
1369        /// - DX12
1370        ///
1371        ///
1372        /// While metal supports this in theory, the behavior of `view_index` differs from vulkan and dx12 so the feature isn't exposed.
1373        #[name("wgpu-selective-multiview")]
1374        const SELECTIVE_MULTIVIEW = 1 << 54;
1375
1376        /// Enables the use of point-primitive outputs from mesh shaders. Making use of this feature also requires enabling
1377        /// `Features::EXPERIMENTAL_MESH_SHADER`.
1378        ///
1379        /// Supported platforms
1380        /// - Vulkan
1381        /// - Metal
1382        ///
1383        /// This is a native only feature.
1384        #[name("wgpu-mesh-shader-points")]
1385        const EXPERIMENTAL_MESH_SHADER_POINTS = 1 << 55;
1386
1387        /// Enables creating texture arrays that are also multisampled.
1388        ///
1389        /// Without this feature, you cannot create a texture that has both a `sample_count` higher
1390        /// than 1, and a `depth_or_array_layers` higher than 1.
1391        ///
1392        /// Supported platforms:
1393        /// - Vulkan (except VK_KHR_portability_subset if multisampleArrayImage is not available)
1394        /// - Metal (with macos 10.14+, ios 14.0+, tvos 16.0+, visionos 1.0+)
1395        #[name("wgpu-multisample-array")]
1396        const MULTISAMPLE_ARRAY = 1 << 56;
1397
1398        /// Enables cooperative matrix operations (also known as tensor cores on NVIDIA GPUs
1399        /// or simdgroup matrix operations on Apple GPUs).
1400        ///
1401        /// Cooperative matrices allow a workgroup to collectively load, store, and perform
1402        /// matrix multiply-accumulate operations on small tiles of data, enabling
1403        /// hardware-accelerated matrix math.
1404        ///
1405        /// **Current limitations:** The implementation currently only supports 8x8 f32 matrices.
1406        /// On Vulkan, support is determined by querying `vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR`
1407        /// for configurations matching 8x8x8 f32. Most Vulkan implementations (NVIDIA, AMD) primarily
1408        /// support f16 inputs at larger sizes (e.g., 16x16), so Vulkan support may be limited.
1409        ///
1410        /// Supported platforms:
1411        /// - Metal (with MSL 2.3+ and Apple7+/Mac2+, using simdgroup matrix operations)
1412        /// - Vulkan (with [VK_KHR_cooperative_matrix](https://registry.khronos.org/vulkan/specs/latest/man/html/VK_KHR_cooperative_matrix.html), if 8x8 f32 is supported)
1413        ///
1414        /// This is a native only feature.
1415        #[name("wgpu-cooperative-matrix")]
1416        const EXPERIMENTAL_COOPERATIVE_MATRIX = 1 << 57;
1417
1418        /// Enables shader per-vertex attributes.
1419        ///
1420        /// Supported platforms:
1421        /// - Vulkan (with VK_KHR_fragment_shader_barycentric)
1422        ///
1423        /// This is a native only feature.
1424        #[name("wgpu-shader-per-vertex")]
1425        const SHADER_PER_VERTEX = 1 << 58;
1426
1427        /// Enables shader `draw_index` builtin.
1428        ///
1429        /// Supported platforms:
1430        /// - GLES
1431        /// - Vulkan
1432        ///
1433        /// Potential platforms:
1434        /// - DX12
1435        /// - Metal
1436        ///
1437        /// This is a native only feature.
1438        #[name("wgpu-shader-draw-index")]
1439        const SHADER_DRAW_INDEX = 1 << 59;
1440        /// Allows the user to create arrays of acceleration structures in shaders:
1441        ///
1442        /// ex.
1443        /// - `var tlas: binding_array<acceleration_structure, 10>` (WGSL)
1444        ///
1445        /// This capability allows them to exist and to be indexed by dynamically uniform values.
1446        ///
1447        /// Supported platforms:
1448        /// - DX12
1449        /// - Vulkan
1450        ///
1451        /// This is a native only feature.
1452        #[name("wgpu-acceleration-structure-binding-array")]
1453        const ACCELERATION_STRUCTURE_BINDING_ARRAY = 1 << 60;
1454
1455        /// Enables the `@coherent` memory decoration on storage buffer variables.
1456        ///
1457        /// Backend mapping:
1458        /// - Vulkan
1459        /// - DX12
1460        /// - Metal (3.2+)
1461        /// - GLES (ES 3.1+ / GL 4.3+)
1462        ///
1463        /// This is a native only feature.
1464        #[name("wgpu-memory-decoration-coherent")]
1465        const MEMORY_DECORATION_COHERENT = 1 << 61;
1466
1467        /// Enables the `@volatile` memory decoration on storage buffer variables.
1468        ///
1469        /// Backend mapping:
1470        /// - Vulkan
1471        /// - GLES (ES 3.1+ / GL 4.3+)
1472        ///
1473        /// This is a native only feature.
1474        #[name("wgpu-memory-decoration-volatile")]
1475        const MEMORY_DECORATION_VOLATILE = 1 << 62;
1476
1477        // Adding a new feature? All bits in the first u64 are used. Use the second u64 (bits 64+).
1478    }
1479
1480    /// Features that are not guaranteed to be supported.
1481    ///
1482    /// These are part of the WebGPU standard. For all features, see [`Features`].
1483    ///
1484    /// If you want to use a feature, you need to first verify that the adapter supports
1485    /// the feature. If the adapter does not support the feature, requesting a device with it enabled
1486    /// will panic.
1487    ///
1488    /// Corresponds to [WebGPU `GPUFeatureName`](
1489    /// https://gpuweb.github.io/gpuweb/#enumdef-gpufeaturename).
1490    #[repr(transparent)]
1491    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1492    #[cfg_attr(feature = "serde", serde(transparent))]
1493    #[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash)]
1494    pub struct FeaturesWebGPU features_webgpu {
1495        // API:
1496
1497        /// By default, polygon depth is clipped to 0-1 range before/during rasterization.
1498        /// Anything outside of that range is rejected, and respective fragments are not touched.
1499        ///
1500        /// With this extension, we can disabling clipping. That allows
1501        /// shadow map occluders to be rendered into a tighter depth range.
1502        ///
1503        /// Supported platforms:
1504        /// - desktops
1505        /// - some mobile chips
1506        /// - WebGPU
1507        ///
1508        /// This is a web and native feature.
1509        #[name("depth-clip-control")]
1510        const DEPTH_CLIP_CONTROL = WEBGPU_FEATURE_DEPTH_CLIP_CONTROL;
1511
1512        /// Allows for explicit creation of textures of format [`TextureFormat::Depth32FloatStencil8`]
1513        ///
1514        /// Supported platforms:
1515        /// - Vulkan (mostly)
1516        /// - DX12
1517        /// - Metal
1518        /// - OpenGL
1519        /// - WebGPU
1520        ///
1521        /// This is a web and native feature.
1522        ///
1523        /// [`TextureFormat::Depth32FloatStencil8`]: super::TextureFormat::Depth32FloatStencil8
1524        #[name("depth32float-stencil8")]
1525        const DEPTH32FLOAT_STENCIL8 = WEBGPU_FEATURE_DEPTH32FLOAT_STENCIL8;
1526
1527        /// Enables BCn family of compressed textures. All BCn textures use 4x4 pixel blocks
1528        /// with 8 or 16 bytes per block.
1529        ///
1530        /// Compressed textures sacrifice some quality in exchange for significantly reduced
1531        /// bandwidth usage.
1532        ///
1533        /// Support for this feature guarantees availability of [`TextureUsages::COPY_SRC | TextureUsages::COPY_DST | TextureUsages::TEXTURE_BINDING`] for BCn formats.
1534        /// [`Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES`] may enable additional usages.
1535        ///
1536        /// This feature guarantees availability of sliced-3d textures for BC formats when combined with TEXTURE_COMPRESSION_BC_SLICED_3D.
1537        ///
1538        /// Supported Platforms:
1539        /// - desktops
1540        /// - Mobile (All Apple9 and some Apple7 and Apple8 devices)
1541        /// - WebGPU
1542        ///
1543        /// This is a web and native feature.
1544        #[name("texture-compression-bc")]
1545        const TEXTURE_COMPRESSION_BC = WEBGPU_FEATURE_TEXTURE_COMPRESSION_BC;
1546
1547
1548        /// Allows the 3d dimension for textures with BC compressed formats.
1549        ///
1550        /// This feature must be used in combination with TEXTURE_COMPRESSION_BC to enable 3D textures with BC compression.
1551        /// It does not enable the BC formats by itself.
1552        ///
1553        /// Supported Platforms:
1554        /// - desktops
1555        /// - Mobile (All Apple9 and some Apple7 and Apple8 devices)
1556        /// - WebGPU
1557        ///
1558        /// This is a web and native feature.
1559        #[name("texture-compression-bc-sliced-3d")]
1560        const TEXTURE_COMPRESSION_BC_SLICED_3D = WEBGPU_FEATURE_TEXTURE_COMPRESSION_BC_SLICED_3D;
1561
1562        /// Enables ETC family of compressed textures. All ETC textures use 4x4 pixel blocks.
1563        /// ETC2 RGB and RGBA1 are 8 bytes per block. RTC2 RGBA8 and EAC are 16 bytes per block.
1564        ///
1565        /// Compressed textures sacrifice some quality in exchange for significantly reduced
1566        /// bandwidth usage.
1567        ///
1568        /// Support for this feature guarantees availability of [`TextureUsages::COPY_SRC | TextureUsages::COPY_DST | TextureUsages::TEXTURE_BINDING`] for ETC2 formats.
1569        /// [`Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES`] may enable additional usages.
1570        ///
1571        /// Supported Platforms:
1572        /// - Vulkan on Intel
1573        /// - Mobile (some)
1574        /// - WebGPU
1575        ///
1576        /// This is a web and native feature.
1577        #[name("texture-compression-etc2")]
1578        const TEXTURE_COMPRESSION_ETC2 = WEBGPU_FEATURE_TEXTURE_COMPRESSION_ETC2;
1579
1580        /// Enables ASTC family of compressed textures. ASTC textures use pixel blocks varying from 4x4 to 12x12.
1581        /// Blocks are always 16 bytes.
1582        ///
1583        /// Compressed textures sacrifice some quality in exchange for significantly reduced
1584        /// bandwidth usage.
1585        ///
1586        /// Support for this feature guarantees availability of [`TextureUsages::COPY_SRC | TextureUsages::COPY_DST | TextureUsages::TEXTURE_BINDING`] for ASTC formats with Unorm/UnormSrgb channel type.
1587        /// [`Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES`] may enable additional usages.
1588        ///
1589        /// This feature does not guarantee availability of sliced 3d textures for ASTC formats.
1590        /// If available, 3d support can be enabled by TEXTURE_COMPRESSION_ASTC_SLICED_3D feature.
1591        ///
1592        /// Supported Platforms:
1593        /// - Vulkan on Intel
1594        /// - Mobile (some)
1595        /// - WebGPU
1596        ///
1597        /// This is a web and native feature.
1598        #[name("texture-compression-astc")]
1599        const TEXTURE_COMPRESSION_ASTC = WEBGPU_FEATURE_TEXTURE_COMPRESSION_ASTC;
1600
1601
1602        /// Allows the 3d dimension for textures with ASTC compressed formats.
1603        ///
1604        /// This feature must be used in combination with TEXTURE_COMPRESSION_ASTC to enable 3D textures with ASTC compression.
1605        /// It does not enable the ASTC formats by itself.
1606        ///
1607        /// Supported Platforms:
1608        /// - Vulkan (some)
1609        /// - Metal on Apple3+
1610        /// - OpenGL/WebGL (some)
1611        /// - WebGPU
1612        ///
1613        /// Not Supported:
1614        /// - DX12
1615        ///
1616        /// This is a web and native feature.
1617        #[name("texture-compression-astc-sliced-3d")]
1618        const TEXTURE_COMPRESSION_ASTC_SLICED_3D = WEBGPU_FEATURE_TEXTURE_COMPRESSION_ASTC_SLICED_3D;
1619
1620        /// Enables use of Timestamp Queries. These queries tell the current gpu timestamp when
1621        /// all work before the query is finished.
1622        ///
1623        /// This feature allows the use of
1624        /// - [`RenderPassDescriptor::timestamp_writes`]
1625        /// - [`ComputePassDescriptor::timestamp_writes`]
1626        /// to write out timestamps.
1627        ///
1628        /// For arbitrary timestamp write commands on encoders refer to [`Features::TIMESTAMP_QUERY_INSIDE_ENCODERS`].
1629        /// For arbitrary timestamp write commands on passes refer to [`Features::TIMESTAMP_QUERY_INSIDE_PASSES`].
1630        ///
1631        /// They must be resolved using [`CommandEncoder::resolve_query_set`] into a buffer,
1632        /// then the result must be multiplied by the timestamp period [`Queue::get_timestamp_period`]
1633        /// to get the timestamp in nanoseconds. Multiple timestamps can then be diffed to get the
1634        /// time for operations between them to finish.
1635        ///
1636        /// Supported Platforms:
1637        /// - Vulkan
1638        /// - DX12
1639        /// - Metal
1640        /// - OpenGL (with GL_ARB_timer_query)
1641        /// - WebGPU
1642        ///
1643        /// This is a web and native feature.
1644        ///
1645        #[doc = link_to_wgpu_docs!(["`RenderPassDescriptor::timestamp_writes`"]: "struct.RenderPassDescriptor.html#structfield.timestamp_writes")]
1646        #[doc = link_to_wgpu_docs!(["`ComputePassDescriptor::timestamp_writes`"]: "struct.ComputePassDescriptor.html#structfield.timestamp_writes")]
1647        #[doc = link_to_wgpu_docs!(["`CommandEncoder::resolve_query_set`"]: "struct.CommandEncoder.html#method.resolve_query_set")]
1648        #[doc = link_to_wgpu_docs!(["`Queue::get_timestamp_period`"]: "struct.Queue.html#method.get_timestamp_period")]
1649        #[name("timestamp-query")]
1650        const TIMESTAMP_QUERY = WEBGPU_FEATURE_TIMESTAMP_QUERY;
1651
1652        /// Allows non-zero value for the `first_instance` member in indirect draw calls.
1653        ///
1654        /// If this feature is not enabled, and the `first_instance` member is non-zero, the behavior may be:
1655        /// - The draw call is ignored.
1656        /// - The draw call is executed as if the `first_instance` is zero.
1657        /// - The draw call is executed with the correct `first_instance` value.
1658        ///
1659        /// Supported Platforms:
1660        /// - Vulkan (mostly)
1661        /// - DX12
1662        /// - Metal on Apple3+ or Mac1+
1663        /// - OpenGL (Desktop 4.2+ with ARB_shader_draw_parameters only)
1664        /// - WebGPU
1665        ///
1666        /// Not Supported:
1667        /// - OpenGL ES / WebGL
1668        ///
1669        /// This is a web and native feature.
1670        #[name("indirect-first-instance")]
1671        const INDIRECT_FIRST_INSTANCE = WEBGPU_FEATURE_INDIRECT_FIRST_INSTANCE;
1672
1673        /// Allows shaders to use 16-bit floating point types. You may use them uniform buffers,
1674        /// storage buffers, and local variables. You may not use them in immediates.
1675        ///
1676        /// In order to use this in WGSL shaders, you must add `enable f16;` to the top of your shader,
1677        /// before any global items.
1678        ///
1679        /// Supported Platforms:
1680        /// - Vulkan
1681        /// - Metal
1682        /// - DX12
1683        /// - WebGPU
1684        ///
1685        /// This is a web and native feature.
1686        #[name("shader-f16")]
1687        const SHADER_F16 = WEBGPU_FEATURE_SHADER_F16;
1688
1689        /// Allows for usage of textures of format [`TextureFormat::Rg11b10Ufloat`] as a render target
1690        ///
1691        /// Supported platforms:
1692        /// - Vulkan
1693        /// - DX12
1694        /// - Metal
1695        /// - WebGPU
1696        ///
1697        /// This is a web and native feature.
1698        ///
1699        /// [`TextureFormat::Rg11b10Ufloat`]: super::TextureFormat::Rg11b10Ufloat
1700        #[name("rg11b10ufloat-renderable")]
1701        const RG11B10UFLOAT_RENDERABLE = WEBGPU_FEATURE_RG11B10UFLOAT_RENDERABLE;
1702
1703        /// Allows the [`TextureUsages::STORAGE_BINDING`] usage on textures with format [`TextureFormat::Bgra8Unorm`]
1704        ///
1705        /// Supported Platforms:
1706        /// - Vulkan
1707        /// - DX12
1708        /// - Metal
1709        /// - WebGPU
1710        ///
1711        /// This is a web and native feature.
1712        ///
1713        /// [`TextureFormat::Bgra8Unorm`]: super::TextureFormat::Bgra8Unorm
1714        /// [`TextureUsages::STORAGE_BINDING`]: super::TextureUsages::STORAGE_BINDING
1715        #[name("bgra8unorm-storage")]
1716        const BGRA8UNORM_STORAGE = WEBGPU_FEATURE_BGRA8UNORM_STORAGE;
1717
1718
1719        /// Allows textures with formats "r32float", "rg32float", and "rgba32float" to be filterable.
1720        ///
1721        /// Supported Platforms:
1722        /// - Vulkan (mainly on Desktop GPUs)
1723        /// - DX12
1724        /// - Metal on macOS or Apple9+ GPUs, optional on iOS/iPadOS with Apple7/8 GPUs
1725        /// - GL with one of `GL_ARB_color_buffer_float`/`GL_EXT_color_buffer_float`/`OES_texture_float_linear`
1726        /// - WebGPU
1727        ///
1728        /// This is a web and native feature.
1729        #[name("float32-filterable")]
1730        const FLOAT32_FILTERABLE = WEBGPU_FEATURE_FLOAT32_FILTERABLE;
1731
1732        /// Allows textures with formats "r32float", "rg32float", and "rgba32float" to be blendable.
1733        ///
1734        /// Supported Platforms:
1735        /// - Vulkan
1736        /// - WebGPU
1737        #[name("float32-blendable")]
1738        const FLOAT32_BLENDABLE = WEBGPU_FEATURE_FLOAT32_BLENDABLE;
1739
1740        /// Allows two outputs from a shader to be used for blending.
1741        /// Note that dual-source blending doesn't support multiple render targets.
1742        ///
1743        /// For more info see the OpenGL ES extension GL_EXT_blend_func_extended.
1744        ///
1745        /// Supported platforms:
1746        /// - OpenGL ES (with GL_EXT_blend_func_extended)
1747        /// - Metal (with MSL 1.2+)
1748        /// - Vulkan (with dualSrcBlend)
1749        /// - DX12
1750        /// - WebGPU
1751        ///
1752        /// This is a web and native feature.
1753        #[name("dual-source-blending")]
1754        const DUAL_SOURCE_BLENDING = WEBGPU_FEATURE_DUAL_SOURCE_BLENDING;
1755
1756        /// Allows the use of `@builtin(clip_distances)` in WGSL.
1757        ///
1758        /// Supported platforms:
1759        /// - Vulkan (mainly on Desktop GPUs)
1760        /// - Metal
1761        /// - GL (Desktop or `GL_EXT_clip_cull_distance`)
1762        /// - WebGPU
1763        ///
1764        /// This is a web and native feature.
1765        #[name("clip-distances")]
1766        const CLIP_DISTANCES = WEBGPU_FEATURE_CLIP_DISTANCES;
1767
1768        /// Allows the use of immediate data: small, fast bits of memory that can be updated
1769        /// inside a [`RenderPass`].
1770        ///
1771        /// Allows the user to call [`RenderPass::set_immediates`], provide a non-zero immediate data size
1772        /// to [`PipelineLayoutDescriptor`], and provide a non-zero limit to [`Limits::max_immediate_size`].
1773        ///
1774        /// A block of immediate data can be declared in WGSL with `var<immediate>`:
1775        ///
1776        /// ```rust,ignore
1777        /// struct Immediates { example: f32, }
1778        /// var<immediate> c: Immediates;
1779        /// ```
1780        ///
1781        /// In GLSL, this corresponds to `layout(immediates) uniform Name {..}`.
1782        ///
1783        /// Supported platforms:
1784        /// - DX12
1785        /// - Vulkan
1786        /// - Metal
1787        /// - OpenGL (emulated with uniforms)
1788        /// - WebGPU
1789        ///
1790        /// WebGPU support is currently a proposal and will be available in browsers in the future.
1791        ///
1792        /// This is a web and native feature.
1793        ///
1794        #[doc = link_to_wgpu_item!(struct RenderPass)]
1795        #[doc = link_to_wgpu_item!(struct PipelineLayoutDescriptor)]
1796        #[doc = link_to_wgpu_docs!(["`RenderPass::set_immediates`"]: "struct.RenderPass.html#method.set_immediates")]
1797        /// [`Limits::max_immediate_size`]: super::Limits
1798        #[name("immediates")]
1799        const IMMEDIATES = WEBGPU_FEATURE_IMMEDIATES;
1800
1801        /// Enables `builtin(primitive_index)` in fragment shaders.
1802        ///
1803        /// Note: enables geometry processing for pipelines using the builtin.
1804        /// This may come with a significant performance impact on some hardware.
1805        /// Other pipelines are not affected.
1806        ///
1807        /// Supported platforms:
1808        /// - Vulkan (with geometryShader)
1809        /// - DX12
1810        /// - Metal (some)
1811        /// - OpenGL (some)
1812        ///
1813        /// This is a web and native feature. `primitive-index` is its
1814        /// WebGPU-defined name, and `shader-primitive-index` is accepted to
1815        /// remain compatible with previous wgpu behavior.
1816        #[name("primitive-index", "shader-primitive-index")]
1817        const PRIMITIVE_INDEX = WEBGPU_FEATURE_PRIMITIVE_INDEX;
1818    }
1819}
1820
1821impl Features {
1822    /// Mask of all features which are part of the upstream WebGPU standard.
1823    #[must_use]
1824    pub const fn all_webgpu_mask() -> Self {
1825        Self::from_bits_truncate(FeatureBits([
1826            FeaturesWGPU::empty().bits(),
1827            FeaturesWebGPU::all().bits(),
1828        ]))
1829    }
1830
1831    /// Mask of all features that are only available when targeting native (not web).
1832    #[must_use]
1833    pub const fn all_native_mask() -> Self {
1834        Self::from_bits_truncate(FeatureBits([
1835            FeaturesWGPU::all().bits(),
1836            FeaturesWebGPU::empty().bits(),
1837        ]))
1838    }
1839
1840    /// Mask of all features which are experimental.
1841    #[must_use]
1842    pub const fn all_experimental_mask() -> Self {
1843        Self::from_bits_truncate(FeatureBits([
1844            FeaturesWGPU::EXPERIMENTAL_MESH_SHADER.bits()
1845                | FeaturesWGPU::EXPERIMENTAL_MESH_SHADER_MULTIVIEW.bits()
1846                | FeaturesWGPU::EXPERIMENTAL_MESH_SHADER_POINTS.bits()
1847                | FeaturesWGPU::EXPERIMENTAL_RAY_QUERY.bits()
1848                | FeaturesWGPU::EXPERIMENTAL_RAY_HIT_VERTEX_RETURN.bits()
1849                | FeaturesWGPU::EXPERIMENTAL_COOPERATIVE_MATRIX.bits(),
1850            FeaturesWebGPU::empty().bits(),
1851        ]))
1852    }
1853
1854    /// Vertex formats allowed for creating and building BLASes
1855    #[must_use]
1856    pub fn allowed_vertex_formats_for_blas(&self) -> Vec<VertexFormat> {
1857        let mut formats = Vec::new();
1858        if self.intersects(Self::EXPERIMENTAL_RAY_QUERY) {
1859            formats.push(VertexFormat::Float32x3);
1860        }
1861        if self.contains(Self::EXTENDED_ACCELERATION_STRUCTURE_VERTEX_FORMATS) {
1862            formats.push(VertexFormat::Float32x2);
1863            formats.push(VertexFormat::Float16x2);
1864            formats.push(VertexFormat::Float16x4);
1865            formats.push(VertexFormat::Snorm16x2);
1866            formats.push(VertexFormat::Snorm16x4);
1867        }
1868        formats
1869    }
1870}
1871
1872#[cfg(test)]
1873mod tests {
1874    use crate::{Features, FeaturesWGPU, FeaturesWebGPU};
1875    use bitflags::{Flag, Flags};
1876
1877    #[cfg(feature = "serde")]
1878    #[test]
1879    fn check_hex() {
1880        use crate::FeatureBits;
1881
1882        use bitflags::{
1883            parser::{ParseHex as _, WriteHex as _},
1884            Bits as _,
1885        };
1886
1887        let mut hex = alloc::string::String::new();
1888        FeatureBits::ALL.write_hex(&mut hex).unwrap();
1889        assert_eq!(
1890            FeatureBits::parse_hex(hex.as_str()).unwrap(),
1891            FeatureBits::ALL
1892        );
1893
1894        hex.clear();
1895        FeatureBits::EMPTY.write_hex(&mut hex).unwrap();
1896        assert_eq!(
1897            FeatureBits::parse_hex(hex.as_str()).unwrap(),
1898            FeatureBits::EMPTY
1899        );
1900
1901        for feature in Features::FLAGS {
1902            hex.clear();
1903            feature.value().bits().write_hex(&mut hex).unwrap();
1904            assert_eq!(
1905                FeatureBits::parse_hex(hex.as_str()).unwrap(),
1906                feature.value().bits(),
1907                "{hex}"
1908            );
1909        }
1910    }
1911
1912    #[test]
1913    fn check_features_display() {
1914        use alloc::format;
1915
1916        let feature = Features::CLEAR_TEXTURE;
1917        assert_eq!(format!("{feature}"), "CLEAR_TEXTURE");
1918
1919        let feature = Features::CLEAR_TEXTURE | Features::BGRA8UNORM_STORAGE;
1920        assert_eq!(format!("{feature}"), "CLEAR_TEXTURE | BGRA8UNORM_STORAGE");
1921    }
1922
1923    #[test]
1924    fn check_features_bits() {
1925        let bits = Features::all().bits();
1926        assert_eq!(Features::from_bits_retain(bits), Features::all());
1927
1928        let bits = Features::empty().bits();
1929        assert_eq!(Features::from_bits_retain(bits), Features::empty());
1930
1931        for feature in Features::FLAGS {
1932            let bits = feature.value().bits();
1933            assert_eq!(Features::from_bits_retain(bits), *feature.value());
1934        }
1935
1936        let bits = FeaturesWebGPU::all().bits();
1937        assert_eq!(
1938            FeaturesWebGPU::from_bits_truncate(bits),
1939            FeaturesWebGPU::all()
1940        );
1941
1942        let bits = FeaturesWebGPU::empty().bits();
1943        assert_eq!(
1944            FeaturesWebGPU::from_bits_truncate(bits),
1945            FeaturesWebGPU::empty()
1946        );
1947
1948        for feature in FeaturesWebGPU::FLAGS {
1949            let bits = feature.value().bits();
1950            assert_eq!(FeaturesWebGPU::from_bits_truncate(bits), *feature.value());
1951        }
1952
1953        let bits = FeaturesWGPU::all().bits();
1954        assert_eq!(FeaturesWGPU::from_bits(bits).unwrap(), FeaturesWGPU::all());
1955
1956        let bits = FeaturesWGPU::empty().bits();
1957        assert_eq!(
1958            FeaturesWGPU::from_bits(bits).unwrap(),
1959            FeaturesWGPU::empty()
1960        );
1961
1962        for feature in FeaturesWGPU::FLAGS {
1963            let bits = feature.value().bits();
1964            assert_eq!(FeaturesWGPU::from_bits(bits).unwrap(), *feature.value());
1965        }
1966    }
1967
1968    #[test]
1969    fn features_names() {
1970        for feature in Features::FLAGS.iter().map(Flag::value).copied() {
1971            let Some(name) = feature.as_str() else {
1972                panic!("`.as_str()` for {feature:?} returned `None`");
1973            };
1974            assert_eq!(name.parse(), Ok(feature));
1975
1976            // Native-only features that are accepted without `wgpu-` prefix for backwards compatibility
1977            let prefix_backcompat_features = [
1978                Features::TEXTURE_FORMAT_16BIT_NORM,
1979                Features::TEXTURE_COMPRESSION_ASTC_HDR,
1980                Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES,
1981                Features::PIPELINE_STATISTICS_QUERY,
1982                Features::TIMESTAMP_QUERY_INSIDE_PASSES,
1983                Features::MAPPABLE_PRIMARY_BUFFERS,
1984                Features::TEXTURE_BINDING_ARRAY,
1985                Features::BUFFER_BINDING_ARRAY,
1986                Features::STORAGE_RESOURCE_BINDING_ARRAY,
1987                Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING,
1988                Features::STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING,
1989                Features::UNIFORM_BUFFER_BINDING_ARRAYS,
1990                Features::PARTIALLY_BOUND_BINDING_ARRAY,
1991                Features::MULTI_DRAW_INDIRECT_COUNT,
1992                Features::ADDRESS_MODE_CLAMP_TO_ZERO,
1993                Features::ADDRESS_MODE_CLAMP_TO_BORDER,
1994                Features::POLYGON_MODE_LINE,
1995                Features::POLYGON_MODE_POINT,
1996                Features::CONSERVATIVE_RASTERIZATION,
1997                Features::VERTEX_WRITABLE_STORAGE,
1998                Features::CLEAR_TEXTURE,
1999                Features::MULTIVIEW,
2000                Features::VERTEX_ATTRIBUTE_64BIT,
2001                Features::EXTERNAL_TEXTURE,
2002                Features::SHADER_F64,
2003                Features::SHADER_I16,
2004                Features::SHADER_EARLY_DEPTH_TEST,
2005                Features::PASSTHROUGH_SHADERS,
2006            ];
2007
2008            if feature == Features::SUBGROUP {
2009                // Standard-track feature that does not have `wgpu-` prefix
2010                assert_eq!(name.parse(), Ok(feature));
2011            } else if feature & Features::all_native_mask() != Features::empty() {
2012                let stripped_name = name.strip_prefix("wgpu-").unwrap_or_else(|| {
2013                    panic!("Native feature `{name}` should have `wgpu-` prefix")
2014                });
2015                let expected = if prefix_backcompat_features.contains(&feature) {
2016                    Ok(feature)
2017                } else {
2018                    Err(())
2019                };
2020                assert_eq!(stripped_name.parse(), expected);
2021            }
2022
2023            // Special backcompat case
2024            if feature == Features::PRIMITIVE_INDEX {
2025                assert_eq!("shader-primitive-index".parse(), Ok(feature));
2026            }
2027        }
2028    }
2029
2030    #[test]
2031    fn create_features_from_parts() {
2032        let features: Features = FeaturesWGPU::TEXTURE_ATOMIC.into();
2033        assert_eq!(features, Features::TEXTURE_ATOMIC);
2034
2035        let features: Features = FeaturesWebGPU::TIMESTAMP_QUERY.into();
2036        assert_eq!(features, Features::TIMESTAMP_QUERY);
2037
2038        let features: Features = Features::from(FeaturesWGPU::TEXTURE_ATOMIC)
2039            | Features::from(FeaturesWebGPU::TIMESTAMP_QUERY);
2040        assert_eq!(
2041            features,
2042            Features::TEXTURE_ATOMIC | Features::TIMESTAMP_QUERY
2043        );
2044        assert_eq!(
2045            features,
2046            Features::from_internal_flags(
2047                FeaturesWGPU::TEXTURE_ATOMIC,
2048                FeaturesWebGPU::TIMESTAMP_QUERY
2049            )
2050        );
2051    }
2052
2053    #[test]
2054    fn experimental_features_part_of_experimental_mask() {
2055        for (name, feature) in Features::all().iter_names() {
2056            let prefixed_with_experimental = name.starts_with("EXPERIMENTAL_");
2057            let in_experimental_mask = Features::all_experimental_mask().contains(feature);
2058            assert_eq!(in_experimental_mask, prefixed_with_experimental);
2059        }
2060    }
2061}