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