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