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