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