wgpu_types/
lib.rs

1//! This library describes the API surface of WebGPU that is agnostic of the backend.
2//! This API is used for targeting both Web and Native.
3
4#![cfg_attr(docsrs, feature(doc_cfg))]
5#![allow(
6    // We don't use syntax sugar where it's not necessary.
7    clippy::match_like_matches_macro,
8)]
9#![warn(
10    clippy::ptr_as_ptr,
11    missing_docs,
12    unsafe_op_in_unsafe_fn,
13    unused_qualifications
14)]
15#![no_std]
16
17#[cfg(feature = "std")]
18extern crate std;
19
20extern crate alloc;
21
22use core::{fmt, hash::Hash, time::Duration};
23
24#[cfg(any(feature = "serde", test))]
25use serde::{Deserialize, Serialize};
26
27mod adapter;
28pub mod assertions;
29mod backend;
30mod binding;
31mod buffer;
32mod cast_utils;
33mod counters;
34mod device;
35mod env;
36pub mod error;
37mod features;
38pub mod instance;
39mod limits;
40pub mod math;
41mod origin_extent;
42mod ray_tracing;
43mod render;
44#[doc(hidden)] // without this we get spurious missing_docs warnings
45mod send_sync;
46mod shader;
47mod surface;
48mod texture;
49mod tokens;
50mod transfers;
51mod vertex;
52mod write_only;
53
54pub use adapter::*;
55pub use backend::*;
56pub use binding::*;
57pub use buffer::*;
58pub use counters::*;
59pub use device::*;
60pub use features::*;
61pub use instance::*;
62pub use limits::*;
63pub use origin_extent::*;
64pub use ray_tracing::*;
65pub use render::*;
66#[doc(hidden)]
67pub use send_sync::*;
68pub use shader::*;
69pub use surface::*;
70pub use texture::*;
71pub use tokens::*;
72pub use transfers::*;
73pub use vertex::*;
74pub use write_only::*;
75
76/// Create a Markdown link definition referring to the `wgpu` crate.
77///
78/// This macro should be used inside a `#[doc = ...]` attribute.
79/// The two arguments should be string literals or macros that expand to string literals.
80/// If the module in which the item using this macro is located is not the crate root,
81/// use the `../` syntax.
82///
83/// We cannot simply use rustdoc links to `wgpu` because it is one of our dependents.
84/// This link adapts to work in locally generated documentation (`cargo doc`) by default,
85/// and work with `docs.rs` URL structure when building for `docs.rs`.
86///
87/// Note: This macro cannot be used outside this crate, because `cfg(docsrs)` will not apply.
88#[cfg(not(docsrs))]
89macro_rules! link_to_wgpu_docs {
90    ([$reference:expr]: $url_path:expr) => {
91        concat!("[", $reference, "]: ../wgpu/", $url_path)
92    };
93
94    (../ [$reference:expr]: $url_path:expr) => {
95        concat!("[", $reference, "]: ../../wgpu/", $url_path)
96    };
97}
98#[cfg(docsrs)]
99macro_rules! link_to_wgpu_docs {
100    ($(../)? [$reference:expr]: $url_path:expr) => {
101        concat!(
102            "[",
103            $reference,
104            // URL path will have a base URL of https://docs.rs/
105            "]: /wgpu/",
106            // The version of wgpu-types is not necessarily the same as the version of wgpu
107            // if a patch release of either has been published, so we cannot use the full version
108            // number. docs.rs will interpret this single number as a Cargo-style version
109            // requirement and redirect to the latest compatible version.
110            //
111            // This technique would break if `wgpu` and `wgpu-types` ever switch to having distinct
112            // major version numbering. An alternative would be to hardcode the corresponding `wgpu`
113            // version, but that would give us another thing to forget to update.
114            env!("CARGO_PKG_VERSION_MAJOR"),
115            "/wgpu/",
116            $url_path
117        )
118    };
119}
120
121/// Create a Markdown link definition referring to an item in the `wgpu` crate.
122///
123/// This macro should be used inside a `#[doc = ...]` attribute.
124/// See [`link_to_wgpu_docs`] for more details.
125macro_rules! link_to_wgpu_item {
126    ($kind:ident $name:ident) => {
127        $crate::link_to_wgpu_docs!(
128            [concat!("`", stringify!($name), "`")]: concat!(stringify!($kind), ".", stringify!($name), ".html")
129        )
130    };
131}
132
133/// Create a Markdown link definition referring to the `wgpu_core` crate.
134///
135/// This macro should be used inside a `#[doc = ...]` attribute.
136/// See [`link_to_wgpu_docs`] for more details.
137#[cfg(not(docsrs))]
138macro_rules! link_to_wgc_docs {
139    ([$reference:expr]: $url_path:expr) => {
140        concat!("[", $reference, "]: ../wgpu_core/", $url_path)
141    };
142
143    (../ [$reference:expr]: $url_path:expr) => {
144        concat!("[", $reference, "]: ../../wgpu_core/", $url_path)
145    };
146}
147#[cfg(docsrs)]
148macro_rules! link_to_wgc_docs {
149    ($(../)? [$reference:expr]: $url_path:expr) => {
150        concat!(
151            "[",
152            $reference,
153            // URL path will have a base URL of https://docs.rs/
154            "]: /wgpu_core/",
155            // The version of wgpu-types is not necessarily the same as the version of wgpu_core
156            // if a patch release of either has been published, so we cannot use the full version
157            // number. docs.rs will interpret this single number as a Cargo-style version
158            // requirement and redirect to the latest compatible version.
159            //
160            // This technique would break if `wgpu_core` and `wgpu-types` ever switch to having
161            // distinct major version numbering. An alternative would be to hardcode the
162            // corresponding `wgpu_core` version, but that would give us another thing to forget
163            // to update.
164            env!("CARGO_PKG_VERSION_MAJOR"),
165            "/wgpu_core/",
166            $url_path
167        )
168    };
169}
170
171pub(crate) use {link_to_wgc_docs, link_to_wgpu_docs, link_to_wgpu_item};
172
173/// Integral type used for [`Buffer`] offsets and sizes.
174///
175#[doc = link_to_wgpu_item!(struct Buffer)]
176pub type BufferAddress = u64;
177
178/// Integral type used for [`BufferSlice`] sizes.
179///
180/// Note that while this type is non-zero, a [`Buffer`] *per se* can have a size of zero,
181/// but no slice or mapping can be created from it.
182///
183#[doc = link_to_wgpu_item!(struct Buffer)]
184#[doc = link_to_wgpu_item!(struct BufferSlice)]
185pub type BufferSize = core::num::NonZeroU64;
186
187/// Integral type used for binding locations in shaders.
188///
189/// Used in [`VertexAttribute`]s and errors.
190///
191#[doc = link_to_wgpu_item!(struct VertexAttribute)]
192pub type ShaderLocation = u32;
193
194/// Integral type used for
195/// [dynamic bind group offsets](../wgpu/struct.RenderPass.html#method.set_bind_group).
196pub type DynamicOffset = u32;
197
198/// Buffer-texture copies must have [`bytes_per_row`] aligned to this number.
199///
200/// This doesn't apply to [`Queue::write_texture`][Qwt], only to [`copy_buffer_to_texture()`]
201/// and [`copy_texture_to_buffer()`].
202///
203/// [`bytes_per_row`]: TexelCopyBufferLayout::bytes_per_row
204#[doc = link_to_wgpu_docs!(["`copy_buffer_to_texture()`"]: "struct.Queue.html#method.copy_buffer_to_texture")]
205#[doc = link_to_wgpu_docs!(["`copy_texture_to_buffer()`"]: "struct.Queue.html#method.copy_texture_to_buffer")]
206#[doc = link_to_wgpu_docs!(["Qwt"]: "struct.Queue.html#method.write_texture")]
207pub const COPY_BYTES_PER_ROW_ALIGNMENT: u32 = 256;
208
209/// An [offset into the query resolve buffer] has to be aligned to this.
210///
211#[doc = link_to_wgpu_docs!(["offset into the query resolve buffer"]: "struct.CommandEncoder.html#method.resolve_query_set")]
212pub const QUERY_RESOLVE_BUFFER_ALIGNMENT: BufferAddress = 256;
213
214/// Buffer to buffer copy as well as buffer clear offsets and sizes must be aligned to this number.
215pub const COPY_BUFFER_ALIGNMENT: BufferAddress = 4;
216
217/// Minimum alignment of buffer mappings.
218///
219/// The range passed to [`map_async()`] or [`get_mapped_range()`] must be at least this aligned.
220///
221#[doc = link_to_wgpu_docs!(["`map_async()`"]: "struct.Buffer.html#method.map_async")]
222#[doc = link_to_wgpu_docs!(["`get_mapped_range()`"]: "struct.Buffer.html#method.get_mapped_range")]
223pub const MAP_ALIGNMENT: BufferAddress = 8;
224
225/// [Vertex buffer offsets] and [strides] have to be a multiple of this number.
226///
227#[doc = link_to_wgpu_docs!(["Vertex buffer offsets"]: "util/trait.RenderEncoder.html#tymethod.set_vertex_buffer")]
228#[doc = link_to_wgpu_docs!(["strides"]: "struct.VertexBufferLayout.html#structfield.array_stride")]
229pub const VERTEX_ALIGNMENT: BufferAddress = 4;
230
231/// [Vertex buffer strides] have to be a multiple of this number.
232///
233#[doc = link_to_wgpu_docs!(["Vertex buffer strides"]: "struct.VertexBufferLayout.html#structfield.array_stride")]
234#[deprecated(note = "Use `VERTEX_ALIGNMENT` instead", since = "27.0.0")]
235pub const VERTEX_STRIDE_ALIGNMENT: BufferAddress = 4;
236
237/// Ranges of [writes to immediate data] must be at least this aligned.
238///
239#[doc = link_to_wgpu_docs!(["writes to immediate data"]: "struct.RenderPass.html#method.set_immediates")]
240pub const IMMEDIATE_DATA_ALIGNMENT: u32 = 4;
241
242/// Storage buffer binding sizes must be multiples of this value.
243#[doc(hidden)]
244pub const STORAGE_BINDING_SIZE_ALIGNMENT: u32 = 4;
245
246/// Maximum number of query result slots that can be requested in a [`QuerySetDescriptor`].
247pub const QUERY_SET_MAX_QUERIES: u32 = 4096;
248
249/// Size in bytes of a single piece of [query] data.
250///
251#[doc = link_to_wgpu_docs!(["query"]: "struct.QuerySet.html")]
252pub const QUERY_SIZE: u32 = 8;
253
254/// The minimum allowed value for [`AdapterInfo::subgroup_min_size`].
255///
256/// See <https://gpuweb.github.io/gpuweb/#gpuadapterinfo>
257/// where you can always use these values on all devices
258pub const MINIMUM_SUBGROUP_MIN_SIZE: u32 = 4;
259/// The maximum allowed value for [`AdapterInfo::subgroup_max_size`].
260///
261/// See <https://gpuweb.github.io/gpuweb/#gpuadapterinfo>
262/// where you can always use these values on all devices.
263pub const MAXIMUM_SUBGROUP_MAX_SIZE: u32 = 128;
264
265/// Passed to `Device::poll` to control how and if it should block.
266#[derive(Clone, Debug)]
267pub enum PollType<T> {
268    /// On wgpu-core based backends, block until the given submission has
269    /// completed execution, and any callbacks have been invoked.
270    ///
271    /// On WebGPU, this has no effect. Callbacks are invoked from the
272    /// window event loop.
273    Wait {
274        /// Submission index to wait for.
275        ///
276        /// If not specified, will wait for the most recent submission at the time of the poll.
277        /// By the time the method returns, more submissions may have taken place.
278        submission_index: Option<T>,
279
280        /// Max time to wait for the submission to complete.
281        ///
282        /// If not specified, will wait indefinitely (or until an error is detected).
283        /// If waiting for the GPU device takes this long or longer, the poll will return [`PollError::Timeout`].
284        timeout: Option<Duration>,
285    },
286
287    /// Check the device for a single time without blocking.
288    Poll,
289}
290
291impl<T> PollType<T> {
292    /// Wait indefinitely until for the most recent submission to complete.
293    ///
294    /// This is a convenience function that creates a [`Self::Wait`] variant with
295    /// no timeout and no submission index.
296    #[must_use]
297    pub const fn wait_indefinitely() -> Self {
298        Self::Wait {
299            submission_index: None,
300            timeout: None,
301        }
302    }
303
304    /// This `PollType` represents a wait of some kind.
305    #[must_use]
306    pub fn is_wait(&self) -> bool {
307        match *self {
308            Self::Wait { .. } => true,
309            Self::Poll => false,
310        }
311    }
312
313    /// Map on the wait index type.
314    #[must_use]
315    pub fn map_index<U, F>(self, func: F) -> PollType<U>
316    where
317        F: FnOnce(T) -> U,
318    {
319        match self {
320            Self::Wait {
321                submission_index,
322                timeout,
323            } => PollType::Wait {
324                submission_index: submission_index.map(func),
325                timeout,
326            },
327            Self::Poll => PollType::Poll,
328        }
329    }
330}
331
332/// Error states after a device poll.
333#[derive(Debug)]
334pub enum PollError {
335    /// The requested Wait timed out before the submission was completed.
336    Timeout,
337    /// The requested Wait was given a wrong submission index.
338    WrongSubmissionIndex(u64, u64),
339}
340
341// This impl could be derived by `thiserror`, but by not doing so, we can reduce the number of
342// dependencies this early in the dependency graph, which may improve build parallelism.
343impl fmt::Display for PollError {
344    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
345        match self {
346            PollError::Timeout => {
347                f.write_str("The requested Wait timed out before the submission was completed.")
348            }
349            PollError::WrongSubmissionIndex(requested, successful) => write!(
350                f,
351                "Tried to wait using a submission index ({requested}) \
352                that has not been returned by a successful submission \
353                (last successful submission: {successful}"
354            ),
355        }
356    }
357}
358
359impl core::error::Error for PollError {}
360
361/// Status of device poll operation.
362#[derive(Debug, PartialEq, Eq)]
363pub enum PollStatus {
364    /// There are no active submissions in flight as of the beginning of the poll call.
365    /// Other submissions may have been queued on other threads during the call.
366    ///
367    /// This implies that the given Wait was satisfied before the timeout.
368    QueueEmpty,
369
370    /// The requested Wait was satisfied before the timeout.
371    WaitSucceeded,
372
373    /// This was a poll.
374    Poll,
375}
376
377impl PollStatus {
378    /// Returns true if the result is [`Self::QueueEmpty`].
379    #[must_use]
380    pub fn is_queue_empty(&self) -> bool {
381        matches!(self, Self::QueueEmpty)
382    }
383
384    /// Returns true if the result is either [`Self::WaitSucceeded`] or [`Self::QueueEmpty`].
385    #[must_use]
386    pub fn wait_finished(&self) -> bool {
387        matches!(self, Self::WaitSucceeded | Self::QueueEmpty)
388    }
389}
390
391/// Describes a [`CommandEncoder`](../wgpu/struct.CommandEncoder.html).
392///
393/// Corresponds to [WebGPU `GPUCommandEncoderDescriptor`](
394/// https://gpuweb.github.io/gpuweb/#dictdef-gpucommandencoderdescriptor).
395#[repr(C)]
396#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
397#[derive(Clone, Debug, PartialEq, Eq, Hash)]
398pub struct CommandEncoderDescriptor<L> {
399    /// Debug label for the command encoder. This will show up in graphics debuggers for easy identification.
400    pub label: L,
401}
402
403impl<L> CommandEncoderDescriptor<L> {
404    /// Takes a closure and maps the label of the command encoder descriptor into another.
405    #[must_use]
406    pub fn map_label<K>(&self, fun: impl FnOnce(&L) -> K) -> CommandEncoderDescriptor<K> {
407        CommandEncoderDescriptor {
408            label: fun(&self.label),
409        }
410    }
411}
412
413impl<T> Default for CommandEncoderDescriptor<Option<T>> {
414    fn default() -> Self {
415        Self { label: None }
416    }
417}
418
419/// RGBA double precision color.
420///
421/// This is not to be used as a generic color type, only for specific wgpu interfaces.
422#[repr(C)]
423#[derive(Clone, Copy, Debug, Default, PartialEq)]
424#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
425#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
426pub struct Color {
427    /// Red component of the color
428    pub r: f64,
429    /// Green component of the color
430    pub g: f64,
431    /// Blue component of the color
432    pub b: f64,
433    /// Alpha component of the color
434    pub a: f64,
435}
436
437#[allow(missing_docs)]
438impl Color {
439    pub const TRANSPARENT: Self = Self {
440        r: 0.0,
441        g: 0.0,
442        b: 0.0,
443        a: 0.0,
444    };
445    pub const BLACK: Self = Self {
446        r: 0.0,
447        g: 0.0,
448        b: 0.0,
449        a: 1.0,
450    };
451    pub const WHITE: Self = Self {
452        r: 1.0,
453        g: 1.0,
454        b: 1.0,
455        a: 1.0,
456    };
457    pub const RED: Self = Self {
458        r: 1.0,
459        g: 0.0,
460        b: 0.0,
461        a: 1.0,
462    };
463    pub const GREEN: Self = Self {
464        r: 0.0,
465        g: 1.0,
466        b: 0.0,
467        a: 1.0,
468    };
469    pub const BLUE: Self = Self {
470        r: 0.0,
471        g: 0.0,
472        b: 1.0,
473        a: 1.0,
474    };
475}
476
477/// Describes a [`CommandBuffer`](../wgpu/struct.CommandBuffer.html).
478///
479/// Corresponds to [WebGPU `GPUCommandBufferDescriptor`](
480/// https://gpuweb.github.io/gpuweb/#dictdef-gpucommandbufferdescriptor).
481#[repr(C)]
482#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
483#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
484pub struct CommandBufferDescriptor<L> {
485    /// Debug label of this command buffer.
486    pub label: L,
487}
488
489impl<L> CommandBufferDescriptor<L> {
490    /// Takes a closure and maps the label of the command buffer descriptor into another.
491    #[must_use]
492    pub fn map_label<K>(&self, fun: impl FnOnce(&L) -> K) -> CommandBufferDescriptor<K> {
493        CommandBufferDescriptor {
494            label: fun(&self.label),
495        }
496    }
497}
498
499/// Describes how to create a `QuerySet`.
500///
501/// Corresponds to [WebGPU `GPUQuerySetDescriptor`](
502/// https://gpuweb.github.io/gpuweb/#dictdef-gpuquerysetdescriptor).
503#[derive(Clone, Debug)]
504#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
505pub struct QuerySetDescriptor<L> {
506    /// Debug label for the query set.
507    pub label: L,
508    /// Kind of query that this query set should contain.
509    pub ty: QueryType,
510    /// Total number of query result slots the set contains. Must not be zero.
511    /// Must not be greater than [`QUERY_SET_MAX_QUERIES`].
512    pub count: u32,
513}
514
515impl<L> QuerySetDescriptor<L> {
516    /// Takes a closure and maps the label of the query set descriptor into another.
517    #[must_use]
518    pub fn map_label<'a, K>(&'a self, fun: impl FnOnce(&'a L) -> K) -> QuerySetDescriptor<K> {
519        QuerySetDescriptor {
520            label: fun(&self.label),
521            ty: self.ty,
522            count: self.count,
523        }
524    }
525}
526
527/// Type of queries contained in a [`QuerySet`].
528///
529/// Each query set may contain any number of queries, but they must all be of the same type.
530///
531/// Corresponds to [WebGPU `GPUQueryType`](
532/// https://gpuweb.github.io/gpuweb/#enumdef-gpuquerytype).
533///
534#[doc = link_to_wgpu_item!(struct QuerySet)]
535#[derive(Copy, Clone, Debug)]
536#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
537pub enum QueryType {
538    /// An occlusion query reports whether any of the fragments drawn within the scope of the query
539    /// passed all per-fragment tests (i.e. were not occluded).
540    ///
541    /// Occlusion queries are performed by setting [`RenderPassDescriptor::occlusion_query_set`],
542    /// then calling [`RenderPass::begin_occlusion_query()`] and
543    /// [`RenderPass::end_occlusion_query()`].
544    /// The query writes to a single result slot in the query set, whose value will be either 0 or 1
545    /// as a boolean.
546    ///
547    #[doc = link_to_wgpu_docs!(["`RenderPassDescriptor::occlusion_query_set`"]: "struct.RenderPassDescriptor.html#structfield.occlusion_query_set")]
548    #[doc = link_to_wgpu_docs!(["`RenderPass::begin_occlusion_query()`"]: "struct.RenderPass.html#structfield.begin_occlusion_query")]
549    #[doc = link_to_wgpu_docs!(["`RenderPass::end_occlusion_query()`"]: "struct.RenderPass.html#structfield.end_occlusion_query")]
550    Occlusion,
551
552    /// A timestamp query records a GPU-timestamp value
553    /// at which a certain command started or finished executing.
554    ///
555    /// Timestamp queries are performed by any one of:
556    /// * Setting [`ComputePassDescriptor::timestamp_writes`]
557    /// * Setting [`RenderPassDescriptor::timestamp_writes`]
558    /// * Calling [`CommandEncoder::write_timestamp()`]
559    /// * Calling [`RenderPass::write_timestamp()`]
560    /// * Calling [`ComputePass::write_timestamp()`]
561    ///
562    /// Each timestamp query writes to a single result slot in the query set.
563    /// The timestamp value must be multiplied by [`Queue::get_timestamp_period()`][Qgtp] to get
564    /// the time in nanoseconds.
565    /// Absolute values have no meaning, but timestamps can be subtracted to get the time it takes
566    /// for a string of operations to complete.
567    /// Timestamps may overflow and wrap to 0, resulting in occasional spurious negative deltas.
568    ///
569    /// Additionally, passes may be executed in parallel or out of the order they were submitted;
570    /// this does not affect their results but is observable via these timestamps.
571    ///
572    /// [`Features::TIMESTAMP_QUERY`] must be enabled to use this query type.
573    ///
574    #[doc = link_to_wgpu_docs!(["`CommandEncoder::write_timestamp()`"]: "struct.CommandEncoder.html#method.write_timestamp")]
575    #[doc = link_to_wgpu_docs!(["`ComputePass::write_timestamp()`"]: "struct.ComputePass.html#method.write_timestamp")]
576    #[doc = link_to_wgpu_docs!(["`RenderPass::write_timestamp()`"]: "struct.RenderPass.html#method.write_timestamp")]
577    #[doc = link_to_wgpu_docs!(["`ComputePassDescriptor::timestamp_writes`"]: "struct.ComputePassDescriptor.html#structfield.timestamp_writes")]
578    #[doc = link_to_wgpu_docs!(["`RenderPassDescriptor::timestamp_writes`"]: "struct.RenderPassDescriptor.html#structfield.timestamp_writes")]
579    #[doc = link_to_wgpu_docs!(["Qgtp"]: "struct.Queue.html#method.get_timestamp_period")]
580    Timestamp,
581
582    /// A pipeline statistics query records information about the execution of pipelines;
583    /// see [`PipelineStatisticsTypes`]'s documentation for details.
584    ///
585    /// Pipeline statistics queries are performed by:
586    ///
587    /// * [`ComputePass::begin_pipeline_statistics_query()`]
588    /// * [`RenderPass::begin_pipeline_statistics_query()`]
589    ///
590    /// A single query may occupy up to 5 result slots in the query set, based on the flags given
591    /// here.
592    ///
593    /// [`Features::PIPELINE_STATISTICS_QUERY`] must be enabled to use this query type.
594    ///
595    #[doc = link_to_wgpu_docs!(["`ComputePass::begin_pipeline_statistics_query()`"]: "struct.ComputePass.html#method.begin_pipeline_statistics_query")]
596    #[doc = link_to_wgpu_docs!(["`RenderPass::begin_pipeline_statistics_query()`"]: "struct.RenderPass.html#method.begin_pipeline_statistics_query")]
597    PipelineStatistics(PipelineStatisticsTypes),
598}
599
600bitflags::bitflags! {
601    /// Flags for which pipeline data should be recorded in a query.
602    ///
603    /// Used in [`QueryType`].
604    ///
605    /// The amount of values written when resolved depends
606    /// on the amount of flags set. For example, if 3 flags are set, 3
607    /// 64-bit values will be written per query.
608    ///
609    /// The order they are written is the order they are declared
610    /// in these bitflags. For example, if you enabled `CLIPPER_PRIMITIVES_OUT`
611    /// and `COMPUTE_SHADER_INVOCATIONS`, it would write 16 bytes,
612    /// the first 8 bytes being the primitive out value, the last 8
613    /// bytes being the compute shader invocation count.
614    #[repr(transparent)]
615    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
616    #[cfg_attr(feature = "serde", serde(transparent))]
617    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
618    pub struct PipelineStatisticsTypes : u8 {
619        /// Amount of times the vertex shader is ran. Accounts for
620        /// the vertex cache when doing indexed rendering.
621        const VERTEX_SHADER_INVOCATIONS = 1 << 0;
622        /// Amount of times the clipper is invoked. This
623        /// is also the amount of triangles output by the vertex shader.
624        const CLIPPER_INVOCATIONS = 1 << 1;
625        /// Amount of primitives that are not culled by the clipper.
626        /// This is the amount of triangles that are actually on screen
627        /// and will be rasterized and rendered.
628        const CLIPPER_PRIMITIVES_OUT = 1 << 2;
629        /// Amount of times the fragment shader is ran. Accounts for
630        /// fragment shaders running in 2x2 blocks in order to get
631        /// derivatives.
632        const FRAGMENT_SHADER_INVOCATIONS = 1 << 3;
633        /// Amount of times a compute shader is invoked. This will
634        /// be equivalent to the dispatch count times the workgroup size.
635        const COMPUTE_SHADER_INVOCATIONS = 1 << 4;
636    }
637}
638
639/// Corresponds to a [`GPUDeviceLostReason`].
640///
641/// [`GPUDeviceLostReason`]: https://www.w3.org/TR/webgpu/#enumdef-gpudevicelostreason
642#[repr(u8)]
643#[derive(Debug, Copy, Clone, Eq, PartialEq)]
644#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
645pub enum DeviceLostReason {
646    /// The device was lost for an unspecific reason, including driver errors.
647    Unknown = 0,
648    /// The device's `destroy` method was called.
649    Destroyed = 1,
650}