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