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