Skip to main content

wgpu_types/
features.rs

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