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