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 can
44//! remain mapped on the CPU while the GPU reads or writes to it. You must
45//! explicitly indicate when data might need to be transferred between CPU and
46//! GPU, if [`Device::map_buffer`] indicates that this is necessary.
47//!
48//! - You must record *explicit barriers* between different usages of a
49//! resource. For example, if a buffer is written to by a compute
50//! shader, and then used as and index buffer to a draw call, you
51//! must use [`CommandEncoder::transition_buffers`] between those two
52//! operations.
53//!
54//! - Pipeline layouts are *explicitly specified* when setting bind groups.
55//! Incompatible layouts disturb groups bound at higher indices.
56//!
57//! - The API *accepts collections as iterators*, to avoid forcing the user to
58//! store data in particular containers. The implementation doesn't guarantee
59//! that any of the iterators are drained, unless stated otherwise by the
60//! function documentation. For this reason, we recommend that iterators don't
61//! do any mutating work.
62//!
63//! Unfortunately, `wgpu-hal`'s safety requirements are not fully documented.
64//! Ideally, all trait methods would have doc comments setting out the
65//! requirements users must meet to ensure correct and portable behavior. If you
66//! are aware of a specific requirement that a backend imposes that is not
67//! ensured by the traits' documented rules, please file an issue. Or, if you are
68//! a capable technical writer, please file a pull request!
69//!
70//! [`wgpu-core`]: https://crates.io/crates/wgpu-core
71//! [`wgpu`]: https://crates.io/crates/wgpu
72//! [`vulkan::Api`]: vulkan/struct.Api.html
73//! [`metal::Api`]: metal/struct.Api.html
74//!
75//! ## Primary backends
76//!
77//! The `wgpu-hal` crate has full-featured backends implemented on the following
78//! platform graphics APIs:
79//!
80//! - Vulkan, available on Linux, Android, and Windows, using the [`ash`] crate's
81//! Vulkan bindings. It's also available on macOS, if you install [MoltenVK].
82//!
83//! - Metal on macOS, using the [`metal`] crate's bindings.
84//!
85//! - Direct3D 12 on Windows, using the [`windows`] crate's bindings.
86//!
87//! [`ash`]: https://crates.io/crates/ash
88//! [MoltenVK]: https://github.com/KhronosGroup/MoltenVK
89//! [`metal`]: https://crates.io/crates/metal
90//! [`windows`]: https://crates.io/crates/windows
91//!
92//! ## Secondary backends
93//!
94//! The `wgpu-hal` crate has a partial implementation based on the following
95//! platform graphics API:
96//!
97//! - The GL backend is available anywhere OpenGL, OpenGL ES, or WebGL are
98//! available. See the [`gles`] module documentation for details.
99//!
100//! [`gles`]: gles/index.html
101//!
102//! You can see what capabilities an adapter is missing by checking the
103//! [`DownlevelCapabilities`][tdc] in [`ExposedAdapter::capabilities`], available
104//! from [`Instance::enumerate_adapters`].
105//!
106//! The API is generally designed to fit the primary backends better than the
107//! secondary backends, so the latter may impose more overhead.
108//!
109//! [tdc]: wgt::DownlevelCapabilities
110//!
111//! ## Traits
112//!
113//! The `wgpu-hal` crate defines a handful of traits that together
114//! represent a cross-platform abstraction for modern GPU APIs.
115//!
116//! - The [`Api`] trait represents a `wgpu-hal` backend. It has no methods of its
117//! own, only a collection of associated types.
118//!
119//! - [`Api::Instance`] implements the [`Instance`] trait. [`Instance::init`]
120//! creates an instance value, which you can use to enumerate the adapters
121//! available on the system. For example, [`vulkan::Api::Instance::init`][Ii]
122//! returns an instance that can enumerate the Vulkan physical devices on your
123//! system.
124//!
125//! - [`Api::Adapter`] implements the [`Adapter`] trait, representing a
126//! particular device from a particular backend. For example, a Vulkan instance
127//! might have a Lavapipe software adapter and a GPU-based adapter.
128//!
129//! - [`Api::Device`] implements the [`Device`] trait, representing an active
130//! link to a device. You get a device value by calling [`Adapter::open`], and
131//! then use it to create buffers, textures, shader modules, and so on.
132//!
133//! - [`Api::Queue`] implements the [`Queue`] trait, which you use to submit
134//! command buffers to a given device.
135//!
136//! - [`Api::CommandEncoder`] implements the [`CommandEncoder`] trait, which you
137//! use to build buffers of commands to submit to a queue. This has all the
138//! methods for drawing and running compute shaders, which is presumably what
139//! you're here for.
140//!
141//! - [`Api::Surface`] implements the [`Surface`] trait, which represents a
142//! swapchain for presenting images on the screen, via interaction with the
143//! system's window manager.
144//!
145//! The [`Api`] trait has various other associated types like [`Api::Buffer`] and
146//! [`Api::Texture`] that represent resources the rest of the interface can
147//! operate on, but these generally do not have their own traits.
148//!
149//! [Ii]: Instance::init
150//!
151//! ## Validation is the calling code's responsibility, not `wgpu-hal`'s
152//!
153//! As much as possible, `wgpu-hal` traits place the burden of validation,
154//! resource tracking, and state tracking on the caller, not on the trait
155//! implementations themselves. Anything which can reasonably be handled in
156//! backend-independent code should be. A `wgpu_hal` backend's sole obligation is
157//! to provide portable behavior, and report conditions that the calling code
158//! can't reasonably anticipate, like device loss or running out of memory.
159//!
160//! The `wgpu` crate collection is intended for use in security-sensitive
161//! applications, like web browsers, where the API is available to untrusted
162//! code. This means that `wgpu-core`'s validation is not simply a service to
163//! developers, to be provided opportunistically when the performance costs are
164//! acceptable and the necessary data is ready at hand. Rather, `wgpu-core`'s
165//! validation must be exhaustive, to ensure that even malicious content cannot
166//! provoke and exploit undefined behavior in the platform's graphics API.
167//!
168//! Because graphics APIs' requirements are complex, the only practical way for
169//! `wgpu` to provide exhaustive validation is to comprehensively track the
170//! lifetime and state of all the resources in the system. Implementing this
171//! separately for each backend is infeasible; effort would be better spent
172//! making the cross-platform validation in `wgpu-core` legible and trustworthy.
173//! Fortunately, the requirements are largely similar across the various
174//! platforms, so cross-platform validation is practical.
175//!
176//! Some backends have specific requirements that aren't practical to foist off
177//! on the `wgpu-hal` user. For example, properly managing macOS Objective-C or
178//! Microsoft COM reference counts is best handled by using appropriate pointer
179//! types within the backend.
180//!
181//! A desire for "defense in depth" may suggest performing additional validation
182//! in `wgpu-hal` when the opportunity arises, but this must be done with
183//! caution. Even experienced contributors infer the expectations their changes
184//! must meet by considering not just requirements made explicit in types, tests,
185//! assertions, and comments, but also those implicit in the surrounding code.
186//! When one sees validation or state-tracking code in `wgpu-hal`, it is tempting
187//! to conclude, "Oh, `wgpu-hal` checks for this, so `wgpu-core` needn't worry
188//! about it - that would be redundant!" The responsibility for exhaustive
189//! validation always rests with `wgpu-core`, regardless of what may or may not
190//! be checked in `wgpu-hal`.
191//!
192//! To this end, any "defense in depth" validation that does appear in `wgpu-hal`
193//! for requirements that `wgpu-core` should have enforced should report failure
194//! via the `unreachable!` macro, because problems detected at this stage always
195//! indicate a bug in `wgpu-core`.
196//!
197//! ## Debugging
198//!
199//! Most of the information on the wiki [Debugging wgpu Applications][wiki-debug]
200//! page still applies to this API, with the exception of API tracing/replay
201//! functionality, which is only available in `wgpu-core`.
202//!
203//! [wiki-debug]: https://github.com/gfx-rs/wgpu/wiki/Debugging-wgpu-Applications
204
205#![no_std]
206#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
207#![allow(
208 // this happens on the GL backend, where it is both thread safe and non-thread safe in the same code.
209 clippy::arc_with_non_send_sync,
210 // We don't use syntax sugar where it's not necessary.
211 clippy::match_like_matches_macro,
212 // Redundant matching is more explicit.
213 clippy::redundant_pattern_matching,
214 // Explicit lifetimes are often easier to reason about.
215 clippy::needless_lifetimes,
216 // No need for defaults in the internal types.
217 clippy::new_without_default,
218 // Matches are good and extendable, no need to make an exception here.
219 clippy::single_match,
220 // Push commands are more regular than macros.
221 clippy::vec_init_then_push,
222 // We unsafe impl `Send` for a reason.
223 clippy::non_send_fields_in_send_ty,
224 // TODO!
225 clippy::missing_safety_doc,
226 // It gets in the way a lot and does not prevent bugs in practice.
227 clippy::pattern_type_mismatch,
228 // We should investigate these.
229 clippy::large_enum_variant
230)]
231#![warn(
232 clippy::alloc_instead_of_core,
233 clippy::ptr_as_ptr,
234 clippy::std_instead_of_alloc,
235 clippy::std_instead_of_core,
236 trivial_casts,
237 trivial_numeric_casts,
238 unsafe_op_in_unsafe_fn,
239 unused_extern_crates,
240 unused_qualifications
241)]
242
243extern crate alloc;
244extern crate wgpu_types as wgt;
245// Each of these backends needs `std` in some fashion; usually `std::thread` functions.
246#[cfg(any(dx12, gles_with_std, metal, vulkan))]
247#[macro_use]
248extern crate std;
249
250/// DirectX12 API internals.
251#[cfg(dx12)]
252pub mod dx12;
253/// GLES API internals.
254#[cfg(gles)]
255pub mod gles;
256/// Metal API internals.
257#[cfg(metal)]
258pub mod metal;
259/// A dummy API implementation.
260// TODO(https://github.com/gfx-rs/wgpu/issues/7120): this should have a cfg
261pub mod noop;
262/// Vulkan API internals.
263#[cfg(vulkan)]
264pub mod vulkan;
265
266pub mod auxil;
267pub mod api {
268 #[cfg(dx12)]
269 pub use super::dx12::Api as Dx12;
270 #[cfg(gles)]
271 pub use super::gles::Api as Gles;
272 #[cfg(metal)]
273 pub use super::metal::Api as Metal;
274 pub use super::noop::Api as Noop;
275 #[cfg(vulkan)]
276 pub use super::vulkan::Api as Vulkan;
277}
278
279mod dynamic;
280#[cfg(feature = "validation_canary")]
281mod validation_canary;
282
283#[cfg(feature = "validation_canary")]
284pub use validation_canary::{ValidationCanary, VALIDATION_CANARY};
285
286pub(crate) use dynamic::impl_dyn_resource;
287pub use dynamic::{
288 DynAccelerationStructure, DynAcquiredSurfaceTexture, DynAdapter, DynBindGroup,
289 DynBindGroupLayout, DynBuffer, DynCommandBuffer, DynCommandEncoder, DynComputePipeline,
290 DynDevice, DynExposedAdapter, DynFence, DynInstance, DynOpenDevice, DynPipelineCache,
291 DynPipelineLayout, DynQuerySet, DynQueue, DynRenderPipeline, DynResource, DynSampler,
292 DynShaderModule, DynSurface, DynSurfaceTexture, DynTexture, DynTextureView,
293};
294
295#[allow(unused)]
296use alloc::boxed::Box;
297use alloc::{borrow::Cow, string::String, vec::Vec};
298use core::{
299 borrow::Borrow,
300 error::Error,
301 fmt,
302 num::{NonZeroU32, NonZeroU64},
303 ops::{Range, RangeInclusive},
304 ptr::NonNull,
305};
306
307use bitflags::bitflags;
308use thiserror::Error;
309use wgt::WasmNotSendSync;
310
311cfg_if::cfg_if! {
312 if #[cfg(supports_ptr_atomics)] {
313 use alloc::sync::Arc;
314 } else if #[cfg(feature = "portable-atomic")] {
315 use portable_atomic_util::Arc;
316 }
317}
318
319// - Vertex + Fragment
320// - Compute
321// Task + Mesh + Fragment
322pub const MAX_CONCURRENT_SHADER_STAGES: usize = 3;
323pub const MAX_ANISOTROPY: u8 = 16;
324pub const MAX_BIND_GROUPS: usize = 8;
325pub const MAX_VERTEX_BUFFERS: usize = 16;
326pub const MAX_COLOR_ATTACHMENTS: usize = 8;
327pub const MAX_MIP_LEVELS: u32 = 16;
328/// Size of a single occlusion/timestamp query, when copied into a buffer, in bytes.
329/// cbindgen:ignore
330pub const QUERY_SIZE: wgt::BufferAddress = 8;
331
332pub type Label<'a> = Option<&'a str>;
333pub type MemoryRange = Range<wgt::BufferAddress>;
334pub type FenceValue = u64;
335#[cfg(supports_64bit_atomics)]
336pub type AtomicFenceValue = core::sync::atomic::AtomicU64;
337#[cfg(not(supports_64bit_atomics))]
338pub type AtomicFenceValue = portable_atomic::AtomicU64;
339
340/// A callback to signal that wgpu is no longer using a resource.
341#[cfg(any(gles, vulkan))]
342pub type DropCallback = Box<dyn FnOnce() + Send + Sync + 'static>;
343
344#[cfg(any(gles, vulkan))]
345pub struct DropGuard {
346 callback: Option<DropCallback>,
347}
348
349#[cfg(all(any(gles, vulkan), any(native, Emscripten)))]
350impl DropGuard {
351 fn from_option(callback: Option<DropCallback>) -> Option<Self> {
352 callback.map(|callback| Self {
353 callback: Some(callback),
354 })
355 }
356}
357
358#[cfg(any(gles, vulkan))]
359impl Drop for DropGuard {
360 fn drop(&mut self) {
361 if let Some(cb) = self.callback.take() {
362 (cb)();
363 }
364 }
365}
366
367#[cfg(any(gles, vulkan))]
368impl fmt::Debug for DropGuard {
369 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
370 f.debug_struct("DropGuard").finish()
371 }
372}
373
374#[derive(Clone, Debug, PartialEq, Eq, Error)]
375pub enum DeviceError {
376 #[error("Out of memory")]
377 OutOfMemory,
378 #[error("Device is lost")]
379 Lost,
380 #[error("Unexpected error variant (driver implementation is at fault)")]
381 Unexpected,
382}
383
384#[allow(dead_code)] // may be unused on some platforms
385#[cold]
386fn hal_usage_error<T: fmt::Display>(txt: T) -> ! {
387 panic!("wgpu-hal invariant was violated (usage error): {txt}")
388}
389
390#[allow(dead_code)] // may be unused on some platforms
391#[cold]
392fn hal_internal_error<T: fmt::Display>(txt: T) -> ! {
393 panic!("wgpu-hal ran into a preventable internal error: {txt}")
394}
395
396#[derive(Clone, Debug, Eq, PartialEq, Error)]
397pub enum ShaderError {
398 #[error("Compilation failed: {0:?}")]
399 Compilation(String),
400 #[error(transparent)]
401 Device(#[from] DeviceError),
402}
403
404#[derive(Clone, Debug, Eq, PartialEq, Error)]
405pub enum PipelineError {
406 #[error("Linkage failed for stage {0:?}: {1}")]
407 Linkage(wgt::ShaderStages, String),
408 #[error("Entry point for stage {0:?} is invalid")]
409 EntryPoint(naga::ShaderStage),
410 #[error(transparent)]
411 Device(#[from] DeviceError),
412 #[error("Pipeline constant error for stage {0:?}: {1}")]
413 PipelineConstants(wgt::ShaderStages, String),
414}
415
416#[derive(Clone, Debug, Eq, PartialEq, Error)]
417pub enum PipelineCacheError {
418 #[error(transparent)]
419 Device(#[from] DeviceError),
420}
421
422#[derive(Clone, Debug, Eq, PartialEq, Error)]
423pub enum SurfaceError {
424 #[error("Surface is lost")]
425 Lost,
426 #[error("Surface is outdated, needs to be re-created")]
427 Outdated,
428 #[error(transparent)]
429 Device(#[from] DeviceError),
430 #[error("Other reason: {0}")]
431 Other(&'static str),
432}
433
434/// Error occurring while trying to create an instance, or create a surface from an instance;
435/// typically relating to the state of the underlying graphics API or hardware.
436#[derive(Clone, Debug, Error)]
437#[error("{message}")]
438pub struct InstanceError {
439 /// These errors are very platform specific, so do not attempt to encode them as an enum.
440 ///
441 /// This message should describe the problem in sufficient detail to be useful for a
442 /// user-to-developer “why won't this work on my machine” bug report, and otherwise follow
443 /// <https://rust-lang.github.io/api-guidelines/interoperability.html#error-types-are-meaningful-and-well-behaved-c-good-err>.
444 message: String,
445
446 /// Underlying error value, if any is available.
447 #[source]
448 source: Option<Arc<dyn Error + Send + Sync + 'static>>,
449}
450
451impl InstanceError {
452 #[allow(dead_code)] // may be unused on some platforms
453 pub(crate) fn new(message: String) -> Self {
454 Self {
455 message,
456 source: None,
457 }
458 }
459 #[allow(dead_code)] // may be unused on some platforms
460 pub(crate) fn with_source(message: String, source: impl Error + Send + Sync + 'static) -> Self {
461 cfg_if::cfg_if! {
462 if #[cfg(supports_ptr_atomics)] {
463 let source = Arc::new(source);
464 } else {
465 // TODO(https://github.com/rust-lang/rust/issues/18598): avoid indirection via Box once arbitrary types support unsized coercion
466 let source: Box<dyn Error + Send + Sync + 'static> = Box::new(source);
467 let source = Arc::from(source);
468 }
469 }
470 Self {
471 message,
472 source: Some(source),
473 }
474 }
475}
476
477/// All the types and methods that make up a implementation on top of a backend.
478///
479/// Only the types that have non-dyn trait bounds have methods on them. Most methods
480/// are either on [`CommandEncoder`] or [`Device`].
481///
482/// The api can either be used through generics (through use of this trait and associated
483/// types) or dynamically through using the `Dyn*` traits.
484pub trait Api: Clone + fmt::Debug + Sized + WasmNotSendSync + 'static {
485 const VARIANT: wgt::Backend;
486
487 type Instance: DynInstance + Instance<A = Self>;
488 type Surface: DynSurface + Surface<A = Self>;
489 type Adapter: DynAdapter + Adapter<A = Self>;
490 type Device: DynDevice + Device<A = Self>;
491
492 type Queue: DynQueue + Queue<A = Self>;
493 type CommandEncoder: DynCommandEncoder + CommandEncoder<A = Self>;
494
495 /// This API's command buffer type.
496 ///
497 /// The only thing you can do with `CommandBuffer`s is build them
498 /// with a [`CommandEncoder`] and then pass them to
499 /// [`Queue::submit`] for execution, or destroy them by passing
500 /// them to [`CommandEncoder::reset_all`].
501 ///
502 /// [`CommandEncoder`]: Api::CommandEncoder
503 type CommandBuffer: DynCommandBuffer;
504
505 type Buffer: DynBuffer;
506 type Texture: DynTexture;
507 type SurfaceTexture: DynSurfaceTexture + Borrow<Self::Texture>;
508 type TextureView: DynTextureView;
509 type Sampler: DynSampler;
510 type QuerySet: DynQuerySet;
511
512 /// A value you can block on to wait for something to finish.
513 ///
514 /// A `Fence` holds a monotonically increasing [`FenceValue`]. You can call
515 /// [`Device::wait`] to block until a fence reaches or passes a value you
516 /// choose. [`Queue::submit`] can take a `Fence` and a [`FenceValue`] to
517 /// store in it when the submitted work is complete.
518 ///
519 /// Attempting to set a fence to a value less than its current value has no
520 /// effect.
521 ///
522 /// Waiting on a fence returns as soon as the fence reaches *or passes* the
523 /// requested value. This implies that, in order to reliably determine when
524 /// an operation has completed, operations must finish in order of
525 /// increasing fence values: if a higher-valued operation were to finish
526 /// before a lower-valued operation, then waiting for the fence to reach the
527 /// lower value could return before the lower-valued operation has actually
528 /// finished.
529 type Fence: DynFence;
530
531 type BindGroupLayout: DynBindGroupLayout;
532 type BindGroup: DynBindGroup;
533 type PipelineLayout: DynPipelineLayout;
534 type ShaderModule: DynShaderModule;
535 type RenderPipeline: DynRenderPipeline;
536 type ComputePipeline: DynComputePipeline;
537 type PipelineCache: DynPipelineCache;
538
539 type AccelerationStructure: DynAccelerationStructure + 'static;
540}
541
542pub trait Instance: Sized + WasmNotSendSync {
543 type A: Api;
544
545 unsafe fn init(desc: &InstanceDescriptor) -> Result<Self, InstanceError>;
546 unsafe fn create_surface(
547 &self,
548 display_handle: raw_window_handle::RawDisplayHandle,
549 window_handle: raw_window_handle::RawWindowHandle,
550 ) -> Result<<Self::A as Api>::Surface, InstanceError>;
551 /// `surface_hint` is only used by the GLES backend targeting WebGL2
552 unsafe fn enumerate_adapters(
553 &self,
554 surface_hint: Option<&<Self::A as Api>::Surface>,
555 ) -> Vec<ExposedAdapter<Self::A>>;
556}
557
558pub trait Surface: WasmNotSendSync {
559 type A: Api;
560
561 /// Configure `self` to use `device`.
562 ///
563 /// # Safety
564 ///
565 /// - All GPU work using `self` must have been completed.
566 /// - All [`AcquiredSurfaceTexture`]s must have been destroyed.
567 /// - All [`Api::TextureView`]s derived from the [`AcquiredSurfaceTexture`]s must have been destroyed.
568 /// - The surface `self` must not currently be configured to use any other [`Device`].
569 unsafe fn configure(
570 &self,
571 device: &<Self::A as Api>::Device,
572 config: &SurfaceConfiguration,
573 ) -> Result<(), SurfaceError>;
574
575 /// Unconfigure `self` on `device`.
576 ///
577 /// # Safety
578 ///
579 /// - All GPU work that uses `surface` must have been completed.
580 /// - All [`AcquiredSurfaceTexture`]s must have been destroyed.
581 /// - All [`Api::TextureView`]s derived from the [`AcquiredSurfaceTexture`]s must have been destroyed.
582 /// - The surface `self` must have been configured on `device`.
583 unsafe fn unconfigure(&self, device: &<Self::A as Api>::Device);
584
585 /// Return the next texture to be presented by `self`, for the caller to draw on.
586 ///
587 /// On success, return an [`AcquiredSurfaceTexture`] representing the
588 /// texture into which the caller should draw the image to be displayed on
589 /// `self`.
590 ///
591 /// If `timeout` elapses before `self` has a texture ready to be acquired,
592 /// return `Ok(None)`. If `timeout` is `None`, wait indefinitely, with no
593 /// timeout.
594 ///
595 /// # Using an [`AcquiredSurfaceTexture`]
596 ///
597 /// On success, this function returns an [`AcquiredSurfaceTexture`] whose
598 /// [`texture`] field is a [`SurfaceTexture`] from which the caller can
599 /// [`borrow`] a [`Texture`] to draw on. The [`AcquiredSurfaceTexture`] also
600 /// carries some metadata about that [`SurfaceTexture`].
601 ///
602 /// All calls to [`Queue::submit`] that draw on that [`Texture`] must also
603 /// include the [`SurfaceTexture`] in the `surface_textures` argument.
604 ///
605 /// When you are done drawing on the texture, you can display it on `self`
606 /// by passing the [`SurfaceTexture`] and `self` to [`Queue::present`].
607 ///
608 /// If you do not wish to display the texture, you must pass the
609 /// [`SurfaceTexture`] to [`self.discard_texture`], so that it can be reused
610 /// by future acquisitions.
611 ///
612 /// # Portability
613 ///
614 /// Some backends can't support a timeout when acquiring a texture. On these
615 /// backends, `timeout` is ignored.
616 ///
617 /// # Safety
618 ///
619 /// - The surface `self` must currently be configured on some [`Device`].
620 ///
621 /// - The `fence` argument must be the same [`Fence`] passed to all calls to
622 /// [`Queue::submit`] that used [`Texture`]s acquired from this surface.
623 ///
624 /// - You may only have one texture acquired from `self` at a time. When
625 /// `acquire_texture` returns `Ok(Some(ast))`, you must pass the returned
626 /// [`SurfaceTexture`] `ast.texture` to either [`Queue::present`] or
627 /// [`Surface::discard_texture`] before calling `acquire_texture` again.
628 ///
629 /// [`texture`]: AcquiredSurfaceTexture::texture
630 /// [`SurfaceTexture`]: Api::SurfaceTexture
631 /// [`borrow`]: alloc::borrow::Borrow::borrow
632 /// [`Texture`]: Api::Texture
633 /// [`Fence`]: Api::Fence
634 /// [`self.discard_texture`]: Surface::discard_texture
635 unsafe fn acquire_texture(
636 &self,
637 timeout: Option<core::time::Duration>,
638 fence: &<Self::A as Api>::Fence,
639 ) -> Result<Option<AcquiredSurfaceTexture<Self::A>>, SurfaceError>;
640
641 /// Relinquish an acquired texture without presenting it.
642 ///
643 /// After this call, the texture underlying [`SurfaceTexture`] may be
644 /// returned by subsequent calls to [`self.acquire_texture`].
645 ///
646 /// # Safety
647 ///
648 /// - The surface `self` must currently be configured on some [`Device`].
649 ///
650 /// - `texture` must be a [`SurfaceTexture`] returned by a call to
651 /// [`self.acquire_texture`] that has not yet been passed to
652 /// [`Queue::present`].
653 ///
654 /// [`SurfaceTexture`]: Api::SurfaceTexture
655 /// [`self.acquire_texture`]: Surface::acquire_texture
656 unsafe fn discard_texture(&self, texture: <Self::A as Api>::SurfaceTexture);
657}
658
659pub trait Adapter: WasmNotSendSync {
660 type A: Api;
661
662 unsafe fn open(
663 &self,
664 features: wgt::Features,
665 limits: &wgt::Limits,
666 memory_hints: &wgt::MemoryHints,
667 ) -> Result<OpenDevice<Self::A>, DeviceError>;
668
669 /// Return the set of supported capabilities for a texture format.
670 unsafe fn texture_format_capabilities(
671 &self,
672 format: wgt::TextureFormat,
673 ) -> TextureFormatCapabilities;
674
675 /// Returns the capabilities of working with a specified surface.
676 ///
677 /// `None` means presentation is not supported for it.
678 unsafe fn surface_capabilities(
679 &self,
680 surface: &<Self::A as Api>::Surface,
681 ) -> Option<SurfaceCapabilities>;
682
683 /// Creates a [`PresentationTimestamp`] using the adapter's WSI.
684 ///
685 /// [`PresentationTimestamp`]: wgt::PresentationTimestamp
686 unsafe fn get_presentation_timestamp(&self) -> wgt::PresentationTimestamp;
687}
688
689/// A connection to a GPU and a pool of resources to use with it.
690///
691/// A `wgpu-hal` `Device` represents an open connection to a specific graphics
692/// processor, controlled via the backend [`Device::A`]. A `Device` is mostly
693/// used for creating resources. Each `Device` has an associated [`Queue`] used
694/// for command submission.
695///
696/// On Vulkan a `Device` corresponds to a logical device ([`VkDevice`]). Other
697/// backends don't have an exact analog: for example, [`ID3D12Device`]s and
698/// [`MTLDevice`]s are owned by the backends' [`wgpu_hal::Adapter`]
699/// implementations, and shared by all [`wgpu_hal::Device`]s created from that
700/// `Adapter`.
701///
702/// A `Device`'s life cycle is generally:
703///
704/// 1) Obtain a `Device` and its associated [`Queue`] by calling
705/// [`Adapter::open`].
706///
707/// Alternatively, the backend-specific types that implement [`Adapter`] often
708/// have methods for creating a `wgpu-hal` `Device` from a platform-specific
709/// handle. For example, [`vulkan::Adapter::device_from_raw`] can create a
710/// [`vulkan::Device`] from an [`ash::Device`].
711///
712/// 1) Create resources to use on the device by calling methods like
713/// [`Device::create_texture`] or [`Device::create_shader_module`].
714///
715/// 1) Call [`Device::create_command_encoder`] to obtain a [`CommandEncoder`],
716/// which you can use to build [`CommandBuffer`]s holding commands to be
717/// executed on the GPU.
718///
719/// 1) Call [`Queue::submit`] on the `Device`'s associated [`Queue`] to submit
720/// [`CommandBuffer`]s for execution on the GPU. If needed, call
721/// [`Device::wait`] to wait for them to finish execution.
722///
723/// 1) Free resources with methods like [`Device::destroy_texture`] or
724/// [`Device::destroy_shader_module`].
725///
726/// 1) Drop the device.
727///
728/// [`vkDevice`]: https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VkDevice
729/// [`ID3D12Device`]: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/nn-d3d12-id3d12device
730/// [`MTLDevice`]: https://developer.apple.com/documentation/metal/mtldevice
731/// [`wgpu_hal::Adapter`]: Adapter
732/// [`wgpu_hal::Device`]: Device
733/// [`vulkan::Adapter::device_from_raw`]: vulkan/struct.Adapter.html#method.device_from_raw
734/// [`vulkan::Device`]: vulkan/struct.Device.html
735/// [`ash::Device`]: https://docs.rs/ash/latest/ash/struct.Device.html
736/// [`CommandBuffer`]: Api::CommandBuffer
737///
738/// # Safety
739///
740/// As with other `wgpu-hal` APIs, [validation] is the caller's
741/// responsibility. Here are the general requirements for all `Device`
742/// methods:
743///
744/// - Any resource passed to a `Device` method must have been created by that
745/// `Device`. For example, a [`Texture`] passed to [`Device::destroy_texture`] must
746/// have been created with the `Device` passed as `self`.
747///
748/// - Resources may not be destroyed if they are used by any submitted command
749/// buffers that have not yet finished execution.
750///
751/// [validation]: index.html#validation-is-the-calling-codes-responsibility-not-wgpu-hals
752/// [`Texture`]: Api::Texture
753pub trait Device: WasmNotSendSync {
754 type A: Api;
755
756 /// Creates a new buffer.
757 ///
758 /// The initial usage is `wgt::BufferUses::empty()`.
759 unsafe fn create_buffer(
760 &self,
761 desc: &BufferDescriptor,
762 ) -> Result<<Self::A as Api>::Buffer, DeviceError>;
763
764 /// Free `buffer` and any GPU resources it owns.
765 ///
766 /// Note that backends are allowed to allocate GPU memory for buffers from
767 /// allocation pools, and this call is permitted to simply return `buffer`'s
768 /// storage to that pool, without making it available to other applications.
769 ///
770 /// # Safety
771 ///
772 /// - The given `buffer` must not currently be mapped.
773 unsafe fn destroy_buffer(&self, buffer: <Self::A as Api>::Buffer);
774
775 /// A hook for when a wgpu-core buffer is created from a raw wgpu-hal buffer.
776 unsafe fn add_raw_buffer(&self, buffer: &<Self::A as Api>::Buffer);
777
778 /// Return a pointer to CPU memory mapping the contents of `buffer`.
779 ///
780 /// Buffer mappings are persistent: the buffer may remain mapped on the CPU
781 /// while the GPU reads or writes to it. (Note that `wgpu_core` does not use
782 /// this feature: when a `wgpu_core::Buffer` is unmapped, the underlying
783 /// `wgpu_hal` buffer is also unmapped.)
784 ///
785 /// If this function returns `Ok(mapping)`, then:
786 ///
787 /// - `mapping.ptr` is the CPU address of the start of the mapped memory.
788 ///
789 /// - If `mapping.is_coherent` is `true`, then CPU writes to the mapped
790 /// memory are immediately visible on the GPU, and vice versa.
791 ///
792 /// # Safety
793 ///
794 /// - The given `buffer` must have been created with the [`MAP_READ`] or
795 /// [`MAP_WRITE`] flags set in [`BufferDescriptor::usage`].
796 ///
797 /// - The given `range` must fall within the size of `buffer`.
798 ///
799 /// - The caller must avoid data races between the CPU and the GPU. A data
800 /// race is any pair of accesses to a particular byte, one of which is a
801 /// write, that are not ordered with respect to each other by some sort of
802 /// synchronization operation.
803 ///
804 /// - If this function returns `Ok(mapping)` and `mapping.is_coherent` is
805 /// `false`, then:
806 ///
807 /// - Every CPU write to a mapped byte followed by a GPU read of that byte
808 /// must have at least one call to [`Device::flush_mapped_ranges`]
809 /// covering that byte that occurs between those two accesses.
810 ///
811 /// - Every GPU write to a mapped byte followed by a CPU read of that byte
812 /// must have at least one call to [`Device::invalidate_mapped_ranges`]
813 /// covering that byte that occurs between those two accesses.
814 ///
815 /// Note that the data race rule above requires that all such access pairs
816 /// be ordered, so it is meaningful to talk about what must occur
817 /// "between" them.
818 ///
819 /// - Zero-sized mappings are not allowed.
820 ///
821 /// - The returned [`BufferMapping::ptr`] must not be used after a call to
822 /// [`Device::unmap_buffer`].
823 ///
824 /// [`MAP_READ`]: wgt::BufferUses::MAP_READ
825 /// [`MAP_WRITE`]: wgt::BufferUses::MAP_WRITE
826 unsafe fn map_buffer(
827 &self,
828 buffer: &<Self::A as Api>::Buffer,
829 range: MemoryRange,
830 ) -> Result<BufferMapping, DeviceError>;
831
832 /// Remove the mapping established by the last call to [`Device::map_buffer`].
833 ///
834 /// # Safety
835 ///
836 /// - The given `buffer` must be currently mapped.
837 unsafe fn unmap_buffer(&self, buffer: &<Self::A as Api>::Buffer);
838
839 /// Indicate that CPU writes to mapped buffer memory should be made visible to the GPU.
840 ///
841 /// # Safety
842 ///
843 /// - The given `buffer` must be currently mapped.
844 ///
845 /// - All ranges produced by `ranges` must fall within `buffer`'s size.
846 unsafe fn flush_mapped_ranges<I>(&self, buffer: &<Self::A as Api>::Buffer, ranges: I)
847 where
848 I: Iterator<Item = MemoryRange>;
849
850 /// Indicate that GPU writes to mapped buffer memory should be made visible to the CPU.
851 ///
852 /// # Safety
853 ///
854 /// - The given `buffer` must be currently mapped.
855 ///
856 /// - All ranges produced by `ranges` must fall within `buffer`'s size.
857 unsafe fn invalidate_mapped_ranges<I>(&self, buffer: &<Self::A as Api>::Buffer, ranges: I)
858 where
859 I: Iterator<Item = MemoryRange>;
860
861 /// Creates a new texture.
862 ///
863 /// The initial usage for all subresources is `wgt::TextureUses::UNINITIALIZED`.
864 unsafe fn create_texture(
865 &self,
866 desc: &TextureDescriptor,
867 ) -> Result<<Self::A as Api>::Texture, DeviceError>;
868 unsafe fn destroy_texture(&self, texture: <Self::A as Api>::Texture);
869
870 /// A hook for when a wgpu-core texture is created from a raw wgpu-hal texture.
871 unsafe fn add_raw_texture(&self, texture: &<Self::A as Api>::Texture);
872
873 unsafe fn create_texture_view(
874 &self,
875 texture: &<Self::A as Api>::Texture,
876 desc: &TextureViewDescriptor,
877 ) -> Result<<Self::A as Api>::TextureView, DeviceError>;
878 unsafe fn destroy_texture_view(&self, view: <Self::A as Api>::TextureView);
879 unsafe fn create_sampler(
880 &self,
881 desc: &SamplerDescriptor,
882 ) -> Result<<Self::A as Api>::Sampler, DeviceError>;
883 unsafe fn destroy_sampler(&self, sampler: <Self::A as Api>::Sampler);
884
885 /// Create a fresh [`CommandEncoder`].
886 ///
887 /// The new `CommandEncoder` is in the "closed" state.
888 unsafe fn create_command_encoder(
889 &self,
890 desc: &CommandEncoderDescriptor<<Self::A as Api>::Queue>,
891 ) -> Result<<Self::A as Api>::CommandEncoder, DeviceError>;
892
893 /// Creates a bind group layout.
894 unsafe fn create_bind_group_layout(
895 &self,
896 desc: &BindGroupLayoutDescriptor,
897 ) -> Result<<Self::A as Api>::BindGroupLayout, DeviceError>;
898 unsafe fn destroy_bind_group_layout(&self, bg_layout: <Self::A as Api>::BindGroupLayout);
899 unsafe fn create_pipeline_layout(
900 &self,
901 desc: &PipelineLayoutDescriptor<<Self::A as Api>::BindGroupLayout>,
902 ) -> Result<<Self::A as Api>::PipelineLayout, DeviceError>;
903 unsafe fn destroy_pipeline_layout(&self, pipeline_layout: <Self::A as Api>::PipelineLayout);
904
905 #[allow(clippy::type_complexity)]
906 unsafe fn create_bind_group(
907 &self,
908 desc: &BindGroupDescriptor<
909 <Self::A as Api>::BindGroupLayout,
910 <Self::A as Api>::Buffer,
911 <Self::A as Api>::Sampler,
912 <Self::A as Api>::TextureView,
913 <Self::A as Api>::AccelerationStructure,
914 >,
915 ) -> Result<<Self::A as Api>::BindGroup, DeviceError>;
916 unsafe fn destroy_bind_group(&self, group: <Self::A as Api>::BindGroup);
917
918 unsafe fn create_shader_module(
919 &self,
920 desc: &ShaderModuleDescriptor,
921 shader: ShaderInput,
922 ) -> Result<<Self::A as Api>::ShaderModule, ShaderError>;
923 unsafe fn destroy_shader_module(&self, module: <Self::A as Api>::ShaderModule);
924
925 #[allow(clippy::type_complexity)]
926 unsafe fn create_render_pipeline(
927 &self,
928 desc: &RenderPipelineDescriptor<
929 <Self::A as Api>::PipelineLayout,
930 <Self::A as Api>::ShaderModule,
931 <Self::A as Api>::PipelineCache,
932 >,
933 ) -> Result<<Self::A as Api>::RenderPipeline, PipelineError>;
934 unsafe fn destroy_render_pipeline(&self, pipeline: <Self::A as Api>::RenderPipeline);
935
936 #[allow(clippy::type_complexity)]
937 unsafe fn create_compute_pipeline(
938 &self,
939 desc: &ComputePipelineDescriptor<
940 <Self::A as Api>::PipelineLayout,
941 <Self::A as Api>::ShaderModule,
942 <Self::A as Api>::PipelineCache,
943 >,
944 ) -> Result<<Self::A as Api>::ComputePipeline, PipelineError>;
945 unsafe fn destroy_compute_pipeline(&self, pipeline: <Self::A as Api>::ComputePipeline);
946
947 unsafe fn create_pipeline_cache(
948 &self,
949 desc: &PipelineCacheDescriptor<'_>,
950 ) -> Result<<Self::A as Api>::PipelineCache, PipelineCacheError>;
951 fn pipeline_cache_validation_key(&self) -> Option<[u8; 16]> {
952 None
953 }
954 unsafe fn destroy_pipeline_cache(&self, cache: <Self::A as Api>::PipelineCache);
955
956 unsafe fn create_query_set(
957 &self,
958 desc: &wgt::QuerySetDescriptor<Label>,
959 ) -> Result<<Self::A as Api>::QuerySet, DeviceError>;
960 unsafe fn destroy_query_set(&self, set: <Self::A as Api>::QuerySet);
961 unsafe fn create_fence(&self) -> Result<<Self::A as Api>::Fence, DeviceError>;
962 unsafe fn destroy_fence(&self, fence: <Self::A as Api>::Fence);
963 unsafe fn get_fence_value(
964 &self,
965 fence: &<Self::A as Api>::Fence,
966 ) -> Result<FenceValue, DeviceError>;
967
968 /// Wait for `fence` to reach `value`.
969 ///
970 /// Operations like [`Queue::submit`] can accept a [`Fence`] and a
971 /// [`FenceValue`] to store in it, so you can use this `wait` function
972 /// to wait for a given queue submission to finish execution.
973 ///
974 /// The `value` argument must be a value that some actual operation you have
975 /// already presented to the device is going to store in `fence`. You cannot
976 /// wait for values yet to be submitted. (This restriction accommodates
977 /// implementations like the `vulkan` backend's [`FencePool`] that must
978 /// allocate a distinct synchronization object for each fence value one is
979 /// able to wait for.)
980 ///
981 /// Calling `wait` with a lower [`FenceValue`] than `fence`'s current value
982 /// returns immediately.
983 ///
984 /// Returns `Ok(true)` on success and `Ok(false)` on timeout.
985 ///
986 /// [`Fence`]: Api::Fence
987 /// [`FencePool`]: vulkan/enum.Fence.html#variant.FencePool
988 unsafe fn wait(
989 &self,
990 fence: &<Self::A as Api>::Fence,
991 value: FenceValue,
992 timeout_ms: u32,
993 ) -> Result<bool, DeviceError>;
994
995 /// Start a graphics debugger capture.
996 ///
997 /// # Safety
998 ///
999 /// See [`wgpu::Device::start_graphics_debugger_capture`][api] for more details.
1000 ///
1001 /// [api]: ../wgpu/struct.Device.html#method.start_graphics_debugger_capture
1002 unsafe fn start_graphics_debugger_capture(&self) -> bool;
1003
1004 /// Stop a graphics debugger capture.
1005 ///
1006 /// # Safety
1007 ///
1008 /// See [`wgpu::Device::stop_graphics_debugger_capture`][api] for more details.
1009 ///
1010 /// [api]: ../wgpu/struct.Device.html#method.stop_graphics_debugger_capture
1011 unsafe fn stop_graphics_debugger_capture(&self);
1012
1013 #[allow(unused_variables)]
1014 unsafe fn pipeline_cache_get_data(
1015 &self,
1016 cache: &<Self::A as Api>::PipelineCache,
1017 ) -> Option<Vec<u8>> {
1018 None
1019 }
1020
1021 unsafe fn create_acceleration_structure(
1022 &self,
1023 desc: &AccelerationStructureDescriptor,
1024 ) -> Result<<Self::A as Api>::AccelerationStructure, DeviceError>;
1025 unsafe fn get_acceleration_structure_build_sizes(
1026 &self,
1027 desc: &GetAccelerationStructureBuildSizesDescriptor<<Self::A as Api>::Buffer>,
1028 ) -> AccelerationStructureBuildSizes;
1029 unsafe fn get_acceleration_structure_device_address(
1030 &self,
1031 acceleration_structure: &<Self::A as Api>::AccelerationStructure,
1032 ) -> wgt::BufferAddress;
1033 unsafe fn destroy_acceleration_structure(
1034 &self,
1035 acceleration_structure: <Self::A as Api>::AccelerationStructure,
1036 );
1037 fn tlas_instance_to_bytes(&self, instance: TlasInstance) -> Vec<u8>;
1038
1039 fn get_internal_counters(&self) -> wgt::HalCounters;
1040
1041 fn generate_allocator_report(&self) -> Option<wgt::AllocatorReport> {
1042 None
1043 }
1044
1045 fn check_if_oom(&self) -> Result<(), DeviceError>;
1046}
1047
1048pub trait Queue: WasmNotSendSync {
1049 type A: Api;
1050
1051 /// Submit `command_buffers` for execution on GPU.
1052 ///
1053 /// Update `fence` to `value` when the operation is complete. See
1054 /// [`Fence`] for details.
1055 ///
1056 /// A `wgpu_hal` queue is "single threaded": all command buffers are
1057 /// executed in the order they're submitted, with each buffer able to see
1058 /// previous buffers' results. Specifically:
1059 ///
1060 /// - If two calls to `submit` on a single `Queue` occur in a particular
1061 /// order (that is, they happen on the same thread, or on two threads that
1062 /// have synchronized to establish an ordering), then the first
1063 /// submission's commands all complete execution before any of the second
1064 /// submission's commands begin. All results produced by one submission
1065 /// are visible to the next.
1066 ///
1067 /// - Within a submission, command buffers execute in the order in which they
1068 /// appear in `command_buffers`. All results produced by one buffer are
1069 /// visible to the next.
1070 ///
1071 /// If two calls to `submit` on a single `Queue` from different threads are
1072 /// not synchronized to occur in a particular order, they must pass distinct
1073 /// [`Fence`]s. As explained in the [`Fence`] documentation, waiting for
1074 /// operations to complete is only trustworthy when operations finish in
1075 /// order of increasing fence value, but submissions from different threads
1076 /// cannot determine how to order the fence values if the submissions
1077 /// themselves are unordered. If each thread uses a separate [`Fence`], this
1078 /// problem does not arise.
1079 ///
1080 /// # Safety
1081 ///
1082 /// - Each [`CommandBuffer`][cb] in `command_buffers` must have been created
1083 /// from a [`CommandEncoder`][ce] that was constructed from the
1084 /// [`Device`][d] associated with this [`Queue`].
1085 ///
1086 /// - Each [`CommandBuffer`][cb] must remain alive until the submitted
1087 /// commands have finished execution. Since command buffers must not
1088 /// outlive their encoders, this implies that the encoders must remain
1089 /// alive as well.
1090 ///
1091 /// - All resources used by a submitted [`CommandBuffer`][cb]
1092 /// ([`Texture`][t]s, [`BindGroup`][bg]s, [`RenderPipeline`][rp]s, and so
1093 /// on) must remain alive until the command buffer finishes execution.
1094 ///
1095 /// - Every [`SurfaceTexture`][st] that any command in `command_buffers`
1096 /// writes to must appear in the `surface_textures` argument.
1097 ///
1098 /// - No [`SurfaceTexture`][st] may appear in the `surface_textures`
1099 /// argument more than once.
1100 ///
1101 /// - Each [`SurfaceTexture`][st] in `surface_textures` must be configured
1102 /// for use with the [`Device`][d] associated with this [`Queue`],
1103 /// typically by calling [`Surface::configure`].
1104 ///
1105 /// - All calls to this function that include a given [`SurfaceTexture`][st]
1106 /// in `surface_textures` must use the same [`Fence`].
1107 ///
1108 /// - The [`Fence`] passed as `signal_fence.0` must remain alive until
1109 /// all submissions that will signal it have completed.
1110 ///
1111 /// [`Fence`]: Api::Fence
1112 /// [cb]: Api::CommandBuffer
1113 /// [ce]: Api::CommandEncoder
1114 /// [d]: Api::Device
1115 /// [t]: Api::Texture
1116 /// [bg]: Api::BindGroup
1117 /// [rp]: Api::RenderPipeline
1118 /// [st]: Api::SurfaceTexture
1119 unsafe fn submit(
1120 &self,
1121 command_buffers: &[&<Self::A as Api>::CommandBuffer],
1122 surface_textures: &[&<Self::A as Api>::SurfaceTexture],
1123 signal_fence: (&mut <Self::A as Api>::Fence, FenceValue),
1124 ) -> Result<(), DeviceError>;
1125 unsafe fn present(
1126 &self,
1127 surface: &<Self::A as Api>::Surface,
1128 texture: <Self::A as Api>::SurfaceTexture,
1129 ) -> Result<(), SurfaceError>;
1130 unsafe fn get_timestamp_period(&self) -> f32;
1131}
1132
1133/// Encoder and allocation pool for `CommandBuffer`s.
1134///
1135/// A `CommandEncoder` not only constructs `CommandBuffer`s but also
1136/// acts as the allocation pool that owns the buffers' underlying
1137/// storage. Thus, `CommandBuffer`s must not outlive the
1138/// `CommandEncoder` that created them.
1139///
1140/// The life cycle of a `CommandBuffer` is as follows:
1141///
1142/// - Call [`Device::create_command_encoder`] to create a new
1143/// `CommandEncoder`, in the "closed" state.
1144///
1145/// - Call `begin_encoding` on a closed `CommandEncoder` to begin
1146/// recording commands. This puts the `CommandEncoder` in the
1147/// "recording" state.
1148///
1149/// - Call methods like `copy_buffer_to_buffer`, `begin_render_pass`,
1150/// etc. on a "recording" `CommandEncoder` to add commands to the
1151/// list. (If an error occurs, you must call `discard_encoding`; see
1152/// below.)
1153///
1154/// - Call `end_encoding` on a recording `CommandEncoder` to close the
1155/// encoder and construct a fresh `CommandBuffer` consisting of the
1156/// list of commands recorded up to that point.
1157///
1158/// - Call `discard_encoding` on a recording `CommandEncoder` to drop
1159/// the commands recorded thus far and close the encoder. This is
1160/// the only safe thing to do on a `CommandEncoder` if an error has
1161/// occurred while recording commands.
1162///
1163/// - Call `reset_all` on a closed `CommandEncoder`, passing all the
1164/// live `CommandBuffers` built from it. All the `CommandBuffer`s
1165/// are destroyed, and their resources are freed.
1166///
1167/// # Safety
1168///
1169/// - The `CommandEncoder` must be in the states described above to
1170/// make the given calls.
1171///
1172/// - A `CommandBuffer` that has been submitted for execution on the
1173/// GPU must live until its execution is complete.
1174///
1175/// - A `CommandBuffer` must not outlive the `CommandEncoder` that
1176/// built it.
1177///
1178/// It is the user's responsibility to meet this requirements. This
1179/// allows `CommandEncoder` implementations to keep their state
1180/// tracking to a minimum.
1181pub trait CommandEncoder: WasmNotSendSync + fmt::Debug {
1182 type A: Api;
1183
1184 /// Begin encoding a new command buffer.
1185 ///
1186 /// This puts this `CommandEncoder` in the "recording" state.
1187 ///
1188 /// # Safety
1189 ///
1190 /// This `CommandEncoder` must be in the "closed" state.
1191 unsafe fn begin_encoding(&mut self, label: Label) -> Result<(), DeviceError>;
1192
1193 /// Discard the command list under construction.
1194 ///
1195 /// If an error has occurred while recording commands, this
1196 /// is the only safe thing to do with the encoder.
1197 ///
1198 /// This puts this `CommandEncoder` in the "closed" state.
1199 ///
1200 /// # Safety
1201 ///
1202 /// This `CommandEncoder` must be in the "recording" state.
1203 ///
1204 /// Callers must not assume that implementations of this
1205 /// function are idempotent, and thus should not call it
1206 /// multiple times in a row.
1207 unsafe fn discard_encoding(&mut self);
1208
1209 /// Return a fresh [`CommandBuffer`] holding the recorded commands.
1210 ///
1211 /// The returned [`CommandBuffer`] holds all the commands recorded
1212 /// on this `CommandEncoder` since the last call to
1213 /// [`begin_encoding`].
1214 ///
1215 /// This puts this `CommandEncoder` in the "closed" state.
1216 ///
1217 /// # Safety
1218 ///
1219 /// This `CommandEncoder` must be in the "recording" state.
1220 ///
1221 /// The returned [`CommandBuffer`] must not outlive this
1222 /// `CommandEncoder`. Implementations are allowed to build
1223 /// `CommandBuffer`s that depend on storage owned by this
1224 /// `CommandEncoder`.
1225 ///
1226 /// [`CommandBuffer`]: Api::CommandBuffer
1227 /// [`begin_encoding`]: CommandEncoder::begin_encoding
1228 unsafe fn end_encoding(&mut self) -> Result<<Self::A as Api>::CommandBuffer, DeviceError>;
1229
1230 /// Reclaim all resources belonging to this `CommandEncoder`.
1231 ///
1232 /// # Safety
1233 ///
1234 /// This `CommandEncoder` must be in the "closed" state.
1235 ///
1236 /// The `command_buffers` iterator must produce all the live
1237 /// [`CommandBuffer`]s built using this `CommandEncoder` --- that
1238 /// is, every extant `CommandBuffer` returned from `end_encoding`.
1239 ///
1240 /// [`CommandBuffer`]: Api::CommandBuffer
1241 unsafe fn reset_all<I>(&mut self, command_buffers: I)
1242 where
1243 I: Iterator<Item = <Self::A as Api>::CommandBuffer>;
1244
1245 unsafe fn transition_buffers<'a, T>(&mut self, barriers: T)
1246 where
1247 T: Iterator<Item = BufferBarrier<'a, <Self::A as Api>::Buffer>>;
1248
1249 unsafe fn transition_textures<'a, T>(&mut self, barriers: T)
1250 where
1251 T: Iterator<Item = TextureBarrier<'a, <Self::A as Api>::Texture>>;
1252
1253 // copy operations
1254
1255 unsafe fn clear_buffer(&mut self, buffer: &<Self::A as Api>::Buffer, range: MemoryRange);
1256
1257 unsafe fn copy_buffer_to_buffer<T>(
1258 &mut self,
1259 src: &<Self::A as Api>::Buffer,
1260 dst: &<Self::A as Api>::Buffer,
1261 regions: T,
1262 ) where
1263 T: Iterator<Item = BufferCopy>;
1264
1265 /// Copy from an external image to an internal texture.
1266 /// Works with a single array layer.
1267 /// Note: `dst` current usage has to be `wgt::TextureUses::COPY_DST`.
1268 /// Note: the copy extent is in physical size (rounded to the block size)
1269 #[cfg(webgl)]
1270 unsafe fn copy_external_image_to_texture<T>(
1271 &mut self,
1272 src: &wgt::CopyExternalImageSourceInfo,
1273 dst: &<Self::A as Api>::Texture,
1274 dst_premultiplication: bool,
1275 regions: T,
1276 ) where
1277 T: Iterator<Item = TextureCopy>;
1278
1279 /// Copy from one texture to another.
1280 /// Works with a single array layer.
1281 /// Note: `dst` current usage has to be `wgt::TextureUses::COPY_DST`.
1282 /// Note: the copy extent is in physical size (rounded to the block size)
1283 unsafe fn copy_texture_to_texture<T>(
1284 &mut self,
1285 src: &<Self::A as Api>::Texture,
1286 src_usage: wgt::TextureUses,
1287 dst: &<Self::A as Api>::Texture,
1288 regions: T,
1289 ) where
1290 T: Iterator<Item = TextureCopy>;
1291
1292 /// Copy from buffer to texture.
1293 /// Works with a single array layer.
1294 /// Note: `dst` current usage has to be `wgt::TextureUses::COPY_DST`.
1295 /// Note: the copy extent is in physical size (rounded to the block size)
1296 unsafe fn copy_buffer_to_texture<T>(
1297 &mut self,
1298 src: &<Self::A as Api>::Buffer,
1299 dst: &<Self::A as Api>::Texture,
1300 regions: T,
1301 ) where
1302 T: Iterator<Item = BufferTextureCopy>;
1303
1304 /// Copy from texture to buffer.
1305 /// Works with a single array layer.
1306 /// Note: the copy extent is in physical size (rounded to the block size)
1307 unsafe fn copy_texture_to_buffer<T>(
1308 &mut self,
1309 src: &<Self::A as Api>::Texture,
1310 src_usage: wgt::TextureUses,
1311 dst: &<Self::A as Api>::Buffer,
1312 regions: T,
1313 ) where
1314 T: Iterator<Item = BufferTextureCopy>;
1315
1316 unsafe fn copy_acceleration_structure_to_acceleration_structure(
1317 &mut self,
1318 src: &<Self::A as Api>::AccelerationStructure,
1319 dst: &<Self::A as Api>::AccelerationStructure,
1320 copy: wgt::AccelerationStructureCopy,
1321 );
1322 // pass common
1323
1324 /// Sets the bind group at `index` to `group`.
1325 ///
1326 /// If this is not the first call to `set_bind_group` within the current
1327 /// render or compute pass:
1328 ///
1329 /// - If `layout` contains `n` bind group layouts, then any previously set
1330 /// bind groups at indices `n` or higher are cleared.
1331 ///
1332 /// - If the first `m` bind group layouts of `layout` are equal to those of
1333 /// the previously passed layout, but no more, then any previously set
1334 /// bind groups at indices `m` or higher are cleared.
1335 ///
1336 /// It follows from the above that passing the same layout as before doesn't
1337 /// clear any bind groups.
1338 ///
1339 /// # Safety
1340 ///
1341 /// - This [`CommandEncoder`] must be within a render or compute pass.
1342 ///
1343 /// - `index` must be the valid index of some bind group layout in `layout`.
1344 /// Call this the "relevant bind group layout".
1345 ///
1346 /// - The layout of `group` must be equal to the relevant bind group layout.
1347 ///
1348 /// - The length of `dynamic_offsets` must match the number of buffer
1349 /// bindings [with dynamic offsets][hdo] in the relevant bind group
1350 /// layout.
1351 ///
1352 /// - If those buffer bindings are ordered by increasing [`binding` number]
1353 /// and paired with elements from `dynamic_offsets`, then each offset must
1354 /// be a valid offset for the binding's corresponding buffer in `group`.
1355 ///
1356 /// [hdo]: wgt::BindingType::Buffer::has_dynamic_offset
1357 /// [`binding` number]: wgt::BindGroupLayoutEntry::binding
1358 unsafe fn set_bind_group(
1359 &mut self,
1360 layout: &<Self::A as Api>::PipelineLayout,
1361 index: u32,
1362 group: &<Self::A as Api>::BindGroup,
1363 dynamic_offsets: &[wgt::DynamicOffset],
1364 );
1365
1366 /// Sets a range in push constant data.
1367 ///
1368 /// IMPORTANT: while the data is passed as words, the offset is in bytes!
1369 ///
1370 /// # Safety
1371 ///
1372 /// - `offset_bytes` must be a multiple of 4.
1373 /// - The range of push constants written must be valid for the pipeline layout at draw time.
1374 unsafe fn set_push_constants(
1375 &mut self,
1376 layout: &<Self::A as Api>::PipelineLayout,
1377 stages: wgt::ShaderStages,
1378 offset_bytes: u32,
1379 data: &[u32],
1380 );
1381
1382 unsafe fn insert_debug_marker(&mut self, label: &str);
1383 unsafe fn begin_debug_marker(&mut self, group_label: &str);
1384 unsafe fn end_debug_marker(&mut self);
1385
1386 // queries
1387
1388 /// # Safety:
1389 ///
1390 /// - If `set` is an occlusion query set, it must be the same one as used in the [`RenderPassDescriptor::occlusion_query_set`] parameter.
1391 unsafe fn begin_query(&mut self, set: &<Self::A as Api>::QuerySet, index: u32);
1392 /// # Safety:
1393 ///
1394 /// - If `set` is an occlusion query set, it must be the same one as used in the [`RenderPassDescriptor::occlusion_query_set`] parameter.
1395 unsafe fn end_query(&mut self, set: &<Self::A as Api>::QuerySet, index: u32);
1396 unsafe fn write_timestamp(&mut self, set: &<Self::A as Api>::QuerySet, index: u32);
1397 unsafe fn reset_queries(&mut self, set: &<Self::A as Api>::QuerySet, range: Range<u32>);
1398 unsafe fn copy_query_results(
1399 &mut self,
1400 set: &<Self::A as Api>::QuerySet,
1401 range: Range<u32>,
1402 buffer: &<Self::A as Api>::Buffer,
1403 offset: wgt::BufferAddress,
1404 stride: wgt::BufferSize,
1405 );
1406
1407 // render passes
1408
1409 /// Begin a new render pass, clearing all active bindings.
1410 ///
1411 /// This clears any bindings established by the following calls:
1412 ///
1413 /// - [`set_bind_group`](CommandEncoder::set_bind_group)
1414 /// - [`set_push_constants`](CommandEncoder::set_push_constants)
1415 /// - [`begin_query`](CommandEncoder::begin_query)
1416 /// - [`set_render_pipeline`](CommandEncoder::set_render_pipeline)
1417 /// - [`set_index_buffer`](CommandEncoder::set_index_buffer)
1418 /// - [`set_vertex_buffer`](CommandEncoder::set_vertex_buffer)
1419 ///
1420 /// # Safety
1421 ///
1422 /// - All prior calls to [`begin_render_pass`] on this [`CommandEncoder`] must have been followed
1423 /// by a call to [`end_render_pass`].
1424 ///
1425 /// - All prior calls to [`begin_compute_pass`] on this [`CommandEncoder`] must have been followed
1426 /// by a call to [`end_compute_pass`].
1427 ///
1428 /// [`begin_render_pass`]: CommandEncoder::begin_render_pass
1429 /// [`begin_compute_pass`]: CommandEncoder::begin_compute_pass
1430 /// [`end_render_pass`]: CommandEncoder::end_render_pass
1431 /// [`end_compute_pass`]: CommandEncoder::end_compute_pass
1432 unsafe fn begin_render_pass(
1433 &mut self,
1434 desc: &RenderPassDescriptor<<Self::A as Api>::QuerySet, <Self::A as Api>::TextureView>,
1435 ) -> Result<(), DeviceError>;
1436
1437 /// End the current render pass.
1438 ///
1439 /// # Safety
1440 ///
1441 /// - There must have been a prior call to [`begin_render_pass`] on this [`CommandEncoder`]
1442 /// that has not been followed by a call to [`end_render_pass`].
1443 ///
1444 /// [`begin_render_pass`]: CommandEncoder::begin_render_pass
1445 /// [`end_render_pass`]: CommandEncoder::end_render_pass
1446 unsafe fn end_render_pass(&mut self);
1447
1448 unsafe fn set_render_pipeline(&mut self, pipeline: &<Self::A as Api>::RenderPipeline);
1449
1450 unsafe fn set_index_buffer<'a>(
1451 &mut self,
1452 binding: BufferBinding<'a, <Self::A as Api>::Buffer>,
1453 format: wgt::IndexFormat,
1454 );
1455 unsafe fn set_vertex_buffer<'a>(
1456 &mut self,
1457 index: u32,
1458 binding: BufferBinding<'a, <Self::A as Api>::Buffer>,
1459 );
1460 unsafe fn set_viewport(&mut self, rect: &Rect<f32>, depth_range: Range<f32>);
1461 unsafe fn set_scissor_rect(&mut self, rect: &Rect<u32>);
1462 unsafe fn set_stencil_reference(&mut self, value: u32);
1463 unsafe fn set_blend_constants(&mut self, color: &[f32; 4]);
1464
1465 unsafe fn draw(
1466 &mut self,
1467 first_vertex: u32,
1468 vertex_count: u32,
1469 first_instance: u32,
1470 instance_count: u32,
1471 );
1472 unsafe fn draw_indexed(
1473 &mut self,
1474 first_index: u32,
1475 index_count: u32,
1476 base_vertex: i32,
1477 first_instance: u32,
1478 instance_count: u32,
1479 );
1480 unsafe fn draw_indirect(
1481 &mut self,
1482 buffer: &<Self::A as Api>::Buffer,
1483 offset: wgt::BufferAddress,
1484 draw_count: u32,
1485 );
1486 unsafe fn draw_indexed_indirect(
1487 &mut self,
1488 buffer: &<Self::A as Api>::Buffer,
1489 offset: wgt::BufferAddress,
1490 draw_count: u32,
1491 );
1492 unsafe fn draw_indirect_count(
1493 &mut self,
1494 buffer: &<Self::A as Api>::Buffer,
1495 offset: wgt::BufferAddress,
1496 count_buffer: &<Self::A as Api>::Buffer,
1497 count_offset: wgt::BufferAddress,
1498 max_count: u32,
1499 );
1500 unsafe fn draw_indexed_indirect_count(
1501 &mut self,
1502 buffer: &<Self::A as Api>::Buffer,
1503 offset: wgt::BufferAddress,
1504 count_buffer: &<Self::A as Api>::Buffer,
1505 count_offset: wgt::BufferAddress,
1506 max_count: u32,
1507 );
1508 unsafe fn draw_mesh_tasks(
1509 &mut self,
1510 group_count_x: u32,
1511 group_count_y: u32,
1512 group_count_z: u32,
1513 );
1514 unsafe fn draw_mesh_tasks_indirect(
1515 &mut self,
1516 buffer: &<Self::A as Api>::Buffer,
1517 offset: wgt::BufferAddress,
1518 draw_count: u32,
1519 );
1520 unsafe fn draw_mesh_tasks_indirect_count(
1521 &mut self,
1522 buffer: &<Self::A as Api>::Buffer,
1523 offset: wgt::BufferAddress,
1524 count_buffer: &<Self::A as Api>::Buffer,
1525 count_offset: wgt::BufferAddress,
1526 max_count: u32,
1527 );
1528
1529 // compute passes
1530
1531 /// Begin a new compute pass, clearing all active bindings.
1532 ///
1533 /// This clears any bindings established by the following calls:
1534 ///
1535 /// - [`set_bind_group`](CommandEncoder::set_bind_group)
1536 /// - [`set_push_constants`](CommandEncoder::set_push_constants)
1537 /// - [`begin_query`](CommandEncoder::begin_query)
1538 /// - [`set_compute_pipeline`](CommandEncoder::set_compute_pipeline)
1539 ///
1540 /// # Safety
1541 ///
1542 /// - All prior calls to [`begin_render_pass`] on this [`CommandEncoder`] must have been followed
1543 /// by a call to [`end_render_pass`].
1544 ///
1545 /// - All prior calls to [`begin_compute_pass`] on this [`CommandEncoder`] must have been followed
1546 /// by a call to [`end_compute_pass`].
1547 ///
1548 /// [`begin_render_pass`]: CommandEncoder::begin_render_pass
1549 /// [`begin_compute_pass`]: CommandEncoder::begin_compute_pass
1550 /// [`end_render_pass`]: CommandEncoder::end_render_pass
1551 /// [`end_compute_pass`]: CommandEncoder::end_compute_pass
1552 unsafe fn begin_compute_pass(
1553 &mut self,
1554 desc: &ComputePassDescriptor<<Self::A as Api>::QuerySet>,
1555 );
1556
1557 /// End the current compute pass.
1558 ///
1559 /// # Safety
1560 ///
1561 /// - There must have been a prior call to [`begin_compute_pass`] on this [`CommandEncoder`]
1562 /// that has not been followed by a call to [`end_compute_pass`].
1563 ///
1564 /// [`begin_compute_pass`]: CommandEncoder::begin_compute_pass
1565 /// [`end_compute_pass`]: CommandEncoder::end_compute_pass
1566 unsafe fn end_compute_pass(&mut self);
1567
1568 unsafe fn set_compute_pipeline(&mut self, pipeline: &<Self::A as Api>::ComputePipeline);
1569
1570 unsafe fn dispatch(&mut self, count: [u32; 3]);
1571 unsafe fn dispatch_indirect(
1572 &mut self,
1573 buffer: &<Self::A as Api>::Buffer,
1574 offset: wgt::BufferAddress,
1575 );
1576
1577 /// To get the required sizes for the buffer allocations use `get_acceleration_structure_build_sizes` per descriptor
1578 /// All buffers must be synchronized externally
1579 /// All buffer regions, which are written to may only be passed once per function call,
1580 /// with the exception of updates in the same descriptor.
1581 /// Consequences of this limitation:
1582 /// - scratch buffers need to be unique
1583 /// - a tlas can't be build in the same call with a blas it contains
1584 unsafe fn build_acceleration_structures<'a, T>(
1585 &mut self,
1586 descriptor_count: u32,
1587 descriptors: T,
1588 ) where
1589 Self::A: 'a,
1590 T: IntoIterator<
1591 Item = BuildAccelerationStructureDescriptor<
1592 'a,
1593 <Self::A as Api>::Buffer,
1594 <Self::A as Api>::AccelerationStructure,
1595 >,
1596 >;
1597
1598 unsafe fn place_acceleration_structure_barrier(
1599 &mut self,
1600 barrier: AccelerationStructureBarrier,
1601 );
1602 // modeled off dx12, because this is able to be polyfilled in vulkan as opposed to the other way round
1603 unsafe fn read_acceleration_structure_compact_size(
1604 &mut self,
1605 acceleration_structure: &<Self::A as Api>::AccelerationStructure,
1606 buf: &<Self::A as Api>::Buffer,
1607 );
1608}
1609
1610bitflags!(
1611 /// Pipeline layout creation flags.
1612 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1613 pub struct PipelineLayoutFlags: u32 {
1614 /// D3D12: Add support for `first_vertex` and `first_instance` builtins
1615 /// via push constants for direct execution.
1616 const FIRST_VERTEX_INSTANCE = 1 << 0;
1617 /// D3D12: Add support for `num_workgroups` builtins via push constants
1618 /// for direct execution.
1619 const NUM_WORK_GROUPS = 1 << 1;
1620 /// D3D12: Add support for the builtins that the other flags enable for
1621 /// indirect execution.
1622 const INDIRECT_BUILTIN_UPDATE = 1 << 2;
1623 }
1624);
1625
1626bitflags!(
1627 /// Pipeline layout creation flags.
1628 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1629 pub struct BindGroupLayoutFlags: u32 {
1630 /// Allows for bind group binding arrays to be shorter than the array in the BGL.
1631 const PARTIALLY_BOUND = 1 << 0;
1632 }
1633);
1634
1635bitflags!(
1636 /// Texture format capability flags.
1637 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1638 pub struct TextureFormatCapabilities: u32 {
1639 /// Format can be sampled.
1640 const SAMPLED = 1 << 0;
1641 /// Format can be sampled with a linear sampler.
1642 const SAMPLED_LINEAR = 1 << 1;
1643 /// Format can be sampled with a min/max reduction sampler.
1644 const SAMPLED_MINMAX = 1 << 2;
1645
1646 /// Format can be used as storage with read-only access.
1647 const STORAGE_READ_ONLY = 1 << 3;
1648 /// Format can be used as storage with write-only access.
1649 const STORAGE_WRITE_ONLY = 1 << 4;
1650 /// Format can be used as storage with both read and write access.
1651 const STORAGE_READ_WRITE = 1 << 5;
1652 /// Format can be used as storage with atomics.
1653 const STORAGE_ATOMIC = 1 << 6;
1654
1655 /// Format can be used as color and input attachment.
1656 const COLOR_ATTACHMENT = 1 << 7;
1657 /// Format can be used as color (with blending) and input attachment.
1658 const COLOR_ATTACHMENT_BLEND = 1 << 8;
1659 /// Format can be used as depth-stencil and input attachment.
1660 const DEPTH_STENCIL_ATTACHMENT = 1 << 9;
1661
1662 /// Format can be multisampled by x2.
1663 const MULTISAMPLE_X2 = 1 << 10;
1664 /// Format can be multisampled by x4.
1665 const MULTISAMPLE_X4 = 1 << 11;
1666 /// Format can be multisampled by x8.
1667 const MULTISAMPLE_X8 = 1 << 12;
1668 /// Format can be multisampled by x16.
1669 const MULTISAMPLE_X16 = 1 << 13;
1670
1671 /// Format can be used for render pass resolve targets.
1672 const MULTISAMPLE_RESOLVE = 1 << 14;
1673
1674 /// Format can be copied from.
1675 const COPY_SRC = 1 << 15;
1676 /// Format can be copied to.
1677 const COPY_DST = 1 << 16;
1678 }
1679);
1680
1681bitflags!(
1682 /// Texture format capability flags.
1683 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1684 pub struct FormatAspects: u8 {
1685 const COLOR = 1 << 0;
1686 const DEPTH = 1 << 1;
1687 const STENCIL = 1 << 2;
1688 const PLANE_0 = 1 << 3;
1689 const PLANE_1 = 1 << 4;
1690 const PLANE_2 = 1 << 5;
1691
1692 const DEPTH_STENCIL = Self::DEPTH.bits() | Self::STENCIL.bits();
1693 }
1694);
1695
1696impl FormatAspects {
1697 pub fn new(format: wgt::TextureFormat, aspect: wgt::TextureAspect) -> Self {
1698 let aspect_mask = match aspect {
1699 wgt::TextureAspect::All => Self::all(),
1700 wgt::TextureAspect::DepthOnly => Self::DEPTH,
1701 wgt::TextureAspect::StencilOnly => Self::STENCIL,
1702 wgt::TextureAspect::Plane0 => Self::PLANE_0,
1703 wgt::TextureAspect::Plane1 => Self::PLANE_1,
1704 wgt::TextureAspect::Plane2 => Self::PLANE_2,
1705 };
1706 Self::from(format) & aspect_mask
1707 }
1708
1709 /// Returns `true` if only one flag is set
1710 pub fn is_one(&self) -> bool {
1711 self.bits().is_power_of_two()
1712 }
1713
1714 pub fn map(&self) -> wgt::TextureAspect {
1715 match *self {
1716 Self::COLOR => wgt::TextureAspect::All,
1717 Self::DEPTH => wgt::TextureAspect::DepthOnly,
1718 Self::STENCIL => wgt::TextureAspect::StencilOnly,
1719 Self::PLANE_0 => wgt::TextureAspect::Plane0,
1720 Self::PLANE_1 => wgt::TextureAspect::Plane1,
1721 Self::PLANE_2 => wgt::TextureAspect::Plane2,
1722 _ => unreachable!(),
1723 }
1724 }
1725}
1726
1727impl From<wgt::TextureFormat> for FormatAspects {
1728 fn from(format: wgt::TextureFormat) -> Self {
1729 match format {
1730 wgt::TextureFormat::Stencil8 => Self::STENCIL,
1731 wgt::TextureFormat::Depth16Unorm
1732 | wgt::TextureFormat::Depth32Float
1733 | wgt::TextureFormat::Depth24Plus => Self::DEPTH,
1734 wgt::TextureFormat::Depth32FloatStencil8 | wgt::TextureFormat::Depth24PlusStencil8 => {
1735 Self::DEPTH_STENCIL
1736 }
1737 wgt::TextureFormat::NV12 => Self::PLANE_0 | Self::PLANE_1,
1738 _ => Self::COLOR,
1739 }
1740 }
1741}
1742
1743bitflags!(
1744 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1745 pub struct MemoryFlags: u32 {
1746 const TRANSIENT = 1 << 0;
1747 const PREFER_COHERENT = 1 << 1;
1748 }
1749);
1750
1751//TODO: it's not intuitive for the backends to consider `LOAD` being optional.
1752
1753bitflags!(
1754 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1755 pub struct AttachmentOps: u8 {
1756 const LOAD = 1 << 0;
1757 const STORE = 1 << 1;
1758 }
1759);
1760
1761#[derive(Clone, Debug)]
1762pub struct InstanceDescriptor<'a> {
1763 pub name: &'a str,
1764 pub flags: wgt::InstanceFlags,
1765 pub memory_budget_thresholds: wgt::MemoryBudgetThresholds,
1766 pub backend_options: wgt::BackendOptions,
1767}
1768
1769#[derive(Clone, Debug)]
1770pub struct Alignments {
1771 /// The alignment of the start of the buffer used as a GPU copy source.
1772 pub buffer_copy_offset: wgt::BufferSize,
1773
1774 /// The alignment of the row pitch of the texture data stored in a buffer that is
1775 /// used in a GPU copy operation.
1776 pub buffer_copy_pitch: wgt::BufferSize,
1777
1778 /// The finest alignment of bound range checking for uniform buffers.
1779 ///
1780 /// When `wgpu_hal` restricts shader references to the [accessible
1781 /// region][ar] of a [`Uniform`] buffer, the size of the accessible region
1782 /// is the bind group binding's stated [size], rounded up to the next
1783 /// multiple of this value.
1784 ///
1785 /// We don't need an analogous field for storage buffer bindings, because
1786 /// all our backends promise to enforce the size at least to a four-byte
1787 /// alignment, and `wgpu_hal` requires bound range lengths to be a multiple
1788 /// of four anyway.
1789 ///
1790 /// [ar]: struct.BufferBinding.html#accessible-region
1791 /// [`Uniform`]: wgt::BufferBindingType::Uniform
1792 /// [size]: BufferBinding::size
1793 pub uniform_bounds_check_alignment: wgt::BufferSize,
1794
1795 /// The size of the raw TLAS instance
1796 pub raw_tlas_instance_size: usize,
1797
1798 /// What the scratch buffer for building an acceleration structure must be aligned to
1799 pub ray_tracing_scratch_buffer_alignment: u32,
1800}
1801
1802#[derive(Clone, Debug)]
1803pub struct Capabilities {
1804 pub limits: wgt::Limits,
1805 pub alignments: Alignments,
1806 pub downlevel: wgt::DownlevelCapabilities,
1807}
1808
1809/// An adapter with all the information needed to reason about its capabilities.
1810///
1811/// These are either made by [`Instance::enumerate_adapters`] or by backend specific
1812/// methods on the backend [`Instance`] or [`Adapter`].
1813#[derive(Debug)]
1814pub struct ExposedAdapter<A: Api> {
1815 pub adapter: A::Adapter,
1816 pub info: wgt::AdapterInfo,
1817 pub features: wgt::Features,
1818 pub capabilities: Capabilities,
1819}
1820
1821/// Describes information about what a `Surface`'s presentation capabilities are.
1822/// Fetch this with [Adapter::surface_capabilities].
1823#[derive(Debug, Clone)]
1824pub struct SurfaceCapabilities {
1825 /// List of supported texture formats.
1826 ///
1827 /// Must be at least one.
1828 pub formats: Vec<wgt::TextureFormat>,
1829
1830 /// Range for the number of queued frames.
1831 ///
1832 /// This adjusts either the swapchain frame count to value + 1 - or sets SetMaximumFrameLatency to the value given,
1833 /// 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.
1834 ///
1835 /// - `maximum_frame_latency.start` must be at least 1.
1836 /// - `maximum_frame_latency.end` must be larger or equal to `maximum_frame_latency.start`.
1837 pub maximum_frame_latency: RangeInclusive<u32>,
1838
1839 /// Current extent of the surface, if known.
1840 pub current_extent: Option<wgt::Extent3d>,
1841
1842 /// Supported texture usage flags.
1843 ///
1844 /// Must have at least `wgt::TextureUses::COLOR_TARGET`
1845 pub usage: wgt::TextureUses,
1846
1847 /// List of supported V-sync modes.
1848 ///
1849 /// Must be at least one.
1850 pub present_modes: Vec<wgt::PresentMode>,
1851
1852 /// List of supported alpha composition modes.
1853 ///
1854 /// Must be at least one.
1855 pub composite_alpha_modes: Vec<wgt::CompositeAlphaMode>,
1856}
1857
1858#[derive(Debug)]
1859pub struct AcquiredSurfaceTexture<A: Api> {
1860 pub texture: A::SurfaceTexture,
1861 /// The presentation configuration no longer matches
1862 /// the surface properties exactly, but can still be used to present
1863 /// to the surface successfully.
1864 pub suboptimal: bool,
1865}
1866
1867/// An open connection to a device and a queue.
1868///
1869/// This can be created from [`Adapter::open`] or backend
1870/// specific methods on the backend's [`Instance`] or [`Adapter`].
1871#[derive(Debug)]
1872pub struct OpenDevice<A: Api> {
1873 pub device: A::Device,
1874 pub queue: A::Queue,
1875}
1876
1877#[derive(Clone, Debug)]
1878pub struct BufferMapping {
1879 pub ptr: NonNull<u8>,
1880 pub is_coherent: bool,
1881}
1882
1883#[derive(Clone, Debug)]
1884pub struct BufferDescriptor<'a> {
1885 pub label: Label<'a>,
1886 pub size: wgt::BufferAddress,
1887 pub usage: wgt::BufferUses,
1888 pub memory_flags: MemoryFlags,
1889}
1890
1891#[derive(Clone, Debug)]
1892pub struct TextureDescriptor<'a> {
1893 pub label: Label<'a>,
1894 pub size: wgt::Extent3d,
1895 pub mip_level_count: u32,
1896 pub sample_count: u32,
1897 pub dimension: wgt::TextureDimension,
1898 pub format: wgt::TextureFormat,
1899 pub usage: wgt::TextureUses,
1900 pub memory_flags: MemoryFlags,
1901 /// Allows views of this texture to have a different format
1902 /// than the texture does.
1903 pub view_formats: Vec<wgt::TextureFormat>,
1904}
1905
1906impl TextureDescriptor<'_> {
1907 pub fn copy_extent(&self) -> CopyExtent {
1908 CopyExtent::map_extent_to_copy_size(&self.size, self.dimension)
1909 }
1910
1911 pub fn is_cube_compatible(&self) -> bool {
1912 self.dimension == wgt::TextureDimension::D2
1913 && self.size.depth_or_array_layers % 6 == 0
1914 && self.sample_count == 1
1915 && self.size.width == self.size.height
1916 }
1917
1918 pub fn array_layer_count(&self) -> u32 {
1919 match self.dimension {
1920 wgt::TextureDimension::D1 | wgt::TextureDimension::D3 => 1,
1921 wgt::TextureDimension::D2 => self.size.depth_or_array_layers,
1922 }
1923 }
1924}
1925
1926/// TextureView descriptor.
1927///
1928/// Valid usage:
1929///. - `format` has to be the same as `TextureDescriptor::format`
1930///. - `dimension` has to be compatible with `TextureDescriptor::dimension`
1931///. - `usage` has to be a subset of `TextureDescriptor::usage`
1932///. - `range` has to be a subset of parent texture
1933#[derive(Clone, Debug)]
1934pub struct TextureViewDescriptor<'a> {
1935 pub label: Label<'a>,
1936 pub format: wgt::TextureFormat,
1937 pub dimension: wgt::TextureViewDimension,
1938 pub usage: wgt::TextureUses,
1939 pub range: wgt::ImageSubresourceRange,
1940}
1941
1942#[derive(Clone, Debug)]
1943pub struct SamplerDescriptor<'a> {
1944 pub label: Label<'a>,
1945 pub address_modes: [wgt::AddressMode; 3],
1946 pub mag_filter: wgt::FilterMode,
1947 pub min_filter: wgt::FilterMode,
1948 pub mipmap_filter: wgt::FilterMode,
1949 pub lod_clamp: Range<f32>,
1950 pub compare: Option<wgt::CompareFunction>,
1951 // Must in the range [1, 16].
1952 //
1953 // Anisotropic filtering must be supported if this is not 1.
1954 pub anisotropy_clamp: u16,
1955 pub border_color: Option<wgt::SamplerBorderColor>,
1956}
1957
1958/// BindGroupLayout descriptor.
1959///
1960/// Valid usage:
1961/// - `entries` are sorted by ascending `wgt::BindGroupLayoutEntry::binding`
1962#[derive(Clone, Debug)]
1963pub struct BindGroupLayoutDescriptor<'a> {
1964 pub label: Label<'a>,
1965 pub flags: BindGroupLayoutFlags,
1966 pub entries: &'a [wgt::BindGroupLayoutEntry],
1967}
1968
1969#[derive(Clone, Debug)]
1970pub struct PipelineLayoutDescriptor<'a, B: DynBindGroupLayout + ?Sized> {
1971 pub label: Label<'a>,
1972 pub flags: PipelineLayoutFlags,
1973 pub bind_group_layouts: &'a [&'a B],
1974 pub push_constant_ranges: &'a [wgt::PushConstantRange],
1975}
1976
1977/// A region of a buffer made visible to shaders via a [`BindGroup`].
1978///
1979/// [`BindGroup`]: Api::BindGroup
1980///
1981/// ## Construction
1982///
1983/// The recommended way to construct a `BufferBinding` is using the `binding`
1984/// method on a wgpu-core `Buffer`, which will validate the binding size
1985/// against the buffer size. A `new_unchecked` constructor is also provided for
1986/// cases where direct construction is necessary.
1987///
1988/// ## Accessible region
1989///
1990/// `wgpu_hal` guarantees that shaders compiled with
1991/// [`ShaderModuleDescriptor::runtime_checks`] set to `true` cannot read or
1992/// write data via this binding outside the *accessible region* of a buffer:
1993///
1994/// - The accessible region starts at [`offset`].
1995///
1996/// - For [`Storage`] bindings, the size of the accessible region is [`size`],
1997/// which must be a multiple of 4.
1998///
1999/// - For [`Uniform`] bindings, the size of the accessible region is [`size`]
2000/// rounded up to the next multiple of
2001/// [`Alignments::uniform_bounds_check_alignment`].
2002///
2003/// Note that this guarantee is stricter than WGSL's requirements for
2004/// [out-of-bounds accesses][woob], as WGSL allows them to return values from
2005/// elsewhere in the buffer. But this guarantee is necessary anyway, to permit
2006/// `wgpu-core` to avoid clearing uninitialized regions of buffers that will
2007/// never be read by the application before they are overwritten. This
2008/// optimization consults bind group buffer binding regions to determine which
2009/// parts of which buffers shaders might observe. This optimization is only
2010/// sound if shader access is bounds-checked.
2011///
2012/// ## Zero-length bindings
2013///
2014/// Some back ends cannot tolerate zero-length regions; for example, see
2015/// [VUID-VkDescriptorBufferInfo-offset-00340][340] and
2016/// [VUID-VkDescriptorBufferInfo-range-00341][341], or the
2017/// documentation for GLES's [glBindBufferRange][bbr]. This documentation
2018/// previously stated that a `BufferBinding` must have `offset` strictly less
2019/// than the size of the buffer, but this restriction was not honored elsewhere
2020/// in the code, so has been removed. However, it remains the case that
2021/// some backends do not support zero-length bindings, so additional
2022/// logic is needed somewhere to handle this properly. See
2023/// [#3170](https://github.com/gfx-rs/wgpu/issues/3170).
2024///
2025/// [`offset`]: BufferBinding::offset
2026/// [`size`]: BufferBinding::size
2027/// [`Storage`]: wgt::BufferBindingType::Storage
2028/// [`Uniform`]: wgt::BufferBindingType::Uniform
2029/// [340]: https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-VkDescriptorBufferInfo-offset-00340
2030/// [341]: https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-VkDescriptorBufferInfo-range-00341
2031/// [bbr]: https://registry.khronos.org/OpenGL-Refpages/es3.0/html/glBindBufferRange.xhtml
2032/// [woob]: https://gpuweb.github.io/gpuweb/wgsl/#out-of-bounds-access-sec
2033#[derive(Debug)]
2034pub struct BufferBinding<'a, B: DynBuffer + ?Sized> {
2035 /// The buffer being bound.
2036 ///
2037 /// This is not fully `pub` to prevent direct construction of
2038 /// `BufferBinding`s, while still allowing public read access to the `offset`
2039 /// and `size` properties.
2040 pub(crate) buffer: &'a B,
2041
2042 /// The offset at which the bound region starts.
2043 ///
2044 /// This must be less or equal to the size of the buffer.
2045 pub offset: wgt::BufferAddress,
2046
2047 /// The size of the region bound, in bytes.
2048 ///
2049 /// If `None`, the region extends from `offset` to the end of the
2050 /// buffer. Given the restrictions on `offset`, this means that
2051 /// the size is always greater than zero.
2052 pub size: Option<wgt::BufferSize>,
2053}
2054
2055// We must implement this manually because `B` is not necessarily `Clone`.
2056impl<B: DynBuffer + ?Sized> Clone for BufferBinding<'_, B> {
2057 fn clone(&self) -> Self {
2058 BufferBinding {
2059 buffer: self.buffer,
2060 offset: self.offset,
2061 size: self.size,
2062 }
2063 }
2064}
2065
2066/// Temporary convenience trait to let us call `.get()` on `u64`s in code that
2067/// really wants to be using `NonZeroU64`.
2068/// TODO(<https://github.com/gfx-rs/wgpu/issues/3170>): remove this
2069pub trait ShouldBeNonZeroExt {
2070 fn get(&self) -> u64;
2071}
2072
2073impl ShouldBeNonZeroExt for NonZeroU64 {
2074 fn get(&self) -> u64 {
2075 NonZeroU64::get(*self)
2076 }
2077}
2078
2079impl ShouldBeNonZeroExt for u64 {
2080 fn get(&self) -> u64 {
2081 *self
2082 }
2083}
2084
2085impl ShouldBeNonZeroExt for Option<NonZeroU64> {
2086 fn get(&self) -> u64 {
2087 match *self {
2088 Some(non_zero) => non_zero.get(),
2089 None => 0,
2090 }
2091 }
2092}
2093
2094impl<'a, B: DynBuffer + ?Sized> BufferBinding<'a, B> {
2095 /// Construct a `BufferBinding` with the given contents.
2096 ///
2097 /// When possible, use the `binding` method on a wgpu-core `Buffer` instead
2098 /// of this method. `Buffer::binding` validates the size of the binding
2099 /// against the size of the buffer.
2100 ///
2101 /// It is more difficult to provide a validating constructor here, due to
2102 /// not having direct access to the size of a `DynBuffer`.
2103 ///
2104 /// SAFETY: The caller is responsible for ensuring that a binding of `size`
2105 /// bytes starting at `offset` is contained within the buffer.
2106 ///
2107 /// The `S` type parameter is a temporary convenience to allow callers to
2108 /// pass a zero size. When the zero-size binding issue is resolved, the
2109 /// argument should just match the type of the member.
2110 /// TODO(<https://github.com/gfx-rs/wgpu/issues/3170>): remove the parameter
2111 pub fn new_unchecked<S: Into<Option<NonZeroU64>>>(
2112 buffer: &'a B,
2113 offset: wgt::BufferAddress,
2114 size: S,
2115 ) -> Self {
2116 Self {
2117 buffer,
2118 offset,
2119 size: size.into(),
2120 }
2121 }
2122}
2123
2124#[derive(Debug)]
2125pub struct TextureBinding<'a, T: DynTextureView + ?Sized> {
2126 pub view: &'a T,
2127 pub usage: wgt::TextureUses,
2128}
2129
2130impl<'a, T: DynTextureView + ?Sized> Clone for TextureBinding<'a, T> {
2131 fn clone(&self) -> Self {
2132 TextureBinding {
2133 view: self.view,
2134 usage: self.usage,
2135 }
2136 }
2137}
2138
2139#[derive(Debug)]
2140pub struct ExternalTextureBinding<'a, B: DynBuffer + ?Sized, T: DynTextureView + ?Sized> {
2141 pub planes: [TextureBinding<'a, T>; 3],
2142 pub params: BufferBinding<'a, B>,
2143}
2144
2145impl<'a, B: DynBuffer + ?Sized, T: DynTextureView + ?Sized> Clone
2146 for ExternalTextureBinding<'a, B, T>
2147{
2148 fn clone(&self) -> Self {
2149 ExternalTextureBinding {
2150 planes: self.planes.clone(),
2151 params: self.params.clone(),
2152 }
2153 }
2154}
2155
2156/// cbindgen:ignore
2157#[derive(Clone, Debug)]
2158pub struct BindGroupEntry {
2159 pub binding: u32,
2160 pub resource_index: u32,
2161 pub count: u32,
2162}
2163
2164/// BindGroup descriptor.
2165///
2166/// Valid usage:
2167///. - `entries` has to be sorted by ascending `BindGroupEntry::binding`
2168///. - `entries` has to have the same set of `BindGroupEntry::binding` as `layout`
2169///. - each entry has to be compatible with the `layout`
2170///. - each entry's `BindGroupEntry::resource_index` is within range
2171/// of the corresponding resource array, selected by the relevant
2172/// `BindGroupLayoutEntry`.
2173#[derive(Clone, Debug)]
2174pub struct BindGroupDescriptor<
2175 'a,
2176 Bgl: DynBindGroupLayout + ?Sized,
2177 B: DynBuffer + ?Sized,
2178 S: DynSampler + ?Sized,
2179 T: DynTextureView + ?Sized,
2180 A: DynAccelerationStructure + ?Sized,
2181> {
2182 pub label: Label<'a>,
2183 pub layout: &'a Bgl,
2184 pub buffers: &'a [BufferBinding<'a, B>],
2185 pub samplers: &'a [&'a S],
2186 pub textures: &'a [TextureBinding<'a, T>],
2187 pub entries: &'a [BindGroupEntry],
2188 pub acceleration_structures: &'a [&'a A],
2189 pub external_textures: &'a [ExternalTextureBinding<'a, B, T>],
2190}
2191
2192#[derive(Clone, Debug)]
2193pub struct CommandEncoderDescriptor<'a, Q: DynQueue + ?Sized> {
2194 pub label: Label<'a>,
2195 pub queue: &'a Q,
2196}
2197
2198/// Naga shader module.
2199#[derive(Default)]
2200pub struct NagaShader {
2201 /// Shader module IR.
2202 pub module: Cow<'static, naga::Module>,
2203 /// Analysis information of the module.
2204 pub info: naga::valid::ModuleInfo,
2205 /// Source codes for debug
2206 pub debug_source: Option<DebugSource>,
2207}
2208
2209// Custom implementation avoids the need to generate Debug impl code
2210// for the whole Naga module and info.
2211impl fmt::Debug for NagaShader {
2212 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
2213 write!(formatter, "Naga shader")
2214 }
2215}
2216
2217/// Shader input.
2218#[allow(clippy::large_enum_variant)]
2219pub enum ShaderInput<'a> {
2220 Naga(NagaShader),
2221 Msl {
2222 shader: String,
2223 entry_point: String,
2224 num_workgroups: (u32, u32, u32),
2225 },
2226 SpirV(&'a [u32]),
2227 Dxil {
2228 shader: &'a [u8],
2229 entry_point: String,
2230 num_workgroups: (u32, u32, u32),
2231 },
2232 Hlsl {
2233 shader: &'a str,
2234 entry_point: String,
2235 num_workgroups: (u32, u32, u32),
2236 },
2237}
2238
2239pub struct ShaderModuleDescriptor<'a> {
2240 pub label: Label<'a>,
2241
2242 /// # Safety
2243 ///
2244 /// See the documentation for each flag in [`ShaderRuntimeChecks`][src].
2245 ///
2246 /// [src]: wgt::ShaderRuntimeChecks
2247 pub runtime_checks: wgt::ShaderRuntimeChecks,
2248}
2249
2250#[derive(Debug, Clone)]
2251pub struct DebugSource {
2252 pub file_name: Cow<'static, str>,
2253 pub source_code: Cow<'static, str>,
2254}
2255
2256/// Describes a programmable pipeline stage.
2257#[derive(Debug)]
2258pub struct ProgrammableStage<'a, M: DynShaderModule + ?Sized> {
2259 /// The compiled shader module for this stage.
2260 pub module: &'a M,
2261 /// The name of the entry point in the compiled shader. There must be a function with this name
2262 /// in the shader.
2263 pub entry_point: &'a str,
2264 /// Pipeline constants
2265 pub constants: &'a naga::back::PipelineConstants,
2266 /// Whether workgroup scoped memory will be initialized with zero values for this stage.
2267 ///
2268 /// This is required by the WebGPU spec, but may have overhead which can be avoided
2269 /// for cross-platform applications
2270 pub zero_initialize_workgroup_memory: bool,
2271}
2272
2273impl<M: DynShaderModule + ?Sized> Clone for ProgrammableStage<'_, M> {
2274 fn clone(&self) -> Self {
2275 Self {
2276 module: self.module,
2277 entry_point: self.entry_point,
2278 constants: self.constants,
2279 zero_initialize_workgroup_memory: self.zero_initialize_workgroup_memory,
2280 }
2281 }
2282}
2283
2284/// Describes a compute pipeline.
2285#[derive(Clone, Debug)]
2286pub struct ComputePipelineDescriptor<
2287 'a,
2288 Pl: DynPipelineLayout + ?Sized,
2289 M: DynShaderModule + ?Sized,
2290 Pc: DynPipelineCache + ?Sized,
2291> {
2292 pub label: Label<'a>,
2293 /// The layout of bind groups for this pipeline.
2294 pub layout: &'a Pl,
2295 /// The compiled compute stage and its entry point.
2296 pub stage: ProgrammableStage<'a, M>,
2297 /// The cache which will be used and filled when compiling this pipeline
2298 pub cache: Option<&'a Pc>,
2299}
2300
2301pub struct PipelineCacheDescriptor<'a> {
2302 pub label: Label<'a>,
2303 pub data: Option<&'a [u8]>,
2304}
2305
2306/// Describes how the vertex buffer is interpreted.
2307#[derive(Clone, Debug)]
2308pub struct VertexBufferLayout<'a> {
2309 /// The stride, in bytes, between elements of this buffer.
2310 pub array_stride: wgt::BufferAddress,
2311 /// How often this vertex buffer is "stepped" forward.
2312 pub step_mode: wgt::VertexStepMode,
2313 /// The list of attributes which comprise a single vertex.
2314 pub attributes: &'a [wgt::VertexAttribute],
2315}
2316
2317#[derive(Clone, Debug)]
2318pub enum VertexProcessor<'a, M: DynShaderModule + ?Sized> {
2319 Standard {
2320 /// The format of any vertex buffers used with this pipeline.
2321 vertex_buffers: &'a [VertexBufferLayout<'a>],
2322 /// The vertex stage for this pipeline.
2323 vertex_stage: ProgrammableStage<'a, M>,
2324 },
2325 Mesh {
2326 task_stage: Option<ProgrammableStage<'a, M>>,
2327 mesh_stage: ProgrammableStage<'a, M>,
2328 },
2329}
2330
2331/// Describes a render (graphics) pipeline.
2332#[derive(Clone, Debug)]
2333pub struct RenderPipelineDescriptor<
2334 'a,
2335 Pl: DynPipelineLayout + ?Sized,
2336 M: DynShaderModule + ?Sized,
2337 Pc: DynPipelineCache + ?Sized,
2338> {
2339 pub label: Label<'a>,
2340 /// The layout of bind groups for this pipeline.
2341 pub layout: &'a Pl,
2342 /// The vertex processing state(vertex shader + buffers or task + mesh shaders)
2343 pub vertex_processor: VertexProcessor<'a, M>,
2344 /// The properties of the pipeline at the primitive assembly and rasterization level.
2345 pub primitive: wgt::PrimitiveState,
2346 /// The effect of draw calls on the depth and stencil aspects of the output target, if any.
2347 pub depth_stencil: Option<wgt::DepthStencilState>,
2348 /// The multi-sampling properties of the pipeline.
2349 pub multisample: wgt::MultisampleState,
2350 /// The fragment stage for this pipeline.
2351 pub fragment_stage: Option<ProgrammableStage<'a, M>>,
2352 /// The effect of draw calls on the color aspect of the output target.
2353 pub color_targets: &'a [Option<wgt::ColorTargetState>],
2354 /// If the pipeline will be used with a multiview render pass, this indicates how many array
2355 /// layers the attachments will have.
2356 pub multiview: Option<NonZeroU32>,
2357 /// The cache which will be used and filled when compiling this pipeline
2358 pub cache: Option<&'a Pc>,
2359}
2360
2361#[derive(Debug, Clone)]
2362pub struct SurfaceConfiguration {
2363 /// Maximum number of queued frames. Must be in
2364 /// `SurfaceCapabilities::maximum_frame_latency` range.
2365 pub maximum_frame_latency: u32,
2366 /// Vertical synchronization mode.
2367 pub present_mode: wgt::PresentMode,
2368 /// Alpha composition mode.
2369 pub composite_alpha_mode: wgt::CompositeAlphaMode,
2370 /// Format of the surface textures.
2371 pub format: wgt::TextureFormat,
2372 /// Requested texture extent. Must be in
2373 /// `SurfaceCapabilities::extents` range.
2374 pub extent: wgt::Extent3d,
2375 /// Allowed usage of surface textures,
2376 pub usage: wgt::TextureUses,
2377 /// Allows views of swapchain texture to have a different format
2378 /// than the texture does.
2379 pub view_formats: Vec<wgt::TextureFormat>,
2380}
2381
2382#[derive(Debug, Clone)]
2383pub struct Rect<T> {
2384 pub x: T,
2385 pub y: T,
2386 pub w: T,
2387 pub h: T,
2388}
2389
2390#[derive(Debug, Clone, PartialEq)]
2391pub struct StateTransition<T> {
2392 pub from: T,
2393 pub to: T,
2394}
2395
2396#[derive(Debug, Clone)]
2397pub struct BufferBarrier<'a, B: DynBuffer + ?Sized> {
2398 pub buffer: &'a B,
2399 pub usage: StateTransition<wgt::BufferUses>,
2400}
2401
2402#[derive(Debug, Clone)]
2403pub struct TextureBarrier<'a, T: DynTexture + ?Sized> {
2404 pub texture: &'a T,
2405 pub range: wgt::ImageSubresourceRange,
2406 pub usage: StateTransition<wgt::TextureUses>,
2407}
2408
2409#[derive(Clone, Copy, Debug)]
2410pub struct BufferCopy {
2411 pub src_offset: wgt::BufferAddress,
2412 pub dst_offset: wgt::BufferAddress,
2413 pub size: wgt::BufferSize,
2414}
2415
2416#[derive(Clone, Debug)]
2417pub struct TextureCopyBase {
2418 pub mip_level: u32,
2419 pub array_layer: u32,
2420 /// Origin within a texture.
2421 /// Note: for 1D and 2D textures, Z must be 0.
2422 pub origin: wgt::Origin3d,
2423 pub aspect: FormatAspects,
2424}
2425
2426#[derive(Clone, Copy, Debug)]
2427pub struct CopyExtent {
2428 pub width: u32,
2429 pub height: u32,
2430 pub depth: u32,
2431}
2432
2433#[derive(Clone, Debug)]
2434pub struct TextureCopy {
2435 pub src_base: TextureCopyBase,
2436 pub dst_base: TextureCopyBase,
2437 pub size: CopyExtent,
2438}
2439
2440#[derive(Clone, Debug)]
2441pub struct BufferTextureCopy {
2442 pub buffer_layout: wgt::TexelCopyBufferLayout,
2443 pub texture_base: TextureCopyBase,
2444 pub size: CopyExtent,
2445}
2446
2447#[derive(Clone, Debug)]
2448pub struct Attachment<'a, T: DynTextureView + ?Sized> {
2449 pub view: &'a T,
2450 /// Contains either a single mutating usage as a target,
2451 /// or a valid combination of read-only usages.
2452 pub usage: wgt::TextureUses,
2453}
2454
2455#[derive(Clone, Debug)]
2456pub struct ColorAttachment<'a, T: DynTextureView + ?Sized> {
2457 pub target: Attachment<'a, T>,
2458 pub depth_slice: Option<u32>,
2459 pub resolve_target: Option<Attachment<'a, T>>,
2460 pub ops: AttachmentOps,
2461 pub clear_value: wgt::Color,
2462}
2463
2464#[derive(Clone, Debug)]
2465pub struct DepthStencilAttachment<'a, T: DynTextureView + ?Sized> {
2466 pub target: Attachment<'a, T>,
2467 pub depth_ops: AttachmentOps,
2468 pub stencil_ops: AttachmentOps,
2469 pub clear_value: (f32, u32),
2470}
2471
2472#[derive(Clone, Debug)]
2473pub struct PassTimestampWrites<'a, Q: DynQuerySet + ?Sized> {
2474 pub query_set: &'a Q,
2475 pub beginning_of_pass_write_index: Option<u32>,
2476 pub end_of_pass_write_index: Option<u32>,
2477}
2478
2479#[derive(Clone, Debug)]
2480pub struct RenderPassDescriptor<'a, Q: DynQuerySet + ?Sized, T: DynTextureView + ?Sized> {
2481 pub label: Label<'a>,
2482 pub extent: wgt::Extent3d,
2483 pub sample_count: u32,
2484 pub color_attachments: &'a [Option<ColorAttachment<'a, T>>],
2485 pub depth_stencil_attachment: Option<DepthStencilAttachment<'a, T>>,
2486 pub multiview: Option<NonZeroU32>,
2487 pub timestamp_writes: Option<PassTimestampWrites<'a, Q>>,
2488 pub occlusion_query_set: Option<&'a Q>,
2489}
2490
2491#[derive(Clone, Debug)]
2492pub struct ComputePassDescriptor<'a, Q: DynQuerySet + ?Sized> {
2493 pub label: Label<'a>,
2494 pub timestamp_writes: Option<PassTimestampWrites<'a, Q>>,
2495}
2496
2497#[test]
2498fn test_default_limits() {
2499 let limits = wgt::Limits::default();
2500 assert!(limits.max_bind_groups <= MAX_BIND_GROUPS as u32);
2501}
2502
2503#[derive(Clone, Debug)]
2504pub struct AccelerationStructureDescriptor<'a> {
2505 pub label: Label<'a>,
2506 pub size: wgt::BufferAddress,
2507 pub format: AccelerationStructureFormat,
2508 pub allow_compaction: bool,
2509}
2510
2511#[derive(Debug, Clone, Copy, Eq, PartialEq)]
2512pub enum AccelerationStructureFormat {
2513 TopLevel,
2514 BottomLevel,
2515}
2516
2517#[derive(Debug, Clone, Copy, Eq, PartialEq)]
2518pub enum AccelerationStructureBuildMode {
2519 Build,
2520 Update,
2521}
2522
2523/// Information of the required size for a corresponding entries struct (+ flags)
2524#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
2525pub struct AccelerationStructureBuildSizes {
2526 pub acceleration_structure_size: wgt::BufferAddress,
2527 pub update_scratch_size: wgt::BufferAddress,
2528 pub build_scratch_size: wgt::BufferAddress,
2529}
2530
2531/// Updates use source_acceleration_structure if present, else the update will be performed in place.
2532/// For updates, only the data is allowed to change (not the meta data or sizes).
2533#[derive(Clone, Debug)]
2534pub struct BuildAccelerationStructureDescriptor<
2535 'a,
2536 B: DynBuffer + ?Sized,
2537 A: DynAccelerationStructure + ?Sized,
2538> {
2539 pub entries: &'a AccelerationStructureEntries<'a, B>,
2540 pub mode: AccelerationStructureBuildMode,
2541 pub flags: AccelerationStructureBuildFlags,
2542 pub source_acceleration_structure: Option<&'a A>,
2543 pub destination_acceleration_structure: &'a A,
2544 pub scratch_buffer: &'a B,
2545 pub scratch_buffer_offset: wgt::BufferAddress,
2546}
2547
2548/// - All buffers, buffer addresses and offsets will be ignored.
2549/// - The build mode will be ignored.
2550/// - Reducing the amount of Instances, Triangle groups or AABB groups (or the number of Triangles/AABBs in corresponding groups),
2551/// may result in reduced size requirements.
2552/// - Any other change may result in a bigger or smaller size requirement.
2553#[derive(Clone, Debug)]
2554pub struct GetAccelerationStructureBuildSizesDescriptor<'a, B: DynBuffer + ?Sized> {
2555 pub entries: &'a AccelerationStructureEntries<'a, B>,
2556 pub flags: AccelerationStructureBuildFlags,
2557}
2558
2559/// Entries for a single descriptor
2560/// * `Instances` - Multiple instances for a top level acceleration structure
2561/// * `Triangles` - Multiple triangle meshes for a bottom level acceleration structure
2562/// * `AABBs` - List of list of axis aligned bounding boxes for a bottom level acceleration structure
2563#[derive(Debug)]
2564pub enum AccelerationStructureEntries<'a, B: DynBuffer + ?Sized> {
2565 Instances(AccelerationStructureInstances<'a, B>),
2566 Triangles(Vec<AccelerationStructureTriangles<'a, B>>),
2567 AABBs(Vec<AccelerationStructureAABBs<'a, B>>),
2568}
2569
2570/// * `first_vertex` - offset in the vertex buffer (as number of vertices)
2571/// * `indices` - optional index buffer with attributes
2572/// * `transform` - optional transform
2573#[derive(Clone, Debug)]
2574pub struct AccelerationStructureTriangles<'a, B: DynBuffer + ?Sized> {
2575 pub vertex_buffer: Option<&'a B>,
2576 pub vertex_format: wgt::VertexFormat,
2577 pub first_vertex: u32,
2578 pub vertex_count: u32,
2579 pub vertex_stride: wgt::BufferAddress,
2580 pub indices: Option<AccelerationStructureTriangleIndices<'a, B>>,
2581 pub transform: Option<AccelerationStructureTriangleTransform<'a, B>>,
2582 pub flags: AccelerationStructureGeometryFlags,
2583}
2584
2585/// * `offset` - offset in bytes
2586#[derive(Clone, Debug)]
2587pub struct AccelerationStructureAABBs<'a, B: DynBuffer + ?Sized> {
2588 pub buffer: Option<&'a B>,
2589 pub offset: u32,
2590 pub count: u32,
2591 pub stride: wgt::BufferAddress,
2592 pub flags: AccelerationStructureGeometryFlags,
2593}
2594
2595pub struct AccelerationStructureCopy {
2596 pub copy_flags: wgt::AccelerationStructureCopy,
2597 pub type_flags: wgt::AccelerationStructureType,
2598}
2599
2600/// * `offset` - offset in bytes
2601#[derive(Clone, Debug)]
2602pub struct AccelerationStructureInstances<'a, B: DynBuffer + ?Sized> {
2603 pub buffer: Option<&'a B>,
2604 pub offset: u32,
2605 pub count: u32,
2606}
2607
2608/// * `offset` - offset in bytes
2609#[derive(Clone, Debug)]
2610pub struct AccelerationStructureTriangleIndices<'a, B: DynBuffer + ?Sized> {
2611 pub format: wgt::IndexFormat,
2612 pub buffer: Option<&'a B>,
2613 pub offset: u32,
2614 pub count: u32,
2615}
2616
2617/// * `offset` - offset in bytes
2618#[derive(Clone, Debug)]
2619pub struct AccelerationStructureTriangleTransform<'a, B: DynBuffer + ?Sized> {
2620 pub buffer: &'a B,
2621 pub offset: u32,
2622}
2623
2624pub use wgt::AccelerationStructureFlags as AccelerationStructureBuildFlags;
2625pub use wgt::AccelerationStructureGeometryFlags;
2626
2627bitflags::bitflags! {
2628 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
2629 pub struct AccelerationStructureUses: u8 {
2630 // For blas used as input for tlas
2631 const BUILD_INPUT = 1 << 0;
2632 // Target for acceleration structure build
2633 const BUILD_OUTPUT = 1 << 1;
2634 // Tlas used in a shader
2635 const SHADER_INPUT = 1 << 2;
2636 // Blas used to query compacted size
2637 const QUERY_INPUT = 1 << 3;
2638 // BLAS used as a src for a copy operation
2639 const COPY_SRC = 1 << 4;
2640 // BLAS used as a dst for a copy operation
2641 const COPY_DST = 1 << 5;
2642 }
2643}
2644
2645#[derive(Debug, Clone)]
2646pub struct AccelerationStructureBarrier {
2647 pub usage: StateTransition<AccelerationStructureUses>,
2648}
2649
2650#[derive(Debug, Copy, Clone)]
2651pub struct TlasInstance {
2652 pub transform: [f32; 12],
2653 pub custom_data: u32,
2654 pub mask: u8,
2655 pub blas_address: u64,
2656}