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