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