wgpu_hal/lib.rs
1/*! A cross-platform unsafe graphics abstraction.
2 *
3 * This crate defines a set of traits abstracting over modern graphics APIs,
4 * with implementations ("backends") for Vulkan, Metal, Direct3D, and GL.
5 *
6 * `wgpu-hal` is a spiritual successor to
7 * [gfx-hal](https://github.com/gfx-rs/gfx), but with reduced scope, and
8 * oriented towards WebGPU implementation goals. It has no overhead for
9 * validation or tracking, and the API translation overhead is kept to the bare
10 * minimum by the design of WebGPU. This API can be used for resource-demanding
11 * applications and engines.
12 *
13 * The `wgpu-hal` crate's main design choices:
14 *
15 * - Our traits are meant to be *portable*: proper use
16 * should get equivalent results regardless of the backend.
17 *
18 * - Our traits' contracts are *unsafe*: implementations perform minimal
19 * validation, if any, and incorrect use will often cause undefined behavior.
20 * This allows us to minimize the overhead we impose over the underlying
21 * graphics system. If you need safety, the [`wgpu-core`] crate provides a
22 * safe API for driving `wgpu-hal`, implementing all necessary validation,
23 * resource state tracking, and so on. (Note that `wgpu-core` is designed for
24 * use via FFI; the [`wgpu`] crate provides more idiomatic Rust bindings for
25 * `wgpu-core`.) Or, you can do your own validation.
26 *
27 * - In the same vein, returned errors *only cover cases the user can't
28 * anticipate*, like running out of memory or losing the device. Any errors
29 * that the user could reasonably anticipate are their responsibility to
30 * avoid. For example, `wgpu-hal` returns no error for mapping a buffer that's
31 * not mappable: as the buffer creator, the user should already know if they
32 * can map it.
33 *
34 * - We use *static dispatch*. The traits are not
35 * generally object-safe. You must select a specific backend type
36 * like [`vulkan::Api`] or [`metal::Api`], and then use that
37 * according to the main traits, or call backend-specific methods.
38 *
39 * - We use *idiomatic Rust parameter passing*,
40 * taking objects by reference, returning them by value, and so on,
41 * unlike `wgpu-core`, which refers to objects by ID.
42 *
43 * - We map buffer contents *persistently*. This means that the buffer
44 * can remain mapped on the CPU while the GPU reads or writes to it.
45 * You must explicitly indicate when data might need to be
46 * transferred between CPU and GPU, if `wgpu-hal` indicates that the
47 * mapping is not coherent (that is, automatically synchronized
48 * between the two devices).
49 *
50 * - You must record *explicit barriers* between different usages of a
51 * resource. For example, if a buffer is written to by a compute
52 * shader, and then used as and index buffer to a draw call, you
53 * must use [`CommandEncoder::transition_buffers`] between those two
54 * operations.
55 *
56 * - Pipeline layouts are *explicitly specified* when setting bind
57 * group. Incompatible layouts disturb groups bound at higher indices.
58 *
59 * - The API *accepts collections as iterators*, to avoid forcing the user to
60 * store data in particular containers. The implementation doesn't guarantee
61 * that any of the iterators are drained, unless stated otherwise by the
62 * function documentation. For this reason, we recommend that iterators don't
63 * do any mutating work.
64 *
65 * Unfortunately, `wgpu-hal`'s safety requirements are not fully documented.
66 * Ideally, all trait methods would have doc comments setting out the
67 * requirements users must meet to ensure correct and portable behavior. If you
68 * are aware of a specific requirement that a backend imposes that is not
69 * ensured by the traits' documented rules, please file an issue. Or, if you are
70 * a capable technical writer, please file a pull request!
71 *
72 * [`wgpu-core`]: https://crates.io/crates/wgpu-core
73 * [`wgpu`]: https://crates.io/crates/wgpu
74 * [`vulkan::Api`]: vulkan/struct.Api.html
75 * [`metal::Api`]: metal/struct.Api.html
76 *
77 * ## Primary backends
78 *
79 * The `wgpu-hal` crate has full-featured backends implemented on the following
80 * platform graphics APIs:
81 *
82 * - Vulkan, available on Linux, Android, and Windows, using the [`ash`] crate's
83 * Vulkan bindings. It's also available on macOS, if you install [MoltenVK].
84 *
85 * - Metal on macOS, using the [`metal`] crate's bindings.
86 *
87 * - Direct3D 12 on Windows, using the [`d3d12`] crate's bindings.
88 *
89 * [`ash`]: https://crates.io/crates/ash
90 * [MoltenVK]: https://github.com/KhronosGroup/MoltenVK
91 * [`metal`]: https://crates.io/crates/metal
92 * [`d3d12`]: ahttps://crates.io/crates/d3d12
93 *
94 * ## Secondary backends
95 *
96 * The `wgpu-hal` crate has a partial implementation based on the following
97 * platform graphics API:
98 *
99 * - The GL backend is available anywhere OpenGL, OpenGL ES, or WebGL are
100 * available. See the [`gles`] module documentation for details.
101 *
102 * [`gles`]: gles/index.html
103 *
104 * You can see what capabilities an adapter is missing by checking the
105 * [`DownlevelCapabilities`][tdc] in [`ExposedAdapter::capabilities`], available
106 * from [`Instance::enumerate_adapters`].
107 *
108 * The API is generally designed to fit the primary backends better than the
109 * secondary backends, so the latter may impose more overhead.
110 *
111 * [tdc]: wgt::DownlevelCapabilities
112 *
113 * ## Traits
114 *
115 * The `wgpu-hal` crate defines a handful of traits that together
116 * represent a cross-platform abstraction for modern GPU APIs.
117 *
118 * - The [`Api`] trait represents a `wgpu-hal` backend. It has no methods of its
119 * own, only a collection of associated types.
120 *
121 * - [`Api::Instance`] implements the [`Instance`] trait. [`Instance::init`]
122 * creates an instance value, which you can use to enumerate the adapters
123 * available on the system. For example, [`vulkan::Api::Instance::init`][Ii]
124 * returns an instance that can enumerate the Vulkan physical devices on your
125 * system.
126 *
127 * - [`Api::Adapter`] implements the [`Adapter`] trait, representing a
128 * particular device from a particular backend. For example, a Vulkan instance
129 * might have a Lavapipe software adapter and a GPU-based adapter.
130 *
131 * - [`Api::Device`] implements the [`Device`] trait, representing an active
132 * link to a device. You get a device value by calling [`Adapter::open`], and
133 * then use it to create buffers, textures, shader modules, and so on.
134 *
135 * - [`Api::Queue`] implements the [`Queue`] trait, which you use to submit
136 * command buffers to a given device.
137 *
138 * - [`Api::CommandEncoder`] implements the [`CommandEncoder`] trait, which you
139 * use to build buffers of commands to submit to a queue. This has all the
140 * methods for drawing and running compute shaders, which is presumably what
141 * you're here for.
142 *
143 * - [`Api::Surface`] implements the [`Surface`] trait, which represents a
144 * swapchain for presenting images on the screen, via interaction with the
145 * system's window manager.
146 *
147 * The [`Api`] trait has various other associated types like [`Api::Buffer`] and
148 * [`Api::Texture`] that represent resources the rest of the interface can
149 * operate on, but these generally do not have their own traits.
150 *
151 * [Ii]: Instance::init
152 *
153 * ## Validation is the calling code's responsibility, not `wgpu-hal`'s
154 *
155 * As much as possible, `wgpu-hal` traits place the burden of validation,
156 * resource tracking, and state tracking on the caller, not on the trait
157 * implementations themselves. Anything which can reasonably be handled in
158 * backend-independent code should be. A `wgpu_hal` backend's sole obligation is
159 * to provide portable behavior, and report conditions that the calling code
160 * can't reasonably anticipate, like device loss or running out of memory.
161 *
162 * The `wgpu` crate collection is intended for use in security-sensitive
163 * applications, like web browsers, where the API is available to untrusted
164 * code. This means that `wgpu-core`'s validation is not simply a service to
165 * developers, to be provided opportunistically when the performance costs are
166 * acceptable and the necessary data is ready at hand. Rather, `wgpu-core`'s
167 * validation must be exhaustive, to ensure that even malicious content cannot
168 * provoke and exploit undefined behavior in the platform's graphics API.
169 *
170 * Because graphics APIs' requirements are complex, the only practical way for
171 * `wgpu` to provide exhaustive validation is to comprehensively track the
172 * lifetime and state of all the resources in the system. Implementing this
173 * separately for each backend is infeasible; effort would be better spent
174 * making the cross-platform validation in `wgpu-core` legible and trustworthy.
175 * Fortunately, the requirements are largely similar across the various
176 * platforms, so cross-platform validation is practical.
177 *
178 * Some backends have specific requirements that aren't practical to foist off
179 * on the `wgpu-hal` user. For example, properly managing macOS Objective-C or
180 * Microsoft COM reference counts is best handled by using appropriate pointer
181 * types within the backend.
182 *
183 * A desire for "defense in depth" may suggest performing additional validation
184 * in `wgpu-hal` when the opportunity arises, but this must be done with
185 * caution. Even experienced contributors infer the expectations their changes
186 * must meet by considering not just requirements made explicit in types, tests,
187 * assertions, and comments, but also those implicit in the surrounding code.
188 * When one sees validation or state-tracking code in `wgpu-hal`, it is tempting
189 * to conclude, "Oh, `wgpu-hal` checks for this, so `wgpu-core` needn't worry
190 * about it - that would be redundant!" The responsibility for exhaustive
191 * validation always rests with `wgpu-core`, regardless of what may or may not
192 * be checked in `wgpu-hal`.
193 *
194 * To this end, any "defense in depth" validation that does appear in `wgpu-hal`
195 * for requirements that `wgpu-core` should have enforced should report failure
196 * via the `unreachable!` macro, because problems detected at this stage always
197 * indicate a bug in `wgpu-core`.
198 *
199 * ## Debugging
200 *
201 * Most of the information on the wiki [Debugging wgpu Applications][wiki-debug]
202 * page still applies to this API, with the exception of API tracing/replay
203 * functionality, which is only available in `wgpu-core`.
204 *
205 * [wiki-debug]: https://github.com/gfx-rs/wgpu/wiki/Debugging-wgpu-Applications
206 */
207
208#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
209#![allow(
210 // this happens on the GL backend, where it is both thread safe and non-thread safe in the same code.
211 clippy::arc_with_non_send_sync,
212 // for `if_then_panic` until it reaches stable
213 unknown_lints,
214 // We use loops for getting early-out of scope without closures.
215 clippy::never_loop,
216 // We don't use syntax sugar where it's not necessary.
217 clippy::match_like_matches_macro,
218 // Redundant matching is more explicit.
219 clippy::redundant_pattern_matching,
220 // Explicit lifetimes are often easier to reason about.
221 clippy::needless_lifetimes,
222 // No need for defaults in the internal types.
223 clippy::new_without_default,
224 // Matches are good and extendable, no need to make an exception here.
225 clippy::single_match,
226 // Push commands are more regular than macros.
227 clippy::vec_init_then_push,
228 // "if panic" is a good uniform construct.
229 clippy::if_then_panic,
230 // We unsafe impl `Send` for a reason.
231 clippy::non_send_fields_in_send_ty,
232 // TODO!
233 clippy::missing_safety_doc,
234 // Clashes with clippy::pattern_type_mismatch
235 clippy::needless_borrowed_reference,
236)]
237#![warn(
238 trivial_casts,
239 trivial_numeric_casts,
240 unsafe_op_in_unsafe_fn,
241 unused_extern_crates,
242 unused_qualifications,
243 // We don't match on a reference, unless required.
244 clippy::pattern_type_mismatch,
245)]
246
247/// DirectX12 API internals.
248#[cfg(dx12)]
249pub mod dx12;
250/// A dummy API implementation.
251pub mod empty;
252/// GLES API internals.
253#[cfg(gles)]
254pub mod gles;
255/// Metal API internals.
256#[cfg(metal)]
257pub mod metal;
258/// Vulkan API internals.
259#[cfg(vulkan)]
260pub mod vulkan;
261
262pub mod auxil;
263pub mod api {
264 #[cfg(dx12)]
265 pub use super::dx12::Api as Dx12;
266 pub use super::empty::Api as Empty;
267 #[cfg(gles)]
268 pub use super::gles::Api as Gles;
269 #[cfg(metal)]
270 pub use super::metal::Api as Metal;
271 #[cfg(vulkan)]
272 pub use super::vulkan::Api as Vulkan;
273}
274
275use std::{
276 borrow::{Borrow, Cow},
277 fmt,
278 num::NonZeroU32,
279 ops::{Range, RangeInclusive},
280 ptr::NonNull,
281 sync::Arc,
282};
283
284use bitflags::bitflags;
285use parking_lot::Mutex;
286use thiserror::Error;
287use wgt::WasmNotSendSync;
288
289// - Vertex + Fragment
290// - Compute
291pub const MAX_CONCURRENT_SHADER_STAGES: usize = 2;
292pub const MAX_ANISOTROPY: u8 = 16;
293pub const MAX_BIND_GROUPS: usize = 8;
294pub const MAX_VERTEX_BUFFERS: usize = 16;
295pub const MAX_COLOR_ATTACHMENTS: usize = 8;
296pub const MAX_MIP_LEVELS: u32 = 16;
297/// Size of a single occlusion/timestamp query, when copied into a buffer, in bytes.
298pub const QUERY_SIZE: wgt::BufferAddress = 8;
299
300pub type Label<'a> = Option<&'a str>;
301pub type MemoryRange = Range<wgt::BufferAddress>;
302pub type FenceValue = u64;
303
304/// Drop guard to signal wgpu-hal is no longer using an externally created object.
305pub type DropGuard = Box<dyn std::any::Any + Send + Sync>;
306
307#[derive(Clone, Debug, PartialEq, Eq, Error)]
308pub enum DeviceError {
309 #[error("Out of memory")]
310 OutOfMemory,
311 #[error("Device is lost")]
312 Lost,
313 #[error("Creation of a resource failed for a reason other than running out of memory.")]
314 ResourceCreationFailed,
315}
316
317#[derive(Clone, Debug, Eq, PartialEq, Error)]
318pub enum ShaderError {
319 #[error("Compilation failed: {0:?}")]
320 Compilation(String),
321 #[error(transparent)]
322 Device(#[from] DeviceError),
323}
324
325#[derive(Clone, Debug, Eq, PartialEq, Error)]
326pub enum PipelineError {
327 #[error("Linkage failed for stage {0:?}: {1}")]
328 Linkage(wgt::ShaderStages, String),
329 #[error("Entry point for stage {0:?} is invalid")]
330 EntryPoint(naga::ShaderStage),
331 #[error(transparent)]
332 Device(#[from] DeviceError),
333}
334
335#[derive(Clone, Debug, Eq, PartialEq, Error)]
336pub enum SurfaceError {
337 #[error("Surface is lost")]
338 Lost,
339 #[error("Surface is outdated, needs to be re-created")]
340 Outdated,
341 #[error(transparent)]
342 Device(#[from] DeviceError),
343 #[error("Other reason: {0}")]
344 Other(&'static str),
345}
346
347/// Error occurring while trying to create an instance, or create a surface from an instance;
348/// typically relating to the state of the underlying graphics API or hardware.
349#[derive(Clone, Debug, Error)]
350#[error("{message}")]
351pub struct InstanceError {
352 /// These errors are very platform specific, so do not attempt to encode them as an enum.
353 ///
354 /// This message should describe the problem in sufficient detail to be useful for a
355 /// user-to-developer “why won't this work on my machine” bug report, and otherwise follow
356 /// <https://rust-lang.github.io/api-guidelines/interoperability.html#error-types-are-meaningful-and-well-behaved-c-good-err>.
357 message: String,
358
359 /// Underlying error value, if any is available.
360 #[source]
361 source: Option<Arc<dyn std::error::Error + Send + Sync + 'static>>,
362}
363
364impl InstanceError {
365 #[allow(dead_code)] // may be unused on some platforms
366 pub(crate) fn new(message: String) -> Self {
367 Self {
368 message,
369 source: None,
370 }
371 }
372 #[allow(dead_code)] // may be unused on some platforms
373 pub(crate) fn with_source(
374 message: String,
375 source: impl std::error::Error + Send + Sync + 'static,
376 ) -> Self {
377 Self {
378 message,
379 source: Some(Arc::new(source)),
380 }
381 }
382}
383
384pub trait Api: Clone + fmt::Debug + Sized {
385 type Instance: Instance<A = Self>;
386 type Surface: Surface<A = Self>;
387 type Adapter: Adapter<A = Self>;
388 type Device: Device<A = Self>;
389
390 type Queue: Queue<A = Self>;
391 type CommandEncoder: CommandEncoder<A = Self>;
392
393 /// This API's command buffer type.
394 ///
395 /// The only thing you can do with `CommandBuffer`s is build them
396 /// with a [`CommandEncoder`] and then pass them to
397 /// [`Queue::submit`] for execution, or destroy them by passing
398 /// them to [`CommandEncoder::reset_all`].
399 ///
400 /// [`CommandEncoder`]: Api::CommandEncoder
401 type CommandBuffer: WasmNotSendSync + fmt::Debug;
402
403 type Buffer: fmt::Debug + WasmNotSendSync + 'static;
404 type Texture: fmt::Debug + WasmNotSendSync + 'static;
405 type SurfaceTexture: fmt::Debug + WasmNotSendSync + Borrow<Self::Texture>;
406 type TextureView: fmt::Debug + WasmNotSendSync;
407 type Sampler: fmt::Debug + WasmNotSendSync;
408 type QuerySet: fmt::Debug + WasmNotSendSync;
409
410 /// A value you can block on to wait for something to finish.
411 ///
412 /// A `Fence` holds a monotonically increasing [`FenceValue`]. You can call
413 /// [`Device::wait`] to block until a fence reaches or passes a value you
414 /// choose. [`Queue::submit`] can take a `Fence` and a [`FenceValue`] to
415 /// store in it when the submitted work is complete.
416 ///
417 /// Attempting to set a fence to a value less than its current value has no
418 /// effect.
419 ///
420 /// Waiting on a fence returns as soon as the fence reaches *or passes* the
421 /// requested value. This implies that, in order to reliably determine when
422 /// an operation has completed, operations must finish in order of
423 /// increasing fence values: if a higher-valued operation were to finish
424 /// before a lower-valued operation, then waiting for the fence to reach the
425 /// lower value could return before the lower-valued operation has actually
426 /// finished.
427 type Fence: fmt::Debug + WasmNotSendSync;
428
429 type BindGroupLayout: fmt::Debug + WasmNotSendSync;
430 type BindGroup: fmt::Debug + WasmNotSendSync;
431 type PipelineLayout: fmt::Debug + WasmNotSendSync;
432 type ShaderModule: fmt::Debug + WasmNotSendSync;
433 type RenderPipeline: fmt::Debug + WasmNotSendSync;
434 type ComputePipeline: fmt::Debug + WasmNotSendSync;
435
436 type AccelerationStructure: fmt::Debug + WasmNotSendSync + 'static;
437}
438
439pub trait Instance: Sized + WasmNotSendSync {
440 type A: Api;
441
442 unsafe fn init(desc: &InstanceDescriptor) -> Result<Self, InstanceError>;
443 unsafe fn create_surface(
444 &self,
445 display_handle: raw_window_handle::RawDisplayHandle,
446 window_handle: raw_window_handle::RawWindowHandle,
447 ) -> Result<<Self::A as Api>::Surface, InstanceError>;
448 unsafe fn destroy_surface(&self, surface: <Self::A as Api>::Surface);
449 unsafe fn enumerate_adapters(&self) -> Vec<ExposedAdapter<Self::A>>;
450}
451
452pub trait Surface: WasmNotSendSync {
453 type A: Api;
454
455 /// Configure `self` to use `device`.
456 ///
457 /// # Safety
458 ///
459 /// - All GPU work using `self` must have been completed.
460 /// - All [`AcquiredSurfaceTexture`]s must have been destroyed.
461 /// - All [`Api::TextureView`]s derived from the [`AcquiredSurfaceTexture`]s must have been destroyed.
462 /// - The surface `self` must not currently be configured to use any other [`Device`].
463 unsafe fn configure(
464 &self,
465 device: &<Self::A as Api>::Device,
466 config: &SurfaceConfiguration,
467 ) -> Result<(), SurfaceError>;
468
469 /// Unconfigure `self` on `device`.
470 ///
471 /// # Safety
472 ///
473 /// - All GPU work that uses `surface` must have been completed.
474 /// - All [`AcquiredSurfaceTexture`]s must have been destroyed.
475 /// - All [`Api::TextureView`]s derived from the [`AcquiredSurfaceTexture`]s must have been destroyed.
476 /// - The surface `self` must have been configured on `device`.
477 unsafe fn unconfigure(&self, device: &<Self::A as Api>::Device);
478
479 /// Return the next texture to be presented by `self`, for the caller to draw on.
480 ///
481 /// On success, return an [`AcquiredSurfaceTexture`] representing the
482 /// texture into which the caller should draw the image to be displayed on
483 /// `self`.
484 ///
485 /// If `timeout` elapses before `self` has a texture ready to be acquired,
486 /// return `Ok(None)`. If `timeout` is `None`, wait indefinitely, with no
487 /// timeout.
488 ///
489 /// # Using an [`AcquiredSurfaceTexture`]
490 ///
491 /// On success, this function returns an [`AcquiredSurfaceTexture`] whose
492 /// [`texture`] field is a [`SurfaceTexture`] from which the caller can
493 /// [`borrow`] a [`Texture`] to draw on. The [`AcquiredSurfaceTexture`] also
494 /// carries some metadata about that [`SurfaceTexture`].
495 ///
496 /// All calls to [`Queue::submit`] that draw on that [`Texture`] must also
497 /// include the [`SurfaceTexture`] in the `surface_textures` argument.
498 ///
499 /// When you are done drawing on the texture, you can display it on `self`
500 /// by passing the [`SurfaceTexture`] and `self` to [`Queue::present`].
501 ///
502 /// If you do not wish to display the texture, you must pass the
503 /// [`SurfaceTexture`] to [`self.discard_texture`], so that it can be reused
504 /// by future acquisitions.
505 ///
506 /// # Portability
507 ///
508 /// Some backends can't support a timeout when acquiring a texture. On these
509 /// backends, `timeout` is ignored.
510 ///
511 /// # Safety
512 ///
513 /// - The surface `self` must currently be configured on some [`Device`].
514 ///
515 /// - The `fence` argument must be the same [`Fence`] passed to all calls to
516 /// [`Queue::submit`] that used [`Texture`]s acquired from this surface.
517 ///
518 /// - You may only have one texture acquired from `self` at a time. When
519 /// `acquire_texture` returns `Ok(Some(ast))`, you must pass the returned
520 /// [`SurfaceTexture`] `ast.texture` to either [`Queue::present`] or
521 /// [`Surface::discard_texture`] before calling `acquire_texture` again.
522 ///
523 /// [`texture`]: AcquiredSurfaceTexture::texture
524 /// [`SurfaceTexture`]: Api::SurfaceTexture
525 /// [`borrow`]: std::borrow::Borrow::borrow
526 /// [`Texture`]: Api::Texture
527 /// [`Fence`]: Api::Fence
528 /// [`self.discard_texture`]: Surface::discard_texture
529 unsafe fn acquire_texture(
530 &self,
531 timeout: Option<std::time::Duration>,
532 fence: &<Self::A as Api>::Fence,
533 ) -> Result<Option<AcquiredSurfaceTexture<Self::A>>, SurfaceError>;
534
535 /// Relinquish an acquired texture without presenting it.
536 ///
537 /// After this call, the texture underlying [`SurfaceTexture`] may be
538 /// returned by subsequent calls to [`self.acquire_texture`].
539 ///
540 /// # Safety
541 ///
542 /// - The surface `self` must currently be configured on some [`Device`].
543 ///
544 /// - `texture` must be a [`SurfaceTexture`] returned by a call to
545 /// [`self.acquire_texture`] that has not yet been passed to
546 /// [`Queue::present`].
547 ///
548 /// [`SurfaceTexture`]: Api::SurfaceTexture
549 /// [`self.acquire_texture`]: Surface::acquire_texture
550 unsafe fn discard_texture(&self, texture: <Self::A as Api>::SurfaceTexture);
551}
552
553pub trait Adapter: WasmNotSendSync {
554 type A: Api;
555
556 unsafe fn open(
557 &self,
558 features: wgt::Features,
559 limits: &wgt::Limits,
560 ) -> Result<OpenDevice<Self::A>, DeviceError>;
561
562 /// Return the set of supported capabilities for a texture format.
563 unsafe fn texture_format_capabilities(
564 &self,
565 format: wgt::TextureFormat,
566 ) -> TextureFormatCapabilities;
567
568 /// Returns the capabilities of working with a specified surface.
569 ///
570 /// `None` means presentation is not supported for it.
571 unsafe fn surface_capabilities(
572 &self,
573 surface: &<Self::A as Api>::Surface,
574 ) -> Option<SurfaceCapabilities>;
575
576 /// Creates a [`PresentationTimestamp`] using the adapter's WSI.
577 ///
578 /// [`PresentationTimestamp`]: wgt::PresentationTimestamp
579 unsafe fn get_presentation_timestamp(&self) -> wgt::PresentationTimestamp;
580}
581
582pub trait Device: WasmNotSendSync {
583 type A: Api;
584
585 /// Exit connection to this logical device.
586 unsafe fn exit(self, queue: <Self::A as Api>::Queue);
587 /// Creates a new buffer.
588 ///
589 /// The initial usage is `BufferUses::empty()`.
590 unsafe fn create_buffer(
591 &self,
592 desc: &BufferDescriptor,
593 ) -> Result<<Self::A as Api>::Buffer, DeviceError>;
594 unsafe fn destroy_buffer(&self, buffer: <Self::A as Api>::Buffer);
595 //TODO: clarify if zero-sized mapping is allowed
596 unsafe fn map_buffer(
597 &self,
598 buffer: &<Self::A as Api>::Buffer,
599 range: MemoryRange,
600 ) -> Result<BufferMapping, DeviceError>;
601 unsafe fn unmap_buffer(&self, buffer: &<Self::A as Api>::Buffer) -> Result<(), DeviceError>;
602 unsafe fn flush_mapped_ranges<I>(&self, buffer: &<Self::A as Api>::Buffer, ranges: I)
603 where
604 I: Iterator<Item = MemoryRange>;
605 unsafe fn invalidate_mapped_ranges<I>(&self, buffer: &<Self::A as Api>::Buffer, ranges: I)
606 where
607 I: Iterator<Item = MemoryRange>;
608
609 /// Creates a new texture.
610 ///
611 /// The initial usage for all subresources is `TextureUses::UNINITIALIZED`.
612 unsafe fn create_texture(
613 &self,
614 desc: &TextureDescriptor,
615 ) -> Result<<Self::A as Api>::Texture, DeviceError>;
616 unsafe fn destroy_texture(&self, texture: <Self::A as Api>::Texture);
617 unsafe fn create_texture_view(
618 &self,
619 texture: &<Self::A as Api>::Texture,
620 desc: &TextureViewDescriptor,
621 ) -> Result<<Self::A as Api>::TextureView, DeviceError>;
622 unsafe fn destroy_texture_view(&self, view: <Self::A as Api>::TextureView);
623 unsafe fn create_sampler(
624 &self,
625 desc: &SamplerDescriptor,
626 ) -> Result<<Self::A as Api>::Sampler, DeviceError>;
627 unsafe fn destroy_sampler(&self, sampler: <Self::A as Api>::Sampler);
628
629 /// Create a fresh [`CommandEncoder`].
630 ///
631 /// The new `CommandEncoder` is in the "closed" state.
632 unsafe fn create_command_encoder(
633 &self,
634 desc: &CommandEncoderDescriptor<Self::A>,
635 ) -> Result<<Self::A as Api>::CommandEncoder, DeviceError>;
636 unsafe fn destroy_command_encoder(&self, pool: <Self::A as Api>::CommandEncoder);
637
638 /// Creates a bind group layout.
639 unsafe fn create_bind_group_layout(
640 &self,
641 desc: &BindGroupLayoutDescriptor,
642 ) -> Result<<Self::A as Api>::BindGroupLayout, DeviceError>;
643 unsafe fn destroy_bind_group_layout(&self, bg_layout: <Self::A as Api>::BindGroupLayout);
644 unsafe fn create_pipeline_layout(
645 &self,
646 desc: &PipelineLayoutDescriptor<Self::A>,
647 ) -> Result<<Self::A as Api>::PipelineLayout, DeviceError>;
648 unsafe fn destroy_pipeline_layout(&self, pipeline_layout: <Self::A as Api>::PipelineLayout);
649 unsafe fn create_bind_group(
650 &self,
651 desc: &BindGroupDescriptor<Self::A>,
652 ) -> Result<<Self::A as Api>::BindGroup, DeviceError>;
653 unsafe fn destroy_bind_group(&self, group: <Self::A as Api>::BindGroup);
654
655 unsafe fn create_shader_module(
656 &self,
657 desc: &ShaderModuleDescriptor,
658 shader: ShaderInput,
659 ) -> Result<<Self::A as Api>::ShaderModule, ShaderError>;
660 unsafe fn destroy_shader_module(&self, module: <Self::A as Api>::ShaderModule);
661 unsafe fn create_render_pipeline(
662 &self,
663 desc: &RenderPipelineDescriptor<Self::A>,
664 ) -> Result<<Self::A as Api>::RenderPipeline, PipelineError>;
665 unsafe fn destroy_render_pipeline(&self, pipeline: <Self::A as Api>::RenderPipeline);
666 unsafe fn create_compute_pipeline(
667 &self,
668 desc: &ComputePipelineDescriptor<Self::A>,
669 ) -> Result<<Self::A as Api>::ComputePipeline, PipelineError>;
670 unsafe fn destroy_compute_pipeline(&self, pipeline: <Self::A as Api>::ComputePipeline);
671
672 unsafe fn create_query_set(
673 &self,
674 desc: &wgt::QuerySetDescriptor<Label>,
675 ) -> Result<<Self::A as Api>::QuerySet, DeviceError>;
676 unsafe fn destroy_query_set(&self, set: <Self::A as Api>::QuerySet);
677 unsafe fn create_fence(&self) -> Result<<Self::A as Api>::Fence, DeviceError>;
678 unsafe fn destroy_fence(&self, fence: <Self::A as Api>::Fence);
679 unsafe fn get_fence_value(
680 &self,
681 fence: &<Self::A as Api>::Fence,
682 ) -> Result<FenceValue, DeviceError>;
683
684 /// Wait for `fence` to reach `value`.
685 ///
686 /// Operations like [`Queue::submit`] can accept a [`Fence`] and a
687 /// [`FenceValue`] to store in it, so you can use this `wait` function
688 /// to wait for a given queue submission to finish execution.
689 ///
690 /// The `value` argument must be a value that some actual operation you have
691 /// already presented to the device is going to store in `fence`. You cannot
692 /// wait for values yet to be submitted. (This restriction accommodates
693 /// implementations like the `vulkan` backend's [`FencePool`] that must
694 /// allocate a distinct synchronization object for each fence value one is
695 /// able to wait for.)
696 ///
697 /// Calling `wait` with a lower [`FenceValue`] than `fence`'s current value
698 /// returns immediately.
699 ///
700 /// [`Fence`]: Api::Fence
701 /// [`FencePool`]: vulkan/enum.Fence.html#variant.FencePool
702 unsafe fn wait(
703 &self,
704 fence: &<Self::A as Api>::Fence,
705 value: FenceValue,
706 timeout_ms: u32,
707 ) -> Result<bool, DeviceError>;
708
709 unsafe fn start_capture(&self) -> bool;
710 unsafe fn stop_capture(&self);
711
712 unsafe fn create_acceleration_structure(
713 &self,
714 desc: &AccelerationStructureDescriptor,
715 ) -> Result<<Self::A as Api>::AccelerationStructure, DeviceError>;
716 unsafe fn get_acceleration_structure_build_sizes(
717 &self,
718 desc: &GetAccelerationStructureBuildSizesDescriptor<Self::A>,
719 ) -> AccelerationStructureBuildSizes;
720 unsafe fn get_acceleration_structure_device_address(
721 &self,
722 acceleration_structure: &<Self::A as Api>::AccelerationStructure,
723 ) -> wgt::BufferAddress;
724 unsafe fn destroy_acceleration_structure(
725 &self,
726 acceleration_structure: <Self::A as Api>::AccelerationStructure,
727 );
728}
729
730pub trait Queue: WasmNotSendSync {
731 type A: Api;
732
733 /// Submit `command_buffers` for execution on GPU.
734 ///
735 /// Update `fence` to `value` when the operation is complete. See
736 /// [`Fence`] for details.
737 ///
738 /// A `wgpu_hal` queue is "single threaded": all command buffers are
739 /// executed in the order they're submitted, with each buffer able to see
740 /// previous buffers' results. Specifically:
741 ///
742 /// - If two calls to `submit` on a single `Queue` occur in a particular
743 /// order (that is, they happen on the same thread, or on two threads that
744 /// have synchronized to establish an ordering), then the first
745 /// submission's commands all complete execution before any of the second
746 /// submission's commands begin. All results produced by one submission
747 /// are visible to the next.
748 ///
749 /// - Within a submission, command buffers execute in the order in which they
750 /// appear in `command_buffers`. All results produced by one buffer are
751 /// visible to the next.
752 ///
753 /// If two calls to `submit` on a single `Queue` from different threads are
754 /// not synchronized to occur in a particular order, they must pass distinct
755 /// [`Fence`]s. As explained in the [`Fence`] documentation, waiting for
756 /// operations to complete is only trustworthy when operations finish in
757 /// order of increasing fence value, but submissions from different threads
758 /// cannot determine how to order the fence values if the submissions
759 /// themselves are unordered. If each thread uses a separate [`Fence`], this
760 /// problem does not arise.
761 ///
762 /// Valid usage:
763 ///
764 /// - All of the [`CommandBuffer`][cb]s were created from
765 /// [`CommandEncoder`][ce]s that are associated with this queue.
766 ///
767 /// - All of those [`CommandBuffer`][cb]s must remain alive until
768 /// the submitted commands have finished execution. (Since
769 /// command buffers must not outlive their encoders, this
770 /// implies that the encoders must remain alive as well.)
771 ///
772 /// - All resources used by a submitted [`CommandBuffer`][cb]
773 /// ([`Texture`][t]s, [`BindGroup`][bg]s, [`RenderPipeline`][rp]s, and so
774 /// on) must remain alive until the command buffer finishes execution.
775 ///
776 /// - Every [`SurfaceTexture`][st] that any command in `command_buffers`
777 /// writes to must appear in the `surface_textures` argument.
778 ///
779 /// - No [`SurfaceTexture`][st] may appear in the `surface_textures`
780 /// argument more than once.
781 ///
782 /// - Each [`SurfaceTexture`][st] in `surface_textures` must be configured
783 /// for use with the [`Device`][d] associated with this [`Queue`],
784 /// typically by calling [`Surface::configure`].
785 ///
786 /// - All calls to this function that include a given [`SurfaceTexture`][st]
787 /// in `surface_textures` must use the same [`Fence`].
788 ///
789 /// [`Fence`]: Api::Fence
790 /// [cb]: Api::CommandBuffer
791 /// [ce]: Api::CommandEncoder
792 /// [st]: Api::SurfaceTexture
793 /// [t]: Api::Texture
794 /// [bg]: Api::BindGroup
795 /// [rp]: Api::RenderPipeline
796 /// [d]: Api::Device
797 unsafe fn submit(
798 &self,
799 command_buffers: &[&<Self::A as Api>::CommandBuffer],
800 surface_textures: &[&<Self::A as Api>::SurfaceTexture],
801 signal_fence: (&mut <Self::A as Api>::Fence, FenceValue),
802 ) -> Result<(), DeviceError>;
803 unsafe fn present(
804 &self,
805 surface: &<Self::A as Api>::Surface,
806 texture: <Self::A as Api>::SurfaceTexture,
807 ) -> Result<(), SurfaceError>;
808 unsafe fn get_timestamp_period(&self) -> f32;
809}
810
811/// Encoder and allocation pool for `CommandBuffer`s.
812///
813/// A `CommandEncoder` not only constructs `CommandBuffer`s but also
814/// acts as the allocation pool that owns the buffers' underlying
815/// storage. Thus, `CommandBuffer`s must not outlive the
816/// `CommandEncoder` that created them.
817///
818/// The life cycle of a `CommandBuffer` is as follows:
819///
820/// - Call [`Device::create_command_encoder`] to create a new
821/// `CommandEncoder`, in the "closed" state.
822///
823/// - Call `begin_encoding` on a closed `CommandEncoder` to begin
824/// recording commands. This puts the `CommandEncoder` in the
825/// "recording" state.
826///
827/// - Call methods like `copy_buffer_to_buffer`, `begin_render_pass`,
828/// etc. on a "recording" `CommandEncoder` to add commands to the
829/// list. (If an error occurs, you must call `discard_encoding`; see
830/// below.)
831///
832/// - Call `end_encoding` on a recording `CommandEncoder` to close the
833/// encoder and construct a fresh `CommandBuffer` consisting of the
834/// list of commands recorded up to that point.
835///
836/// - Call `discard_encoding` on a recording `CommandEncoder` to drop
837/// the commands recorded thus far and close the encoder. This is
838/// the only safe thing to do on a `CommandEncoder` if an error has
839/// occurred while recording commands.
840///
841/// - Call `reset_all` on a closed `CommandEncoder`, passing all the
842/// live `CommandBuffers` built from it. All the `CommandBuffer`s
843/// are destroyed, and their resources are freed.
844///
845/// # Safety
846///
847/// - The `CommandEncoder` must be in the states described above to
848/// make the given calls.
849///
850/// - A `CommandBuffer` that has been submitted for execution on the
851/// GPU must live until its execution is complete.
852///
853/// - A `CommandBuffer` must not outlive the `CommandEncoder` that
854/// built it.
855///
856/// - A `CommandEncoder` must not outlive its `Device`.
857///
858/// It is the user's responsibility to meet this requirements. This
859/// allows `CommandEncoder` implementations to keep their state
860/// tracking to a minimum.
861pub trait CommandEncoder: WasmNotSendSync + fmt::Debug {
862 type A: Api;
863
864 /// Begin encoding a new command buffer.
865 ///
866 /// This puts this `CommandEncoder` in the "recording" state.
867 ///
868 /// # Safety
869 ///
870 /// This `CommandEncoder` must be in the "closed" state.
871 unsafe fn begin_encoding(&mut self, label: Label) -> Result<(), DeviceError>;
872
873 /// Discard the command list under construction.
874 ///
875 /// If an error has occurred while recording commands, this
876 /// is the only safe thing to do with the encoder.
877 ///
878 /// This puts this `CommandEncoder` in the "closed" state.
879 ///
880 /// # Safety
881 ///
882 /// This `CommandEncoder` must be in the "recording" state.
883 ///
884 /// Callers must not assume that implementations of this
885 /// function are idempotent, and thus should not call it
886 /// multiple times in a row.
887 unsafe fn discard_encoding(&mut self);
888
889 /// Return a fresh [`CommandBuffer`] holding the recorded commands.
890 ///
891 /// The returned [`CommandBuffer`] holds all the commands recorded
892 /// on this `CommandEncoder` since the last call to
893 /// [`begin_encoding`].
894 ///
895 /// This puts this `CommandEncoder` in the "closed" state.
896 ///
897 /// # Safety
898 ///
899 /// This `CommandEncoder` must be in the "recording" state.
900 ///
901 /// The returned [`CommandBuffer`] must not outlive this
902 /// `CommandEncoder`. Implementations are allowed to build
903 /// `CommandBuffer`s that depend on storage owned by this
904 /// `CommandEncoder`.
905 ///
906 /// [`CommandBuffer`]: Api::CommandBuffer
907 /// [`begin_encoding`]: CommandEncoder::begin_encoding
908 unsafe fn end_encoding(&mut self) -> Result<<Self::A as Api>::CommandBuffer, DeviceError>;
909
910 /// Reclaim all resources belonging to this `CommandEncoder`.
911 ///
912 /// # Safety
913 ///
914 /// This `CommandEncoder` must be in the "closed" state.
915 ///
916 /// The `command_buffers` iterator must produce all the live
917 /// [`CommandBuffer`]s built using this `CommandEncoder` --- that
918 /// is, every extant `CommandBuffer` returned from `end_encoding`.
919 ///
920 /// [`CommandBuffer`]: Api::CommandBuffer
921 unsafe fn reset_all<I>(&mut self, command_buffers: I)
922 where
923 I: Iterator<Item = <Self::A as Api>::CommandBuffer>;
924
925 unsafe fn transition_buffers<'a, T>(&mut self, barriers: T)
926 where
927 T: Iterator<Item = BufferBarrier<'a, Self::A>>;
928
929 unsafe fn transition_textures<'a, T>(&mut self, barriers: T)
930 where
931 T: Iterator<Item = TextureBarrier<'a, Self::A>>;
932
933 // copy operations
934
935 unsafe fn clear_buffer(&mut self, buffer: &<Self::A as Api>::Buffer, range: MemoryRange);
936
937 unsafe fn copy_buffer_to_buffer<T>(
938 &mut self,
939 src: &<Self::A as Api>::Buffer,
940 dst: &<Self::A as Api>::Buffer,
941 regions: T,
942 ) where
943 T: Iterator<Item = BufferCopy>;
944
945 /// Copy from an external image to an internal texture.
946 /// Works with a single array layer.
947 /// Note: `dst` current usage has to be `TextureUses::COPY_DST`.
948 /// Note: the copy extent is in physical size (rounded to the block size)
949 #[cfg(webgl)]
950 unsafe fn copy_external_image_to_texture<T>(
951 &mut self,
952 src: &wgt::ImageCopyExternalImage,
953 dst: &<Self::A as Api>::Texture,
954 dst_premultiplication: bool,
955 regions: T,
956 ) where
957 T: Iterator<Item = TextureCopy>;
958
959 /// Copy from one texture to another.
960 /// Works with a single array layer.
961 /// Note: `dst` current usage has to be `TextureUses::COPY_DST`.
962 /// Note: the copy extent is in physical size (rounded to the block size)
963 unsafe fn copy_texture_to_texture<T>(
964 &mut self,
965 src: &<Self::A as Api>::Texture,
966 src_usage: TextureUses,
967 dst: &<Self::A as Api>::Texture,
968 regions: T,
969 ) where
970 T: Iterator<Item = TextureCopy>;
971
972 /// Copy from buffer to texture.
973 /// Works with a single array layer.
974 /// Note: `dst` current usage has to be `TextureUses::COPY_DST`.
975 /// Note: the copy extent is in physical size (rounded to the block size)
976 unsafe fn copy_buffer_to_texture<T>(
977 &mut self,
978 src: &<Self::A as Api>::Buffer,
979 dst: &<Self::A as Api>::Texture,
980 regions: T,
981 ) where
982 T: Iterator<Item = BufferTextureCopy>;
983
984 /// Copy from texture to buffer.
985 /// Works with a single array layer.
986 /// Note: the copy extent is in physical size (rounded to the block size)
987 unsafe fn copy_texture_to_buffer<T>(
988 &mut self,
989 src: &<Self::A as Api>::Texture,
990 src_usage: TextureUses,
991 dst: &<Self::A as Api>::Buffer,
992 regions: T,
993 ) where
994 T: Iterator<Item = BufferTextureCopy>;
995
996 // pass common
997
998 /// Sets the bind group at `index` to `group`, assuming the layout
999 /// of all the preceding groups to be taken from `layout`.
1000 unsafe fn set_bind_group(
1001 &mut self,
1002 layout: &<Self::A as Api>::PipelineLayout,
1003 index: u32,
1004 group: &<Self::A as Api>::BindGroup,
1005 dynamic_offsets: &[wgt::DynamicOffset],
1006 );
1007
1008 /// Sets a range in push constant data.
1009 ///
1010 /// IMPORTANT: while the data is passed as words, the offset is in bytes!
1011 ///
1012 /// # Safety
1013 ///
1014 /// - `offset_bytes` must be a multiple of 4.
1015 /// - The range of push constants written must be valid for the pipeline layout at draw time.
1016 unsafe fn set_push_constants(
1017 &mut self,
1018 layout: &<Self::A as Api>::PipelineLayout,
1019 stages: wgt::ShaderStages,
1020 offset_bytes: u32,
1021 data: &[u32],
1022 );
1023
1024 unsafe fn insert_debug_marker(&mut self, label: &str);
1025 unsafe fn begin_debug_marker(&mut self, group_label: &str);
1026 unsafe fn end_debug_marker(&mut self);
1027
1028 // queries
1029
1030 /// # Safety:
1031 ///
1032 /// - If `set` is an occlusion query set, it must be the same one as used in the [`RenderPassDescriptor::occlusion_query_set`] parameter.
1033 unsafe fn begin_query(&mut self, set: &<Self::A as Api>::QuerySet, index: u32);
1034 /// # Safety:
1035 ///
1036 /// - If `set` is an occlusion query set, it must be the same one as used in the [`RenderPassDescriptor::occlusion_query_set`] parameter.
1037 unsafe fn end_query(&mut self, set: &<Self::A as Api>::QuerySet, index: u32);
1038 unsafe fn write_timestamp(&mut self, set: &<Self::A as Api>::QuerySet, index: u32);
1039 unsafe fn reset_queries(&mut self, set: &<Self::A as Api>::QuerySet, range: Range<u32>);
1040 unsafe fn copy_query_results(
1041 &mut self,
1042 set: &<Self::A as Api>::QuerySet,
1043 range: Range<u32>,
1044 buffer: &<Self::A as Api>::Buffer,
1045 offset: wgt::BufferAddress,
1046 stride: wgt::BufferSize,
1047 );
1048
1049 // render passes
1050
1051 // Begins a render pass, clears all active bindings.
1052 unsafe fn begin_render_pass(&mut self, desc: &RenderPassDescriptor<Self::A>);
1053 unsafe fn end_render_pass(&mut self);
1054
1055 unsafe fn set_render_pipeline(&mut self, pipeline: &<Self::A as Api>::RenderPipeline);
1056
1057 unsafe fn set_index_buffer<'a>(
1058 &mut self,
1059 binding: BufferBinding<'a, Self::A>,
1060 format: wgt::IndexFormat,
1061 );
1062 unsafe fn set_vertex_buffer<'a>(&mut self, index: u32, binding: BufferBinding<'a, Self::A>);
1063 unsafe fn set_viewport(&mut self, rect: &Rect<f32>, depth_range: Range<f32>);
1064 unsafe fn set_scissor_rect(&mut self, rect: &Rect<u32>);
1065 unsafe fn set_stencil_reference(&mut self, value: u32);
1066 unsafe fn set_blend_constants(&mut self, color: &[f32; 4]);
1067
1068 unsafe fn draw(
1069 &mut self,
1070 first_vertex: u32,
1071 vertex_count: u32,
1072 first_instance: u32,
1073 instance_count: u32,
1074 );
1075 unsafe fn draw_indexed(
1076 &mut self,
1077 first_index: u32,
1078 index_count: u32,
1079 base_vertex: i32,
1080 first_instance: u32,
1081 instance_count: u32,
1082 );
1083 unsafe fn draw_indirect(
1084 &mut self,
1085 buffer: &<Self::A as Api>::Buffer,
1086 offset: wgt::BufferAddress,
1087 draw_count: u32,
1088 );
1089 unsafe fn draw_indexed_indirect(
1090 &mut self,
1091 buffer: &<Self::A as Api>::Buffer,
1092 offset: wgt::BufferAddress,
1093 draw_count: u32,
1094 );
1095 unsafe fn draw_indirect_count(
1096 &mut self,
1097 buffer: &<Self::A as Api>::Buffer,
1098 offset: wgt::BufferAddress,
1099 count_buffer: &<Self::A as Api>::Buffer,
1100 count_offset: wgt::BufferAddress,
1101 max_count: u32,
1102 );
1103 unsafe fn draw_indexed_indirect_count(
1104 &mut self,
1105 buffer: &<Self::A as Api>::Buffer,
1106 offset: wgt::BufferAddress,
1107 count_buffer: &<Self::A as Api>::Buffer,
1108 count_offset: wgt::BufferAddress,
1109 max_count: u32,
1110 );
1111
1112 // compute passes
1113
1114 // Begins a compute pass, clears all active bindings.
1115 unsafe fn begin_compute_pass(&mut self, desc: &ComputePassDescriptor<Self::A>);
1116 unsafe fn end_compute_pass(&mut self);
1117
1118 unsafe fn set_compute_pipeline(&mut self, pipeline: &<Self::A as Api>::ComputePipeline);
1119
1120 unsafe fn dispatch(&mut self, count: [u32; 3]);
1121 unsafe fn dispatch_indirect(
1122 &mut self,
1123 buffer: &<Self::A as Api>::Buffer,
1124 offset: wgt::BufferAddress,
1125 );
1126
1127 /// To get the required sizes for the buffer allocations use `get_acceleration_structure_build_sizes` per descriptor
1128 /// All buffers must be synchronized externally
1129 /// All buffer regions, which are written to may only be passed once per function call,
1130 /// with the exception of updates in the same descriptor.
1131 /// Consequences of this limitation:
1132 /// - scratch buffers need to be unique
1133 /// - a tlas can't be build in the same call with a blas it contains
1134 unsafe fn build_acceleration_structures<'a, T>(
1135 &mut self,
1136 descriptor_count: u32,
1137 descriptors: T,
1138 ) where
1139 Self::A: 'a,
1140 T: IntoIterator<Item = BuildAccelerationStructureDescriptor<'a, Self::A>>;
1141
1142 unsafe fn place_acceleration_structure_barrier(
1143 &mut self,
1144 barrier: AccelerationStructureBarrier,
1145 );
1146}
1147
1148bitflags!(
1149 /// Pipeline layout creation flags.
1150 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1151 pub struct PipelineLayoutFlags: u32 {
1152 /// Include support for `first_vertex` / `first_instance` drawing.
1153 const FIRST_VERTEX_INSTANCE = 1 << 0;
1154 /// Include support for num work groups builtin.
1155 const NUM_WORK_GROUPS = 1 << 1;
1156 }
1157);
1158
1159bitflags!(
1160 /// Pipeline layout creation flags.
1161 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1162 pub struct BindGroupLayoutFlags: u32 {
1163 /// Allows for bind group binding arrays to be shorter than the array in the BGL.
1164 const PARTIALLY_BOUND = 1 << 0;
1165 }
1166);
1167
1168bitflags!(
1169 /// Texture format capability flags.
1170 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1171 pub struct TextureFormatCapabilities: u32 {
1172 /// Format can be sampled.
1173 const SAMPLED = 1 << 0;
1174 /// Format can be sampled with a linear sampler.
1175 const SAMPLED_LINEAR = 1 << 1;
1176 /// Format can be sampled with a min/max reduction sampler.
1177 const SAMPLED_MINMAX = 1 << 2;
1178
1179 /// Format can be used as storage with write-only access.
1180 const STORAGE = 1 << 3;
1181 /// Format can be used as storage with read and read/write access.
1182 const STORAGE_READ_WRITE = 1 << 4;
1183 /// Format can be used as storage with atomics.
1184 const STORAGE_ATOMIC = 1 << 5;
1185
1186 /// Format can be used as color and input attachment.
1187 const COLOR_ATTACHMENT = 1 << 6;
1188 /// Format can be used as color (with blending) and input attachment.
1189 const COLOR_ATTACHMENT_BLEND = 1 << 7;
1190 /// Format can be used as depth-stencil and input attachment.
1191 const DEPTH_STENCIL_ATTACHMENT = 1 << 8;
1192
1193 /// Format can be multisampled by x2.
1194 const MULTISAMPLE_X2 = 1 << 9;
1195 /// Format can be multisampled by x4.
1196 const MULTISAMPLE_X4 = 1 << 10;
1197 /// Format can be multisampled by x8.
1198 const MULTISAMPLE_X8 = 1 << 11;
1199 /// Format can be multisampled by x16.
1200 const MULTISAMPLE_X16 = 1 << 12;
1201
1202 /// Format can be used for render pass resolve targets.
1203 const MULTISAMPLE_RESOLVE = 1 << 13;
1204
1205 /// Format can be copied from.
1206 const COPY_SRC = 1 << 14;
1207 /// Format can be copied to.
1208 const COPY_DST = 1 << 15;
1209 }
1210);
1211
1212bitflags!(
1213 /// Texture format capability flags.
1214 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1215 pub struct FormatAspects: u8 {
1216 const COLOR = 1 << 0;
1217 const DEPTH = 1 << 1;
1218 const STENCIL = 1 << 2;
1219 const PLANE_0 = 1 << 3;
1220 const PLANE_1 = 1 << 4;
1221 const PLANE_2 = 1 << 5;
1222
1223 const DEPTH_STENCIL = Self::DEPTH.bits() | Self::STENCIL.bits();
1224 }
1225);
1226
1227impl FormatAspects {
1228 pub fn new(format: wgt::TextureFormat, aspect: wgt::TextureAspect) -> Self {
1229 let aspect_mask = match aspect {
1230 wgt::TextureAspect::All => Self::all(),
1231 wgt::TextureAspect::DepthOnly => Self::DEPTH,
1232 wgt::TextureAspect::StencilOnly => Self::STENCIL,
1233 wgt::TextureAspect::Plane0 => Self::PLANE_0,
1234 wgt::TextureAspect::Plane1 => Self::PLANE_1,
1235 wgt::TextureAspect::Plane2 => Self::PLANE_2,
1236 };
1237 Self::from(format) & aspect_mask
1238 }
1239
1240 /// Returns `true` if only one flag is set
1241 pub fn is_one(&self) -> bool {
1242 self.bits().count_ones() == 1
1243 }
1244
1245 pub fn map(&self) -> wgt::TextureAspect {
1246 match *self {
1247 Self::COLOR => wgt::TextureAspect::All,
1248 Self::DEPTH => wgt::TextureAspect::DepthOnly,
1249 Self::STENCIL => wgt::TextureAspect::StencilOnly,
1250 Self::PLANE_0 => wgt::TextureAspect::Plane0,
1251 Self::PLANE_1 => wgt::TextureAspect::Plane1,
1252 Self::PLANE_2 => wgt::TextureAspect::Plane2,
1253 _ => unreachable!(),
1254 }
1255 }
1256}
1257
1258impl From<wgt::TextureFormat> for FormatAspects {
1259 fn from(format: wgt::TextureFormat) -> Self {
1260 match format {
1261 wgt::TextureFormat::Stencil8 => Self::STENCIL,
1262 wgt::TextureFormat::Depth16Unorm
1263 | wgt::TextureFormat::Depth32Float
1264 | wgt::TextureFormat::Depth24Plus => Self::DEPTH,
1265 wgt::TextureFormat::Depth32FloatStencil8 | wgt::TextureFormat::Depth24PlusStencil8 => {
1266 Self::DEPTH_STENCIL
1267 }
1268 wgt::TextureFormat::NV12 => Self::PLANE_0 | Self::PLANE_1,
1269 _ => Self::COLOR,
1270 }
1271 }
1272}
1273
1274bitflags!(
1275 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1276 pub struct MemoryFlags: u32 {
1277 const TRANSIENT = 1 << 0;
1278 const PREFER_COHERENT = 1 << 1;
1279 }
1280);
1281
1282//TODO: it's not intuitive for the backends to consider `LOAD` being optional.
1283
1284bitflags!(
1285 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1286 pub struct AttachmentOps: u8 {
1287 const LOAD = 1 << 0;
1288 const STORE = 1 << 1;
1289 }
1290);
1291
1292bitflags::bitflags! {
1293 /// Similar to `wgt::BufferUsages` but for internal use.
1294 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1295 pub struct BufferUses: u16 {
1296 /// The argument to a read-only mapping.
1297 const MAP_READ = 1 << 0;
1298 /// The argument to a write-only mapping.
1299 const MAP_WRITE = 1 << 1;
1300 /// The source of a hardware copy.
1301 const COPY_SRC = 1 << 2;
1302 /// The destination of a hardware copy.
1303 const COPY_DST = 1 << 3;
1304 /// The index buffer used for drawing.
1305 const INDEX = 1 << 4;
1306 /// A vertex buffer used for drawing.
1307 const VERTEX = 1 << 5;
1308 /// A uniform buffer bound in a bind group.
1309 const UNIFORM = 1 << 6;
1310 /// A read-only storage buffer used in a bind group.
1311 const STORAGE_READ = 1 << 7;
1312 /// A read-write or write-only buffer used in a bind group.
1313 const STORAGE_READ_WRITE = 1 << 8;
1314 /// The indirect or count buffer in a indirect draw or dispatch.
1315 const INDIRECT = 1 << 9;
1316 /// A buffer used to store query results.
1317 const QUERY_RESOLVE = 1 << 10;
1318 const ACCELERATION_STRUCTURE_SCRATCH = 1 << 11;
1319 const BOTTOM_LEVEL_ACCELERATION_STRUCTURE_INPUT = 1 << 12;
1320 const TOP_LEVEL_ACCELERATION_STRUCTURE_INPUT = 1 << 13;
1321 /// The combination of states that a buffer may be in _at the same time_.
1322 const INCLUSIVE = Self::MAP_READ.bits() | Self::COPY_SRC.bits() |
1323 Self::INDEX.bits() | Self::VERTEX.bits() | Self::UNIFORM.bits() |
1324 Self::STORAGE_READ.bits() | Self::INDIRECT.bits() | Self::BOTTOM_LEVEL_ACCELERATION_STRUCTURE_INPUT.bits() | Self::TOP_LEVEL_ACCELERATION_STRUCTURE_INPUT.bits();
1325 /// The combination of states that a buffer must exclusively be in.
1326 const EXCLUSIVE = Self::MAP_WRITE.bits() | Self::COPY_DST.bits() | Self::STORAGE_READ_WRITE.bits() | Self::ACCELERATION_STRUCTURE_SCRATCH.bits();
1327 /// The combination of all usages that the are guaranteed to be be ordered by the hardware.
1328 /// If a usage is ordered, then if the buffer state doesn't change between draw calls, there
1329 /// are no barriers needed for synchronization.
1330 const ORDERED = Self::INCLUSIVE.bits() | Self::MAP_WRITE.bits();
1331 }
1332}
1333
1334bitflags::bitflags! {
1335 /// Similar to `wgt::TextureUsages` but for internal use.
1336 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1337 pub struct TextureUses: u16 {
1338 /// The texture is in unknown state.
1339 const UNINITIALIZED = 1 << 0;
1340 /// Ready to present image to the surface.
1341 const PRESENT = 1 << 1;
1342 /// The source of a hardware copy.
1343 const COPY_SRC = 1 << 2;
1344 /// The destination of a hardware copy.
1345 const COPY_DST = 1 << 3;
1346 /// Read-only sampled or fetched resource.
1347 const RESOURCE = 1 << 4;
1348 /// The color target of a renderpass.
1349 const COLOR_TARGET = 1 << 5;
1350 /// Read-only depth stencil usage.
1351 const DEPTH_STENCIL_READ = 1 << 6;
1352 /// Read-write depth stencil usage
1353 const DEPTH_STENCIL_WRITE = 1 << 7;
1354 /// Read-only storage buffer usage. Corresponds to a UAV in d3d, so is exclusive, despite being read only.
1355 const STORAGE_READ = 1 << 8;
1356 /// Read-write or write-only storage buffer usage.
1357 const STORAGE_READ_WRITE = 1 << 9;
1358 /// The combination of states that a texture may be in _at the same time_.
1359 const INCLUSIVE = Self::COPY_SRC.bits() | Self::RESOURCE.bits() | Self::DEPTH_STENCIL_READ.bits();
1360 /// The combination of states that a texture must exclusively be in.
1361 const EXCLUSIVE = Self::COPY_DST.bits() | Self::COLOR_TARGET.bits() | Self::DEPTH_STENCIL_WRITE.bits() | Self::STORAGE_READ.bits() | Self::STORAGE_READ_WRITE.bits() | Self::PRESENT.bits();
1362 /// The combination of all usages that the are guaranteed to be be ordered by the hardware.
1363 /// If a usage is ordered, then if the texture state doesn't change between draw calls, there
1364 /// are no barriers needed for synchronization.
1365 const ORDERED = Self::INCLUSIVE.bits() | Self::COLOR_TARGET.bits() | Self::DEPTH_STENCIL_WRITE.bits() | Self::STORAGE_READ.bits();
1366
1367 /// Flag used by the wgpu-core texture tracker to say a texture is in different states for every sub-resource
1368 const COMPLEX = 1 << 10;
1369 /// Flag used by the wgpu-core texture tracker to say that the tracker does not know the state of the sub-resource.
1370 /// This is different from UNINITIALIZED as that says the tracker does know, but the texture has not been initialized.
1371 const UNKNOWN = 1 << 11;
1372 }
1373}
1374
1375#[derive(Clone, Debug)]
1376pub struct InstanceDescriptor<'a> {
1377 pub name: &'a str,
1378 pub flags: wgt::InstanceFlags,
1379 pub dx12_shader_compiler: wgt::Dx12Compiler,
1380 pub gles_minor_version: wgt::Gles3MinorVersion,
1381}
1382
1383#[derive(Clone, Debug)]
1384pub struct Alignments {
1385 /// The alignment of the start of the buffer used as a GPU copy source.
1386 pub buffer_copy_offset: wgt::BufferSize,
1387 /// The alignment of the row pitch of the texture data stored in a buffer that is
1388 /// used in a GPU copy operation.
1389 pub buffer_copy_pitch: wgt::BufferSize,
1390}
1391
1392#[derive(Clone, Debug)]
1393pub struct Capabilities {
1394 pub limits: wgt::Limits,
1395 pub alignments: Alignments,
1396 pub downlevel: wgt::DownlevelCapabilities,
1397}
1398
1399#[derive(Debug)]
1400pub struct ExposedAdapter<A: Api> {
1401 pub adapter: A::Adapter,
1402 pub info: wgt::AdapterInfo,
1403 pub features: wgt::Features,
1404 pub capabilities: Capabilities,
1405}
1406
1407/// Describes information about what a `Surface`'s presentation capabilities are.
1408/// Fetch this with [Adapter::surface_capabilities].
1409#[derive(Debug, Clone)]
1410pub struct SurfaceCapabilities {
1411 /// List of supported texture formats.
1412 ///
1413 /// Must be at least one.
1414 pub formats: Vec<wgt::TextureFormat>,
1415
1416 /// Range for the number of queued frames.
1417 ///
1418 /// This adjusts either the swapchain frame count to value + 1 - or sets SetMaximumFrameLatency to the value given,
1419 /// or uses a wait-for-present in the acquire method to limit rendering such that it acts like it's a value + 1 swapchain frame set.
1420 ///
1421 /// - `maximum_frame_latency.start` must be at least 1.
1422 /// - `maximum_frame_latency.end` must be larger or equal to `maximum_frame_latency.start`.
1423 pub maximum_frame_latency: RangeInclusive<u32>,
1424
1425 /// Current extent of the surface, if known.
1426 pub current_extent: Option<wgt::Extent3d>,
1427
1428 /// Supported texture usage flags.
1429 ///
1430 /// Must have at least `TextureUses::COLOR_TARGET`
1431 pub usage: TextureUses,
1432
1433 /// List of supported V-sync modes.
1434 ///
1435 /// Must be at least one.
1436 pub present_modes: Vec<wgt::PresentMode>,
1437
1438 /// List of supported alpha composition modes.
1439 ///
1440 /// Must be at least one.
1441 pub composite_alpha_modes: Vec<wgt::CompositeAlphaMode>,
1442}
1443
1444#[derive(Debug)]
1445pub struct AcquiredSurfaceTexture<A: Api> {
1446 pub texture: A::SurfaceTexture,
1447 /// The presentation configuration no longer matches
1448 /// the surface properties exactly, but can still be used to present
1449 /// to the surface successfully.
1450 pub suboptimal: bool,
1451}
1452
1453#[derive(Debug)]
1454pub struct OpenDevice<A: Api> {
1455 pub device: A::Device,
1456 pub queue: A::Queue,
1457}
1458
1459#[derive(Clone, Debug)]
1460pub struct BufferMapping {
1461 pub ptr: NonNull<u8>,
1462 pub is_coherent: bool,
1463}
1464
1465#[derive(Clone, Debug)]
1466pub struct BufferDescriptor<'a> {
1467 pub label: Label<'a>,
1468 pub size: wgt::BufferAddress,
1469 pub usage: BufferUses,
1470 pub memory_flags: MemoryFlags,
1471}
1472
1473#[derive(Clone, Debug)]
1474pub struct TextureDescriptor<'a> {
1475 pub label: Label<'a>,
1476 pub size: wgt::Extent3d,
1477 pub mip_level_count: u32,
1478 pub sample_count: u32,
1479 pub dimension: wgt::TextureDimension,
1480 pub format: wgt::TextureFormat,
1481 pub usage: TextureUses,
1482 pub memory_flags: MemoryFlags,
1483 /// Allows views of this texture to have a different format
1484 /// than the texture does.
1485 pub view_formats: Vec<wgt::TextureFormat>,
1486}
1487
1488impl TextureDescriptor<'_> {
1489 pub fn copy_extent(&self) -> CopyExtent {
1490 CopyExtent::map_extent_to_copy_size(&self.size, self.dimension)
1491 }
1492
1493 pub fn is_cube_compatible(&self) -> bool {
1494 self.dimension == wgt::TextureDimension::D2
1495 && self.size.depth_or_array_layers % 6 == 0
1496 && self.sample_count == 1
1497 && self.size.width == self.size.height
1498 }
1499
1500 pub fn array_layer_count(&self) -> u32 {
1501 match self.dimension {
1502 wgt::TextureDimension::D1 | wgt::TextureDimension::D3 => 1,
1503 wgt::TextureDimension::D2 => self.size.depth_or_array_layers,
1504 }
1505 }
1506}
1507
1508/// TextureView descriptor.
1509///
1510/// Valid usage:
1511///. - `format` has to be the same as `TextureDescriptor::format`
1512///. - `dimension` has to be compatible with `TextureDescriptor::dimension`
1513///. - `usage` has to be a subset of `TextureDescriptor::usage`
1514///. - `range` has to be a subset of parent texture
1515#[derive(Clone, Debug)]
1516pub struct TextureViewDescriptor<'a> {
1517 pub label: Label<'a>,
1518 pub format: wgt::TextureFormat,
1519 pub dimension: wgt::TextureViewDimension,
1520 pub usage: TextureUses,
1521 pub range: wgt::ImageSubresourceRange,
1522}
1523
1524#[derive(Clone, Debug)]
1525pub struct SamplerDescriptor<'a> {
1526 pub label: Label<'a>,
1527 pub address_modes: [wgt::AddressMode; 3],
1528 pub mag_filter: wgt::FilterMode,
1529 pub min_filter: wgt::FilterMode,
1530 pub mipmap_filter: wgt::FilterMode,
1531 pub lod_clamp: Range<f32>,
1532 pub compare: Option<wgt::CompareFunction>,
1533 // Must in the range [1, 16].
1534 //
1535 // Anisotropic filtering must be supported if this is not 1.
1536 pub anisotropy_clamp: u16,
1537 pub border_color: Option<wgt::SamplerBorderColor>,
1538}
1539
1540/// BindGroupLayout descriptor.
1541///
1542/// Valid usage:
1543/// - `entries` are sorted by ascending `wgt::BindGroupLayoutEntry::binding`
1544#[derive(Clone, Debug)]
1545pub struct BindGroupLayoutDescriptor<'a> {
1546 pub label: Label<'a>,
1547 pub flags: BindGroupLayoutFlags,
1548 pub entries: &'a [wgt::BindGroupLayoutEntry],
1549}
1550
1551#[derive(Clone, Debug)]
1552pub struct PipelineLayoutDescriptor<'a, A: Api> {
1553 pub label: Label<'a>,
1554 pub flags: PipelineLayoutFlags,
1555 pub bind_group_layouts: &'a [&'a A::BindGroupLayout],
1556 pub push_constant_ranges: &'a [wgt::PushConstantRange],
1557}
1558
1559#[derive(Debug)]
1560pub struct BufferBinding<'a, A: Api> {
1561 /// The buffer being bound.
1562 pub buffer: &'a A::Buffer,
1563
1564 /// The offset at which the bound region starts.
1565 ///
1566 /// This must be less than the size of the buffer. Some back ends
1567 /// cannot tolerate zero-length regions; for example, see
1568 /// [VUID-VkDescriptorBufferInfo-offset-00340][340] and
1569 /// [VUID-VkDescriptorBufferInfo-range-00341][341], or the
1570 /// documentation for GLES's [glBindBufferRange][bbr].
1571 ///
1572 /// [340]: https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-VkDescriptorBufferInfo-offset-00340
1573 /// [341]: https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-VkDescriptorBufferInfo-range-00341
1574 /// [bbr]: https://registry.khronos.org/OpenGL-Refpages/es3.0/html/glBindBufferRange.xhtml
1575 pub offset: wgt::BufferAddress,
1576
1577 /// The size of the region bound, in bytes.
1578 ///
1579 /// If `None`, the region extends from `offset` to the end of the
1580 /// buffer. Given the restrictions on `offset`, this means that
1581 /// the size is always greater than zero.
1582 pub size: Option<wgt::BufferSize>,
1583}
1584
1585// Rust gets confused about the impl requirements for `A`
1586impl<A: Api> Clone for BufferBinding<'_, A> {
1587 fn clone(&self) -> Self {
1588 Self {
1589 buffer: self.buffer,
1590 offset: self.offset,
1591 size: self.size,
1592 }
1593 }
1594}
1595
1596#[derive(Debug)]
1597pub struct TextureBinding<'a, A: Api> {
1598 pub view: &'a A::TextureView,
1599 pub usage: TextureUses,
1600}
1601
1602// Rust gets confused about the impl requirements for `A`
1603impl<A: Api> Clone for TextureBinding<'_, A> {
1604 fn clone(&self) -> Self {
1605 Self {
1606 view: self.view,
1607 usage: self.usage,
1608 }
1609 }
1610}
1611
1612#[derive(Clone, Debug)]
1613pub struct BindGroupEntry {
1614 pub binding: u32,
1615 pub resource_index: u32,
1616 pub count: u32,
1617}
1618
1619/// BindGroup descriptor.
1620///
1621/// Valid usage:
1622///. - `entries` has to be sorted by ascending `BindGroupEntry::binding`
1623///. - `entries` has to have the same set of `BindGroupEntry::binding` as `layout`
1624///. - each entry has to be compatible with the `layout`
1625///. - each entry's `BindGroupEntry::resource_index` is within range
1626/// of the corresponding resource array, selected by the relevant
1627/// `BindGroupLayoutEntry`.
1628#[derive(Clone, Debug)]
1629pub struct BindGroupDescriptor<'a, A: Api> {
1630 pub label: Label<'a>,
1631 pub layout: &'a A::BindGroupLayout,
1632 pub buffers: &'a [BufferBinding<'a, A>],
1633 pub samplers: &'a [&'a A::Sampler],
1634 pub textures: &'a [TextureBinding<'a, A>],
1635 pub entries: &'a [BindGroupEntry],
1636 pub acceleration_structures: &'a [&'a A::AccelerationStructure],
1637}
1638
1639#[derive(Clone, Debug)]
1640pub struct CommandEncoderDescriptor<'a, A: Api> {
1641 pub label: Label<'a>,
1642 pub queue: &'a A::Queue,
1643}
1644
1645/// Naga shader module.
1646pub struct NagaShader {
1647 /// Shader module IR.
1648 pub module: Cow<'static, naga::Module>,
1649 /// Analysis information of the module.
1650 pub info: naga::valid::ModuleInfo,
1651 /// Source codes for debug
1652 pub debug_source: Option<DebugSource>,
1653}
1654
1655// Custom implementation avoids the need to generate Debug impl code
1656// for the whole Naga module and info.
1657impl fmt::Debug for NagaShader {
1658 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1659 write!(formatter, "Naga shader")
1660 }
1661}
1662
1663/// Shader input.
1664#[allow(clippy::large_enum_variant)]
1665pub enum ShaderInput<'a> {
1666 Naga(NagaShader),
1667 SpirV(&'a [u32]),
1668}
1669
1670pub struct ShaderModuleDescriptor<'a> {
1671 pub label: Label<'a>,
1672 pub runtime_checks: bool,
1673}
1674
1675#[derive(Debug, Clone)]
1676pub struct DebugSource {
1677 pub file_name: Cow<'static, str>,
1678 pub source_code: Cow<'static, str>,
1679}
1680
1681/// Describes a programmable pipeline stage.
1682#[derive(Debug)]
1683pub struct ProgrammableStage<'a, A: Api> {
1684 /// The compiled shader module for this stage.
1685 pub module: &'a A::ShaderModule,
1686 /// The name of the entry point in the compiled shader. There must be a function with this name
1687 /// in the shader.
1688 pub entry_point: &'a str,
1689 /// Pipeline constants
1690 pub constants: &'a naga::back::PipelineConstants,
1691 /// Whether workgroup scoped memory will be initialized with zero values for this stage.
1692 ///
1693 /// This is required by the WebGPU spec, but may have overhead which can be avoided
1694 /// for cross-platform applications
1695 pub zero_initialize_workgroup_memory: bool,
1696}
1697
1698// Rust gets confused about the impl requirements for `A`
1699impl<A: Api> Clone for ProgrammableStage<'_, A> {
1700 fn clone(&self) -> Self {
1701 Self {
1702 module: self.module,
1703 entry_point: self.entry_point,
1704 constants: self.constants,
1705 zero_initialize_workgroup_memory: self.zero_initialize_workgroup_memory,
1706 }
1707 }
1708}
1709
1710/// Describes a compute pipeline.
1711#[derive(Clone, Debug)]
1712pub struct ComputePipelineDescriptor<'a, A: Api> {
1713 pub label: Label<'a>,
1714 /// The layout of bind groups for this pipeline.
1715 pub layout: &'a A::PipelineLayout,
1716 /// The compiled compute stage and its entry point.
1717 pub stage: ProgrammableStage<'a, A>,
1718}
1719
1720/// Describes how the vertex buffer is interpreted.
1721#[derive(Clone, Debug)]
1722pub struct VertexBufferLayout<'a> {
1723 /// The stride, in bytes, between elements of this buffer.
1724 pub array_stride: wgt::BufferAddress,
1725 /// How often this vertex buffer is "stepped" forward.
1726 pub step_mode: wgt::VertexStepMode,
1727 /// The list of attributes which comprise a single vertex.
1728 pub attributes: &'a [wgt::VertexAttribute],
1729}
1730
1731/// Describes a render (graphics) pipeline.
1732#[derive(Clone, Debug)]
1733pub struct RenderPipelineDescriptor<'a, A: Api> {
1734 pub label: Label<'a>,
1735 /// The layout of bind groups for this pipeline.
1736 pub layout: &'a A::PipelineLayout,
1737 /// The format of any vertex buffers used with this pipeline.
1738 pub vertex_buffers: &'a [VertexBufferLayout<'a>],
1739 /// The vertex stage for this pipeline.
1740 pub vertex_stage: ProgrammableStage<'a, A>,
1741 /// The properties of the pipeline at the primitive assembly and rasterization level.
1742 pub primitive: wgt::PrimitiveState,
1743 /// The effect of draw calls on the depth and stencil aspects of the output target, if any.
1744 pub depth_stencil: Option<wgt::DepthStencilState>,
1745 /// The multi-sampling properties of the pipeline.
1746 pub multisample: wgt::MultisampleState,
1747 /// The fragment stage for this pipeline.
1748 pub fragment_stage: Option<ProgrammableStage<'a, A>>,
1749 /// The effect of draw calls on the color aspect of the output target.
1750 pub color_targets: &'a [Option<wgt::ColorTargetState>],
1751 /// If the pipeline will be used with a multiview render pass, this indicates how many array
1752 /// layers the attachments will have.
1753 pub multiview: Option<NonZeroU32>,
1754}
1755
1756#[derive(Debug, Clone)]
1757pub struct SurfaceConfiguration {
1758 /// Maximum number of queued frames. Must be in
1759 /// `SurfaceCapabilities::maximum_frame_latency` range.
1760 pub maximum_frame_latency: u32,
1761 /// Vertical synchronization mode.
1762 pub present_mode: wgt::PresentMode,
1763 /// Alpha composition mode.
1764 pub composite_alpha_mode: wgt::CompositeAlphaMode,
1765 /// Format of the surface textures.
1766 pub format: wgt::TextureFormat,
1767 /// Requested texture extent. Must be in
1768 /// `SurfaceCapabilities::extents` range.
1769 pub extent: wgt::Extent3d,
1770 /// Allowed usage of surface textures,
1771 pub usage: TextureUses,
1772 /// Allows views of swapchain texture to have a different format
1773 /// than the texture does.
1774 pub view_formats: Vec<wgt::TextureFormat>,
1775}
1776
1777#[derive(Debug, Clone)]
1778pub struct Rect<T> {
1779 pub x: T,
1780 pub y: T,
1781 pub w: T,
1782 pub h: T,
1783}
1784
1785#[derive(Debug, Clone)]
1786pub struct BufferBarrier<'a, A: Api> {
1787 pub buffer: &'a A::Buffer,
1788 pub usage: Range<BufferUses>,
1789}
1790
1791#[derive(Debug, Clone)]
1792pub struct TextureBarrier<'a, A: Api> {
1793 pub texture: &'a A::Texture,
1794 pub range: wgt::ImageSubresourceRange,
1795 pub usage: Range<TextureUses>,
1796}
1797
1798#[derive(Clone, Copy, Debug)]
1799pub struct BufferCopy {
1800 pub src_offset: wgt::BufferAddress,
1801 pub dst_offset: wgt::BufferAddress,
1802 pub size: wgt::BufferSize,
1803}
1804
1805#[derive(Clone, Debug)]
1806pub struct TextureCopyBase {
1807 pub mip_level: u32,
1808 pub array_layer: u32,
1809 /// Origin within a texture.
1810 /// Note: for 1D and 2D textures, Z must be 0.
1811 pub origin: wgt::Origin3d,
1812 pub aspect: FormatAspects,
1813}
1814
1815#[derive(Clone, Copy, Debug)]
1816pub struct CopyExtent {
1817 pub width: u32,
1818 pub height: u32,
1819 pub depth: u32,
1820}
1821
1822#[derive(Clone, Debug)]
1823pub struct TextureCopy {
1824 pub src_base: TextureCopyBase,
1825 pub dst_base: TextureCopyBase,
1826 pub size: CopyExtent,
1827}
1828
1829#[derive(Clone, Debug)]
1830pub struct BufferTextureCopy {
1831 pub buffer_layout: wgt::ImageDataLayout,
1832 pub texture_base: TextureCopyBase,
1833 pub size: CopyExtent,
1834}
1835
1836#[derive(Debug)]
1837pub struct Attachment<'a, A: Api> {
1838 pub view: &'a A::TextureView,
1839 /// Contains either a single mutating usage as a target,
1840 /// or a valid combination of read-only usages.
1841 pub usage: TextureUses,
1842}
1843
1844// Rust gets confused about the impl requirements for `A`
1845impl<A: Api> Clone for Attachment<'_, A> {
1846 fn clone(&self) -> Self {
1847 Self {
1848 view: self.view,
1849 usage: self.usage,
1850 }
1851 }
1852}
1853
1854#[derive(Debug)]
1855pub struct ColorAttachment<'a, A: Api> {
1856 pub target: Attachment<'a, A>,
1857 pub resolve_target: Option<Attachment<'a, A>>,
1858 pub ops: AttachmentOps,
1859 pub clear_value: wgt::Color,
1860}
1861
1862// Rust gets confused about the impl requirements for `A`
1863impl<A: Api> Clone for ColorAttachment<'_, A> {
1864 fn clone(&self) -> Self {
1865 Self {
1866 target: self.target.clone(),
1867 resolve_target: self.resolve_target.clone(),
1868 ops: self.ops,
1869 clear_value: self.clear_value,
1870 }
1871 }
1872}
1873
1874#[derive(Clone, Debug)]
1875pub struct DepthStencilAttachment<'a, A: Api> {
1876 pub target: Attachment<'a, A>,
1877 pub depth_ops: AttachmentOps,
1878 pub stencil_ops: AttachmentOps,
1879 pub clear_value: (f32, u32),
1880}
1881
1882#[derive(Debug)]
1883pub struct RenderPassTimestampWrites<'a, A: Api> {
1884 pub query_set: &'a A::QuerySet,
1885 pub beginning_of_pass_write_index: Option<u32>,
1886 pub end_of_pass_write_index: Option<u32>,
1887}
1888
1889// Rust gets confused about the impl requirements for `A`
1890impl<A: Api> Clone for RenderPassTimestampWrites<'_, A> {
1891 fn clone(&self) -> Self {
1892 Self {
1893 query_set: self.query_set,
1894 beginning_of_pass_write_index: self.beginning_of_pass_write_index,
1895 end_of_pass_write_index: self.end_of_pass_write_index,
1896 }
1897 }
1898}
1899
1900#[derive(Clone, Debug)]
1901pub struct RenderPassDescriptor<'a, A: Api> {
1902 pub label: Label<'a>,
1903 pub extent: wgt::Extent3d,
1904 pub sample_count: u32,
1905 pub color_attachments: &'a [Option<ColorAttachment<'a, A>>],
1906 pub depth_stencil_attachment: Option<DepthStencilAttachment<'a, A>>,
1907 pub multiview: Option<NonZeroU32>,
1908 pub timestamp_writes: Option<RenderPassTimestampWrites<'a, A>>,
1909 pub occlusion_query_set: Option<&'a A::QuerySet>,
1910}
1911
1912#[derive(Debug)]
1913pub struct ComputePassTimestampWrites<'a, A: Api> {
1914 pub query_set: &'a A::QuerySet,
1915 pub beginning_of_pass_write_index: Option<u32>,
1916 pub end_of_pass_write_index: Option<u32>,
1917}
1918
1919// Rust gets confused about the impl requirements for `A`
1920impl<A: Api> Clone for ComputePassTimestampWrites<'_, A> {
1921 fn clone(&self) -> Self {
1922 Self {
1923 query_set: self.query_set,
1924 beginning_of_pass_write_index: self.beginning_of_pass_write_index,
1925 end_of_pass_write_index: self.end_of_pass_write_index,
1926 }
1927 }
1928}
1929
1930#[derive(Clone, Debug)]
1931pub struct ComputePassDescriptor<'a, A: Api> {
1932 pub label: Label<'a>,
1933 pub timestamp_writes: Option<ComputePassTimestampWrites<'a, A>>,
1934}
1935
1936/// Stores the text of any validation errors that have occurred since
1937/// the last call to `get_and_reset`.
1938///
1939/// Each value is a validation error and a message associated with it,
1940/// or `None` if the error has no message from the api.
1941///
1942/// This is used for internal wgpu testing only and _must not_ be used
1943/// as a way to check for errors.
1944///
1945/// This works as a static because `cargo nextest` runs all of our
1946/// tests in separate processes, so each test gets its own canary.
1947///
1948/// This prevents the issue of one validation error terminating the
1949/// entire process.
1950pub static VALIDATION_CANARY: ValidationCanary = ValidationCanary {
1951 inner: Mutex::new(Vec::new()),
1952};
1953
1954/// Flag for internal testing.
1955pub struct ValidationCanary {
1956 inner: Mutex<Vec<String>>,
1957}
1958
1959impl ValidationCanary {
1960 #[allow(dead_code)] // in some configurations this function is dead
1961 fn add(&self, msg: String) {
1962 self.inner.lock().push(msg);
1963 }
1964
1965 /// Returns any API validation errors that have occurred in this process
1966 /// since the last call to this function.
1967 pub fn get_and_reset(&self) -> Vec<String> {
1968 self.inner.lock().drain(..).collect()
1969 }
1970}
1971
1972#[test]
1973fn test_default_limits() {
1974 let limits = wgt::Limits::default();
1975 assert!(limits.max_bind_groups <= MAX_BIND_GROUPS as u32);
1976}
1977
1978#[derive(Clone, Debug)]
1979pub struct AccelerationStructureDescriptor<'a> {
1980 pub label: Label<'a>,
1981 pub size: wgt::BufferAddress,
1982 pub format: AccelerationStructureFormat,
1983}
1984
1985#[derive(Debug, Clone, Copy, Eq, PartialEq)]
1986pub enum AccelerationStructureFormat {
1987 TopLevel,
1988 BottomLevel,
1989}
1990
1991#[derive(Debug, Clone, Copy, Eq, PartialEq)]
1992pub enum AccelerationStructureBuildMode {
1993 Build,
1994 Update,
1995}
1996
1997/// Information of the required size for a corresponding entries struct (+ flags)
1998#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
1999pub struct AccelerationStructureBuildSizes {
2000 pub acceleration_structure_size: wgt::BufferAddress,
2001 pub update_scratch_size: wgt::BufferAddress,
2002 pub build_scratch_size: wgt::BufferAddress,
2003}
2004
2005/// Updates use source_acceleration_structure if present, else the update will be performed in place.
2006/// For updates, only the data is allowed to change (not the meta data or sizes).
2007#[derive(Clone, Debug)]
2008pub struct BuildAccelerationStructureDescriptor<'a, A: Api> {
2009 pub entries: &'a AccelerationStructureEntries<'a, A>,
2010 pub mode: AccelerationStructureBuildMode,
2011 pub flags: AccelerationStructureBuildFlags,
2012 pub source_acceleration_structure: Option<&'a A::AccelerationStructure>,
2013 pub destination_acceleration_structure: &'a A::AccelerationStructure,
2014 pub scratch_buffer: &'a A::Buffer,
2015 pub scratch_buffer_offset: wgt::BufferAddress,
2016}
2017
2018/// - All buffers, buffer addresses and offsets will be ignored.
2019/// - The build mode will be ignored.
2020/// - Reducing the amount of Instances, Triangle groups or AABB groups (or the number of Triangles/AABBs in corresponding groups),
2021/// may result in reduced size requirements.
2022/// - Any other change may result in a bigger or smaller size requirement.
2023#[derive(Clone, Debug)]
2024pub struct GetAccelerationStructureBuildSizesDescriptor<'a, A: Api> {
2025 pub entries: &'a AccelerationStructureEntries<'a, A>,
2026 pub flags: AccelerationStructureBuildFlags,
2027}
2028
2029/// Entries for a single descriptor
2030/// * `Instances` - Multiple instances for a top level acceleration structure
2031/// * `Triangles` - Multiple triangle meshes for a bottom level acceleration structure
2032/// * `AABBs` - List of list of axis aligned bounding boxes for a bottom level acceleration structure
2033#[derive(Debug)]
2034pub enum AccelerationStructureEntries<'a, A: Api> {
2035 Instances(AccelerationStructureInstances<'a, A>),
2036 Triangles(Vec<AccelerationStructureTriangles<'a, A>>),
2037 AABBs(Vec<AccelerationStructureAABBs<'a, A>>),
2038}
2039
2040/// * `first_vertex` - offset in the vertex buffer (as number of vertices)
2041/// * `indices` - optional index buffer with attributes
2042/// * `transform` - optional transform
2043#[derive(Clone, Debug)]
2044pub struct AccelerationStructureTriangles<'a, A: Api> {
2045 pub vertex_buffer: Option<&'a A::Buffer>,
2046 pub vertex_format: wgt::VertexFormat,
2047 pub first_vertex: u32,
2048 pub vertex_count: u32,
2049 pub vertex_stride: wgt::BufferAddress,
2050 pub indices: Option<AccelerationStructureTriangleIndices<'a, A>>,
2051 pub transform: Option<AccelerationStructureTriangleTransform<'a, A>>,
2052 pub flags: AccelerationStructureGeometryFlags,
2053}
2054
2055/// * `offset` - offset in bytes
2056#[derive(Clone, Debug)]
2057pub struct AccelerationStructureAABBs<'a, A: Api> {
2058 pub buffer: Option<&'a A::Buffer>,
2059 pub offset: u32,
2060 pub count: u32,
2061 pub stride: wgt::BufferAddress,
2062 pub flags: AccelerationStructureGeometryFlags,
2063}
2064
2065/// * `offset` - offset in bytes
2066#[derive(Clone, Debug)]
2067pub struct AccelerationStructureInstances<'a, A: Api> {
2068 pub buffer: Option<&'a A::Buffer>,
2069 pub offset: u32,
2070 pub count: u32,
2071}
2072
2073/// * `offset` - offset in bytes
2074#[derive(Clone, Debug)]
2075pub struct AccelerationStructureTriangleIndices<'a, A: Api> {
2076 pub format: wgt::IndexFormat,
2077 pub buffer: Option<&'a A::Buffer>,
2078 pub offset: u32,
2079 pub count: u32,
2080}
2081
2082/// * `offset` - offset in bytes
2083#[derive(Clone, Debug)]
2084pub struct AccelerationStructureTriangleTransform<'a, A: Api> {
2085 pub buffer: &'a A::Buffer,
2086 pub offset: u32,
2087}
2088
2089pub use wgt::AccelerationStructureFlags as AccelerationStructureBuildFlags;
2090pub use wgt::AccelerationStructureGeometryFlags;
2091
2092bitflags::bitflags! {
2093 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
2094 pub struct AccelerationStructureUses: u8 {
2095 // For blas used as input for tlas
2096 const BUILD_INPUT = 1 << 0;
2097 // Target for acceleration structure build
2098 const BUILD_OUTPUT = 1 << 1;
2099 // Tlas used in a shader
2100 const SHADER_INPUT = 1 << 2;
2101 }
2102}
2103
2104#[derive(Debug, Clone)]
2105pub struct AccelerationStructureBarrier {
2106 pub usage: Range<AccelerationStructureUses>,
2107}