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