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