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
133pub(crate) use {link_to_wgpu_docs, link_to_wgpu_item};
134
135/// Integral type used for [`Buffer`] offsets and sizes.
136///
137#[doc = link_to_wgpu_item!(struct Buffer)]
138pub type BufferAddress = u64;
139
140/// Integral type used for [`BufferSlice`] sizes.
141///
142/// Note that while this type is non-zero, a [`Buffer`] *per se* can have a size of zero,
143/// but no slice or mapping can be created from it.
144///
145#[doc = link_to_wgpu_item!(struct Buffer)]
146#[doc = link_to_wgpu_item!(struct BufferSlice)]
147pub type BufferSize = core::num::NonZeroU64;
148
149/// Integral type used for binding locations in shaders.
150///
151/// Used in [`VertexAttribute`]s and errors.
152///
153#[doc = link_to_wgpu_item!(struct VertexAttribute)]
154pub type ShaderLocation = u32;
155
156/// Integral type used for
157/// [dynamic bind group offsets](../wgpu/struct.RenderPass.html#method.set_bind_group).
158pub type DynamicOffset = u32;
159
160/// Buffer-texture copies must have [`bytes_per_row`] aligned to this number.
161///
162/// This doesn't apply to [`Queue::write_texture`][Qwt], only to [`copy_buffer_to_texture()`]
163/// and [`copy_texture_to_buffer()`].
164///
165/// [`bytes_per_row`]: TexelCopyBufferLayout::bytes_per_row
166#[doc = link_to_wgpu_docs!(["`copy_buffer_to_texture()`"]: "struct.Queue.html#method.copy_buffer_to_texture")]
167#[doc = link_to_wgpu_docs!(["`copy_texture_to_buffer()`"]: "struct.Queue.html#method.copy_texture_to_buffer")]
168#[doc = link_to_wgpu_docs!(["Qwt"]: "struct.Queue.html#method.write_texture")]
169pub const COPY_BYTES_PER_ROW_ALIGNMENT: u32 = 256;
170
171/// An [offset into the query resolve buffer] has to be aligned to this.
172///
173#[doc = link_to_wgpu_docs!(["offset into the query resolve buffer"]: "struct.CommandEncoder.html#method.resolve_query_set")]
174pub const QUERY_RESOLVE_BUFFER_ALIGNMENT: BufferAddress = 256;
175
176/// Buffer to buffer copy as well as buffer clear offsets and sizes must be aligned to this number.
177pub const COPY_BUFFER_ALIGNMENT: BufferAddress = 4;
178
179/// Minimum alignment of buffer mappings.
180///
181/// The range passed to [`map_async()`] or [`get_mapped_range()`] must be at least this aligned.
182///
183#[doc = link_to_wgpu_docs!(["`map_async()`"]: "struct.Buffer.html#method.map_async")]
184#[doc = link_to_wgpu_docs!(["`get_mapped_range()`"]: "struct.Buffer.html#method.get_mapped_range")]
185pub const MAP_ALIGNMENT: BufferAddress = 8;
186
187/// [Vertex buffer offsets] and [strides] have to be a multiple of this number.
188///
189#[doc = link_to_wgpu_docs!(["Vertex buffer offsets"]: "util/trait.RenderEncoder.html#tymethod.set_vertex_buffer")]
190#[doc = link_to_wgpu_docs!(["strides"]: "struct.VertexBufferLayout.html#structfield.array_stride")]
191pub const VERTEX_ALIGNMENT: BufferAddress = 4;
192
193/// [Vertex buffer strides] have to be a multiple of this number.
194///
195#[doc = link_to_wgpu_docs!(["Vertex buffer strides"]: "struct.VertexBufferLayout.html#structfield.array_stride")]
196#[deprecated(note = "Use `VERTEX_ALIGNMENT` instead", since = "27.0.0")]
197pub const VERTEX_STRIDE_ALIGNMENT: BufferAddress = 4;
198
199/// Ranges of [writes to immediate data] must be at least this aligned.
200///
201#[doc = link_to_wgpu_docs!(["writes to immediate data"]: "struct.RenderPass.html#method.set_immediates")]
202pub const IMMEDIATE_DATA_ALIGNMENT: u32 = 4;
203
204/// Storage buffer binding sizes must be multiples of this value.
205#[doc(hidden)]
206pub const STORAGE_BINDING_SIZE_ALIGNMENT: u32 = 4;
207
208/// Maximum number of query result slots that can be requested in a [`QuerySetDescriptor`].
209pub const QUERY_SET_MAX_QUERIES: u32 = 4096;
210
211/// Size in bytes of a single piece of [query] data.
212///
213#[doc = link_to_wgpu_docs!(["query"]: "struct.QuerySet.html")]
214pub const QUERY_SIZE: u32 = 8;
215
216/// The minimum allowed value for [`AdapterInfo::subgroup_min_size`].
217///
218/// See <https://gpuweb.github.io/gpuweb/#gpuadapterinfo>
219/// where you can always use these values on all devices
220pub const MINIMUM_SUBGROUP_MIN_SIZE: u32 = 4;
221/// The maximum allowed value for [`AdapterInfo::subgroup_max_size`].
222///
223/// See <https://gpuweb.github.io/gpuweb/#gpuadapterinfo>
224/// where you can always use these values on all devices.
225pub const MAXIMUM_SUBGROUP_MAX_SIZE: u32 = 128;
226
227/// Passed to `Device::poll` to control how and if it should block.
228#[derive(Clone, Debug)]
229pub enum PollType<T> {
230 /// On wgpu-core based backends, block until the given submission has
231 /// completed execution, and any callbacks have been invoked.
232 ///
233 /// On WebGPU, this has no effect. Callbacks are invoked from the
234 /// window event loop.
235 Wait {
236 /// Submission index to wait for.
237 ///
238 /// If not specified, will wait for the most recent submission at the time of the poll.
239 /// By the time the method returns, more submissions may have taken place.
240 submission_index: Option<T>,
241
242 /// Max time to wait for the submission to complete.
243 ///
244 /// If not specified, will wait indefinitely (or until an error is detected).
245 /// If waiting for the GPU device takes this long or longer, the poll will return [`PollError::Timeout`].
246 timeout: Option<Duration>,
247 },
248
249 /// Check the device for a single time without blocking.
250 Poll,
251}
252
253impl<T> PollType<T> {
254 /// Wait indefinitely until for the most recent submission to complete.
255 ///
256 /// This is a convenience function that creates a [`Self::Wait`] variant with
257 /// no timeout and no submission index.
258 #[must_use]
259 pub const fn wait_indefinitely() -> Self {
260 Self::Wait {
261 submission_index: None,
262 timeout: None,
263 }
264 }
265
266 /// This `PollType` represents a wait of some kind.
267 #[must_use]
268 pub fn is_wait(&self) -> bool {
269 match *self {
270 Self::Wait { .. } => true,
271 Self::Poll => false,
272 }
273 }
274
275 /// Map on the wait index type.
276 #[must_use]
277 pub fn map_index<U, F>(self, func: F) -> PollType<U>
278 where
279 F: FnOnce(T) -> U,
280 {
281 match self {
282 Self::Wait {
283 submission_index,
284 timeout,
285 } => PollType::Wait {
286 submission_index: submission_index.map(func),
287 timeout,
288 },
289 Self::Poll => PollType::Poll,
290 }
291 }
292}
293
294/// Error states after a device poll.
295#[derive(Debug)]
296pub enum PollError {
297 /// The requested Wait timed out before the submission was completed.
298 Timeout,
299 /// The requested Wait was given a wrong submission index.
300 WrongSubmissionIndex(u64, u64),
301}
302
303// This impl could be derived by `thiserror`, but by not doing so, we can reduce the number of
304// dependencies this early in the dependency graph, which may improve build parallelism.
305impl fmt::Display for PollError {
306 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
307 match self {
308 PollError::Timeout => {
309 f.write_str("The requested Wait timed out before the submission was completed.")
310 }
311 PollError::WrongSubmissionIndex(requested, successful) => write!(
312 f,
313 "Tried to wait using a submission index ({requested}) \
314 that has not been returned by a successful submission \
315 (last successful submission: {successful}"
316 ),
317 }
318 }
319}
320
321impl core::error::Error for PollError {}
322
323/// Status of device poll operation.
324#[derive(Debug, PartialEq, Eq)]
325pub enum PollStatus {
326 /// There are no active submissions in flight as of the beginning of the poll call.
327 /// Other submissions may have been queued on other threads during the call.
328 ///
329 /// This implies that the given Wait was satisfied before the timeout.
330 QueueEmpty,
331
332 /// The requested Wait was satisfied before the timeout.
333 WaitSucceeded,
334
335 /// This was a poll.
336 Poll,
337}
338
339impl PollStatus {
340 /// Returns true if the result is [`Self::QueueEmpty`].
341 #[must_use]
342 pub fn is_queue_empty(&self) -> bool {
343 matches!(self, Self::QueueEmpty)
344 }
345
346 /// Returns true if the result is either [`Self::WaitSucceeded`] or [`Self::QueueEmpty`].
347 #[must_use]
348 pub fn wait_finished(&self) -> bool {
349 matches!(self, Self::WaitSucceeded | Self::QueueEmpty)
350 }
351}
352
353/// Describes a [`CommandEncoder`](../wgpu/struct.CommandEncoder.html).
354///
355/// Corresponds to [WebGPU `GPUCommandEncoderDescriptor`](
356/// https://gpuweb.github.io/gpuweb/#dictdef-gpucommandencoderdescriptor).
357#[repr(C)]
358#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
359#[derive(Clone, Debug, PartialEq, Eq, Hash)]
360pub struct CommandEncoderDescriptor<L> {
361 /// Debug label for the command encoder. This will show up in graphics debuggers for easy identification.
362 pub label: L,
363}
364
365impl<L> CommandEncoderDescriptor<L> {
366 /// Takes a closure and maps the label of the command encoder descriptor into another.
367 #[must_use]
368 pub fn map_label<K>(&self, fun: impl FnOnce(&L) -> K) -> CommandEncoderDescriptor<K> {
369 CommandEncoderDescriptor {
370 label: fun(&self.label),
371 }
372 }
373}
374
375impl<T> Default for CommandEncoderDescriptor<Option<T>> {
376 fn default() -> Self {
377 Self { label: None }
378 }
379}
380
381/// RGBA double precision color.
382///
383/// This is not to be used as a generic color type, only for specific wgpu interfaces.
384#[repr(C)]
385#[derive(Clone, Copy, Debug, Default, PartialEq)]
386#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
387#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
388pub struct Color {
389 /// Red component of the color
390 pub r: f64,
391 /// Green component of the color
392 pub g: f64,
393 /// Blue component of the color
394 pub b: f64,
395 /// Alpha component of the color
396 pub a: f64,
397}
398
399#[allow(missing_docs)]
400impl Color {
401 pub const TRANSPARENT: Self = Self {
402 r: 0.0,
403 g: 0.0,
404 b: 0.0,
405 a: 0.0,
406 };
407 pub const BLACK: Self = Self {
408 r: 0.0,
409 g: 0.0,
410 b: 0.0,
411 a: 1.0,
412 };
413 pub const WHITE: Self = Self {
414 r: 1.0,
415 g: 1.0,
416 b: 1.0,
417 a: 1.0,
418 };
419 pub const RED: Self = Self {
420 r: 1.0,
421 g: 0.0,
422 b: 0.0,
423 a: 1.0,
424 };
425 pub const GREEN: Self = Self {
426 r: 0.0,
427 g: 1.0,
428 b: 0.0,
429 a: 1.0,
430 };
431 pub const BLUE: Self = Self {
432 r: 0.0,
433 g: 0.0,
434 b: 1.0,
435 a: 1.0,
436 };
437}
438
439/// Describes a [`CommandBuffer`](../wgpu/struct.CommandBuffer.html).
440///
441/// Corresponds to [WebGPU `GPUCommandBufferDescriptor`](
442/// https://gpuweb.github.io/gpuweb/#dictdef-gpucommandbufferdescriptor).
443#[repr(C)]
444#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
445#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
446pub struct CommandBufferDescriptor<L> {
447 /// Debug label of this command buffer.
448 pub label: L,
449}
450
451impl<L> CommandBufferDescriptor<L> {
452 /// Takes a closure and maps the label of the command buffer descriptor into another.
453 #[must_use]
454 pub fn map_label<K>(&self, fun: impl FnOnce(&L) -> K) -> CommandBufferDescriptor<K> {
455 CommandBufferDescriptor {
456 label: fun(&self.label),
457 }
458 }
459}
460
461/// Describes how to create a `QuerySet`.
462///
463/// Corresponds to [WebGPU `GPUQuerySetDescriptor`](
464/// https://gpuweb.github.io/gpuweb/#dictdef-gpuquerysetdescriptor).
465#[derive(Clone, Debug)]
466#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
467pub struct QuerySetDescriptor<L> {
468 /// Debug label for the query set.
469 pub label: L,
470 /// Kind of query that this query set should contain.
471 pub ty: QueryType,
472 /// Total number of query result slots the set contains. Must not be zero.
473 /// Must not be greater than [`QUERY_SET_MAX_QUERIES`].
474 pub count: u32,
475}
476
477impl<L> QuerySetDescriptor<L> {
478 /// Takes a closure and maps the label of the query set descriptor into another.
479 #[must_use]
480 pub fn map_label<'a, K>(&'a self, fun: impl FnOnce(&'a L) -> K) -> QuerySetDescriptor<K> {
481 QuerySetDescriptor {
482 label: fun(&self.label),
483 ty: self.ty,
484 count: self.count,
485 }
486 }
487}
488
489/// Type of queries contained in a [`QuerySet`].
490///
491/// Each query set may contain any number of queries, but they must all be of the same type.
492///
493/// Corresponds to [WebGPU `GPUQueryType`](
494/// https://gpuweb.github.io/gpuweb/#enumdef-gpuquerytype).
495///
496#[doc = link_to_wgpu_item!(struct QuerySet)]
497#[derive(Copy, Clone, Debug)]
498#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
499pub enum QueryType {
500 /// An occlusion query reports whether any of the fragments drawn within the scope of the query
501 /// passed all per-fragment tests (i.e. were not occluded).
502 ///
503 /// Occlusion queries are performed by setting [`RenderPassDescriptor::occlusion_query_set`],
504 /// then calling [`RenderPass::begin_occlusion_query()`] and
505 /// [`RenderPass::end_occlusion_query()`].
506 /// The query writes to a single result slot in the query set, whose value will be either 0 or 1
507 /// as a boolean.
508 ///
509 #[doc = link_to_wgpu_docs!(["`RenderPassDescriptor::occlusion_query_set`"]: "struct.RenderPassDescriptor.html#structfield.occlusion_query_set")]
510 #[doc = link_to_wgpu_docs!(["`RenderPass::begin_occlusion_query()`"]: "struct.RenderPass.html#structfield.begin_occlusion_query")]
511 #[doc = link_to_wgpu_docs!(["`RenderPass::end_occlusion_query()`"]: "struct.RenderPass.html#structfield.end_occlusion_query")]
512 Occlusion,
513
514 /// A timestamp query records a GPU-timestamp value
515 /// at which a certain command started or finished executing.
516 ///
517 /// Timestamp queries are performed by any one of:
518 /// * Setting [`ComputePassDescriptor::timestamp_writes`]
519 /// * Setting [`RenderPassDescriptor::timestamp_writes`]
520 /// * Calling [`CommandEncoder::write_timestamp()`]
521 /// * Calling [`RenderPass::write_timestamp()`]
522 /// * Calling [`ComputePass::write_timestamp()`]
523 ///
524 /// Each timestamp query writes to a single result slot in the query set.
525 /// The timestamp value must be multiplied by [`Queue::get_timestamp_period()`][Qgtp] to get
526 /// the time in nanoseconds.
527 /// Absolute values have no meaning, but timestamps can be subtracted to get the time it takes
528 /// for a string of operations to complete.
529 /// Timestamps may overflow and wrap to 0, resulting in occasional spurious negative deltas.
530 ///
531 /// Additionally, passes may be executed in parallel or out of the order they were submitted;
532 /// this does not affect their results but is observable via these timestamps.
533 ///
534 /// [`Features::TIMESTAMP_QUERY`] must be enabled to use this query type.
535 ///
536 #[doc = link_to_wgpu_docs!(["`CommandEncoder::write_timestamp()`"]: "struct.CommandEncoder.html#method.write_timestamp")]
537 #[doc = link_to_wgpu_docs!(["`ComputePass::write_timestamp()`"]: "struct.ComputePass.html#method.write_timestamp")]
538 #[doc = link_to_wgpu_docs!(["`RenderPass::write_timestamp()`"]: "struct.RenderPass.html#method.write_timestamp")]
539 #[doc = link_to_wgpu_docs!(["`ComputePassDescriptor::timestamp_writes`"]: "struct.ComputePassDescriptor.html#structfield.timestamp_writes")]
540 #[doc = link_to_wgpu_docs!(["`RenderPassDescriptor::timestamp_writes`"]: "struct.RenderPassDescriptor.html#structfield.timestamp_writes")]
541 #[doc = link_to_wgpu_docs!(["Qgtp"]: "struct.Queue.html#method.get_timestamp_period")]
542 Timestamp,
543
544 /// A pipeline statistics query records information about the execution of pipelines;
545 /// see [`PipelineStatisticsTypes`]'s documentation for details.
546 ///
547 /// Pipeline statistics queries are performed by:
548 ///
549 /// * [`ComputePass::begin_pipeline_statistics_query()`]
550 /// * [`RenderPass::begin_pipeline_statistics_query()`]
551 ///
552 /// A single query may occupy up to 5 result slots in the query set, based on the flags given
553 /// here.
554 ///
555 /// [`Features::PIPELINE_STATISTICS_QUERY`] must be enabled to use this query type.
556 ///
557 #[doc = link_to_wgpu_docs!(["`ComputePass::begin_pipeline_statistics_query()`"]: "struct.ComputePass.html#method.begin_pipeline_statistics_query")]
558 #[doc = link_to_wgpu_docs!(["`RenderPass::begin_pipeline_statistics_query()`"]: "struct.RenderPass.html#method.begin_pipeline_statistics_query")]
559 PipelineStatistics(PipelineStatisticsTypes),
560}
561
562bitflags::bitflags! {
563 /// Flags for which pipeline data should be recorded in a query.
564 ///
565 /// Used in [`QueryType`].
566 ///
567 /// The amount of values written when resolved depends
568 /// on the amount of flags set. For example, if 3 flags are set, 3
569 /// 64-bit values will be written per query.
570 ///
571 /// The order they are written is the order they are declared
572 /// in these bitflags. For example, if you enabled `CLIPPER_PRIMITIVES_OUT`
573 /// and `COMPUTE_SHADER_INVOCATIONS`, it would write 16 bytes,
574 /// the first 8 bytes being the primitive out value, the last 8
575 /// bytes being the compute shader invocation count.
576 #[repr(transparent)]
577 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
578 #[cfg_attr(feature = "serde", serde(transparent))]
579 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
580 pub struct PipelineStatisticsTypes : u8 {
581 /// Amount of times the vertex shader is ran. Accounts for
582 /// the vertex cache when doing indexed rendering.
583 const VERTEX_SHADER_INVOCATIONS = 1 << 0;
584 /// Amount of times the clipper is invoked. This
585 /// is also the amount of triangles output by the vertex shader.
586 const CLIPPER_INVOCATIONS = 1 << 1;
587 /// Amount of primitives that are not culled by the clipper.
588 /// This is the amount of triangles that are actually on screen
589 /// and will be rasterized and rendered.
590 const CLIPPER_PRIMITIVES_OUT = 1 << 2;
591 /// Amount of times the fragment shader is ran. Accounts for
592 /// fragment shaders running in 2x2 blocks in order to get
593 /// derivatives.
594 const FRAGMENT_SHADER_INVOCATIONS = 1 << 3;
595 /// Amount of times a compute shader is invoked. This will
596 /// be equivalent to the dispatch count times the workgroup size.
597 const COMPUTE_SHADER_INVOCATIONS = 1 << 4;
598 }
599}
600
601/// Corresponds to a [`GPUDeviceLostReason`].
602///
603/// [`GPUDeviceLostReason`]: https://www.w3.org/TR/webgpu/#enumdef-gpudevicelostreason
604#[repr(u8)]
605#[derive(Debug, Copy, Clone, Eq, PartialEq)]
606#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
607pub enum DeviceLostReason {
608 /// The device was lost for an unspecific reason, including driver errors.
609 Unknown = 0,
610 /// The device's `destroy` method was called.
611 Destroyed = 1,
612}