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