wgpu_types/
features.rs

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