wgpu_types/
features.rs

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