Skip to main content

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))]
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    // TODO!
223    clippy::missing_safety_doc,
224    // It gets in the way a lot and does not prevent bugs in practice.
225    clippy::pattern_type_mismatch,
226    // We should investigate these.
227    clippy::large_enum_variant
228)]
229#![warn(
230    clippy::alloc_instead_of_core,
231    clippy::ptr_as_ptr,
232    clippy::std_instead_of_alloc,
233    clippy::std_instead_of_core,
234    trivial_casts,
235    trivial_numeric_casts,
236    unsafe_op_in_unsafe_fn,
237    unused_extern_crates,
238    unused_qualifications
239)]
240
241extern crate alloc;
242#[allow(unused_extern_crates)]
243extern crate naga_types as nt;
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, DynRayTracingPipeline, DynRenderPipeline,
292    DynResource, DynSampler, DynShaderModule, DynSurface, DynSurfaceTexture, DynTexture,
293    DynTextureView,
294};
295
296#[allow(unused)]
297use alloc::boxed::Box;
298use alloc::{borrow::Cow, string::String, vec::Vec};
299use core::{
300    borrow::Borrow,
301    error::Error,
302    fmt,
303    num::{NonZeroU32, NonZeroU64},
304    ops::{Range, RangeInclusive},
305    ptr::NonNull,
306};
307
308use bitflags::bitflags;
309use raw_window_handle::DisplayHandle;
310use thiserror::Error;
311use wgt::WasmNotSendSync;
312
313cfg_if::cfg_if! {
314    if #[cfg(supports_ptr_atomics)] {
315        use alloc::sync::Arc;
316    } else if #[cfg(feature = "portable-atomic")] {
317        use portable_atomic_util::Arc;
318    }
319}
320
321// - Vertex + Fragment
322// - Compute
323// Task + Mesh + Fragment
324pub const MAX_CONCURRENT_SHADER_STAGES: usize = 3;
325pub const MAX_ANISOTROPY: u8 = 16;
326pub const MAX_BIND_GROUPS: usize = 8;
327pub const MAX_VERTEX_BUFFERS: usize = 16;
328pub const MAX_COLOR_ATTACHMENTS: usize = 8;
329pub const MAX_MIP_LEVELS: u32 = 16;
330/// Size of a single occlusion/timestamp query, when copied into a buffer, in bytes.
331/// cbindgen:ignore
332pub const QUERY_SIZE: wgt::BufferAddress = 8;
333
334pub type Label<'a> = Option<&'a str>;
335pub type MemoryRange = Range<wgt::BufferAddress>;
336pub type FenceValue = u64;
337#[cfg(supports_64bit_atomics)]
338pub type AtomicFenceValue = core::sync::atomic::AtomicU64;
339#[cfg(not(supports_64bit_atomics))]
340pub type AtomicFenceValue = portable_atomic::AtomicU64;
341
342/// A callback to signal that wgpu is no longer using a resource.
343#[cfg(any(gles, vulkan, metal))]
344pub type DropCallback = Box<dyn FnOnce() + Send + Sync + 'static>;
345
346#[cfg(any(gles, vulkan, metal))]
347pub struct DropGuard {
348    callback: Option<DropCallback>,
349}
350
351#[cfg(all(any(gles, vulkan, metal), any(native, Emscripten)))]
352impl DropGuard {
353    fn from_option(callback: Option<DropCallback>) -> Option<Self> {
354        callback.map(Self::new)
355    }
356
357    fn new(callback: DropCallback) -> Self {
358        Self {
359            callback: Some(callback),
360        }
361    }
362}
363
364#[cfg(any(gles, vulkan, metal))]
365impl Drop for DropGuard {
366    fn drop(&mut self) {
367        if let Some(cb) = self.callback.take() {
368            (cb)();
369        }
370    }
371}
372
373#[cfg(any(gles, vulkan, metal))]
374impl fmt::Debug for DropGuard {
375    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
376        f.debug_struct("DropGuard").finish()
377    }
378}
379
380#[derive(Clone, Debug, PartialEq, Eq, Error)]
381pub enum DeviceError {
382    #[error("Out of memory")]
383    OutOfMemory,
384    #[error("Device is lost")]
385    Lost,
386    #[error("Unexpected error variant (driver implementation is at fault)")]
387    Unexpected,
388}
389
390#[cfg(any(dx12, vulkan))]
391impl From<gpu_allocator::AllocationError> for DeviceError {
392    fn from(result: gpu_allocator::AllocationError) -> Self {
393        match result {
394            gpu_allocator::AllocationError::OutOfMemory => Self::OutOfMemory,
395            gpu_allocator::AllocationError::FailedToMap(e) => {
396                log::error!("gpu-allocator: Failed to map: {e}");
397                Self::Lost
398            }
399            gpu_allocator::AllocationError::NoCompatibleMemoryTypeFound => {
400                log::error!("gpu-allocator: No Compatible Memory Type Found");
401                Self::Lost
402            }
403            gpu_allocator::AllocationError::InvalidAllocationCreateDesc => {
404                log::error!("gpu-allocator: Invalid Allocation Creation Description");
405                Self::Lost
406            }
407            gpu_allocator::AllocationError::InvalidAllocatorCreateDesc(e) => {
408                log::error!("gpu-allocator: Invalid Allocator Creation Description: {e}");
409                Self::Lost
410            }
411
412            gpu_allocator::AllocationError::Internal(e) => {
413                log::error!("gpu-allocator: Internal Error: {e}");
414                Self::Lost
415            }
416            gpu_allocator::AllocationError::BarrierLayoutNeedsDevice10
417            | gpu_allocator::AllocationError::CastableFormatsRequiresEnhancedBarriers
418            | gpu_allocator::AllocationError::CastableFormatsRequiresAtLeastDevice12 => {
419                unreachable!()
420            }
421        }
422    }
423}
424
425// A copy of gpu_allocator::AllocationSizes, allowing to read the configured value for
426// the dx12 backend, we should instead add getters to gpu_allocator::AllocationSizes
427// and remove this type.
428// https://github.com/Traverse-Research/gpu-allocator/issues/295
429#[cfg_attr(not(any(dx12, vulkan)), expect(dead_code))]
430pub(crate) struct AllocationSizes {
431    pub(crate) min_device_memblock_size: u64,
432    pub(crate) max_device_memblock_size: u64,
433    pub(crate) min_host_memblock_size: u64,
434    pub(crate) max_host_memblock_size: u64,
435}
436
437impl AllocationSizes {
438    #[allow(dead_code, reason = "may be unused on some platforms")]
439    pub(crate) fn from_memory_hints(memory_hints: &wgt::MemoryHints) -> Self {
440        // TODO: the allocator's configuration should take hardware capability into
441        // account.
442        const MB: u64 = 1024 * 1024;
443
444        match memory_hints {
445            wgt::MemoryHints::Performance => Self {
446                min_device_memblock_size: 128 * MB,
447                max_device_memblock_size: 256 * MB,
448                min_host_memblock_size: 64 * MB,
449                max_host_memblock_size: 128 * MB,
450            },
451            wgt::MemoryHints::MemoryUsage => Self {
452                min_device_memblock_size: 8 * MB,
453                max_device_memblock_size: 64 * MB,
454                min_host_memblock_size: 4 * MB,
455                max_host_memblock_size: 32 * MB,
456            },
457            wgt::MemoryHints::Manual {
458                suballocated_device_memory_block_size,
459            } => {
460                // TODO: https://github.com/gfx-rs/wgpu/issues/8625
461                // Would it be useful to expose the host size in memory hints
462                // instead of always using half of the device size?
463                let device_size = suballocated_device_memory_block_size;
464                let host_size = device_size.start / 2..device_size.end / 2;
465
466                // gpu_allocator clamps the sizes between 4MiB and 256MiB, but we clamp them ourselves since we use
467                // the sizes when detecting high memory pressure and there is no way to query the values otherwise.
468                Self {
469                    min_device_memblock_size: device_size.start.clamp(4 * MB, 256 * MB),
470                    max_device_memblock_size: device_size.end.clamp(4 * MB, 256 * MB),
471                    min_host_memblock_size: host_size.start.clamp(4 * MB, 256 * MB),
472                    max_host_memblock_size: host_size.end.clamp(4 * MB, 256 * MB),
473                }
474            }
475        }
476    }
477}
478
479#[cfg(any(dx12, vulkan))]
480impl From<AllocationSizes> for gpu_allocator::AllocationSizes {
481    fn from(value: AllocationSizes) -> gpu_allocator::AllocationSizes {
482        gpu_allocator::AllocationSizes::new(
483            value.min_device_memblock_size,
484            value.min_host_memblock_size,
485        )
486        .with_max_device_memblock_size(value.max_device_memblock_size)
487        .with_max_host_memblock_size(value.max_host_memblock_size)
488    }
489}
490
491#[allow(dead_code, reason = "may be unused on some platforms")]
492#[cold]
493fn hal_usage_error<T: fmt::Display>(txt: T) -> ! {
494    panic!("wgpu-hal invariant was violated (usage error): {txt}")
495}
496
497#[allow(dead_code, reason = "may be unused on some platforms")]
498#[cold]
499fn hal_internal_error<T: fmt::Display>(txt: T) -> ! {
500    panic!("wgpu-hal ran into a preventable internal error: {txt}")
501}
502
503#[derive(Clone, Debug, Eq, PartialEq, Error)]
504pub enum ShaderError {
505    #[error("Compilation failed: {0:?}")]
506    Compilation(String),
507    #[error(transparent)]
508    Device(#[from] DeviceError),
509}
510
511#[derive(Clone, Debug, Eq, PartialEq, Error)]
512pub enum PipelineError {
513    #[error("Linkage failed for stage {0:?}: {1}")]
514    Linkage(wgt::ShaderStages, String),
515    #[error("Entry point for stage {0:?} is invalid")]
516    EntryPoint(naga::ShaderStage),
517    #[error(transparent)]
518    Device(#[from] DeviceError),
519    #[error("Pipeline constant error for stage {0:?}: {1}")]
520    PipelineConstants(wgt::ShaderStages, String),
521}
522
523#[derive(Clone, Debug, Eq, PartialEq, Error)]
524pub enum PipelineCacheError {
525    #[error(transparent)]
526    Device(#[from] DeviceError),
527}
528
529#[derive(Clone, Debug, Eq, PartialEq, Error)]
530pub enum SurfaceError {
531    #[error("Surface is lost")]
532    Lost,
533    #[error("Surface is outdated, needs to be re-created")]
534    Outdated,
535    #[error("Timed out waiting for a surface texture")]
536    Timeout,
537    #[error("The window is occluded (e.g. minimized or behind another window). Try again once the window is no longer occluded.")]
538    Occluded,
539    #[error(transparent)]
540    Device(#[from] DeviceError),
541    #[error("Other reason: {0}")]
542    Other(&'static str),
543}
544
545/// Error occurring while trying to create an instance, or create a surface from an instance;
546/// typically relating to the state of the underlying graphics API or hardware.
547#[derive(Clone, Debug, Error)]
548#[error("{message}")]
549pub struct InstanceError {
550    /// These errors are very platform specific, so do not attempt to encode them as an enum.
551    ///
552    /// This message should describe the problem in sufficient detail to be useful for a
553    /// user-to-developer “why won't this work on my machine” bug report, and otherwise follow
554    /// <https://rust-lang.github.io/api-guidelines/interoperability.html#error-types-are-meaningful-and-well-behaved-c-good-err>.
555    message: String,
556
557    /// Underlying error value, if any is available.
558    #[source]
559    source: Option<Arc<dyn Error + Send + Sync + 'static>>,
560}
561
562impl InstanceError {
563    #[allow(dead_code, reason = "may be unused on some platforms")]
564    pub(crate) fn new(message: String) -> Self {
565        Self {
566            message,
567            source: None,
568        }
569    }
570    #[allow(dead_code, reason = "may be unused on some platforms")]
571    pub(crate) fn with_source(message: String, source: impl Error + Send + Sync + 'static) -> Self {
572        cfg_if::cfg_if! {
573            if #[cfg(supports_ptr_atomics)] {
574                let source = Arc::new(source);
575            } else {
576                // TODO(https://github.com/rust-lang/rust/issues/18598): avoid indirection via Box once arbitrary types support unsized coercion
577                let source: Box<dyn Error + Send + Sync + 'static> = Box::new(source);
578                let source = Arc::from(source);
579            }
580        }
581        Self {
582            message,
583            source: Some(source),
584        }
585    }
586}
587
588/// All the types and methods that make up a implementation on top of a backend.
589///
590/// Only the types that have non-dyn trait bounds have methods on them. Most methods
591/// are either on [`CommandEncoder`] or [`Device`].
592///
593/// The api can either be used through generics (through use of this trait and associated
594/// types) or dynamically through using the `Dyn*` traits.
595pub trait Api: Clone + fmt::Debug + Sized + WasmNotSendSync + 'static {
596    const VARIANT: wgt::Backend;
597
598    type Instance: DynInstance + Instance<A = Self>;
599    type Surface: DynSurface + Surface<A = Self>;
600    type Adapter: DynAdapter + Adapter<A = Self>;
601    type Device: DynDevice + Device<A = Self>;
602
603    type Queue: DynQueue + Queue<A = Self>;
604    type CommandEncoder: DynCommandEncoder + CommandEncoder<A = Self>;
605
606    /// This API's command buffer type.
607    ///
608    /// The only thing you can do with `CommandBuffer`s is build them
609    /// with a [`CommandEncoder`] and then pass them to
610    /// [`Queue::submit`] for execution, or destroy them by passing
611    /// them to [`CommandEncoder::reset_all`].
612    ///
613    /// [`CommandEncoder`]: Api::CommandEncoder
614    type CommandBuffer: DynCommandBuffer;
615
616    type Buffer: DynBuffer;
617    type Texture: DynTexture;
618    type SurfaceTexture: DynSurfaceTexture + Borrow<Self::Texture>;
619    type TextureView: DynTextureView;
620    type Sampler: DynSampler;
621    type QuerySet: DynQuerySet;
622
623    /// A value you can block on to wait for something to finish.
624    ///
625    /// A `Fence` holds a monotonically increasing [`FenceValue`]. You can call
626    /// [`Device::wait`] to block until a fence reaches or passes a value you
627    /// choose. [`Queue::submit`] can take a `Fence` and a [`FenceValue`] to
628    /// store in it when the submitted work is complete.
629    ///
630    /// Attempting to set a fence to a value less than its current value has no
631    /// effect.
632    ///
633    /// Waiting on a fence returns as soon as the fence reaches *or passes* the
634    /// requested value. This implies that, in order to reliably determine when
635    /// an operation has completed, operations must finish in order of
636    /// increasing fence values: if a higher-valued operation were to finish
637    /// before a lower-valued operation, then waiting for the fence to reach the
638    /// lower value could return before the lower-valued operation has actually
639    /// finished.
640    ///
641    /// Fences are internally synchronised by the hal, and so should not need to be
642    /// contained in external synchronisation primitives.
643    type Fence: DynFence;
644
645    type BindGroupLayout: DynBindGroupLayout;
646    type BindGroup: DynBindGroup;
647    type PipelineLayout: DynPipelineLayout;
648    type ShaderModule: DynShaderModule;
649    type RenderPipeline: DynRenderPipeline;
650    type ComputePipeline: DynComputePipeline;
651    type RayTracingPipeline: DynRayTracingPipeline;
652    type PipelineCache: DynPipelineCache;
653
654    type AccelerationStructure: DynAccelerationStructure + 'static;
655}
656
657pub trait Instance: Sized + WasmNotSendSync {
658    type A: Api;
659
660    unsafe fn init(desc: &InstanceDescriptor<'_>) -> Result<Self, InstanceError>;
661    unsafe fn create_surface(
662        &self,
663        display_handle: raw_window_handle::RawDisplayHandle,
664        window_handle: raw_window_handle::RawWindowHandle,
665    ) -> Result<<Self::A as Api>::Surface, InstanceError>;
666    /// `surface_hint` is only used by the GLES backend targeting WebGL2
667    unsafe fn enumerate_adapters(
668        &self,
669        surface_hint: Option<&<Self::A as Api>::Surface>,
670    ) -> Vec<ExposedAdapter<Self::A>>;
671}
672
673pub trait Surface: WasmNotSendSync {
674    type A: Api;
675
676    /// Configure `self` to use `device`.
677    ///
678    /// # Safety
679    ///
680    /// - All GPU work using `self` must have been completed.
681    /// - All [`AcquiredSurfaceTexture`]s must have been destroyed.
682    /// - All [`Api::TextureView`]s derived from the [`AcquiredSurfaceTexture`]s must have been destroyed.
683    /// - The surface `self` must not currently be configured to use any other [`Device`].
684    unsafe fn configure(
685        &self,
686        device: &<Self::A as Api>::Device,
687        config: &SurfaceConfiguration,
688    ) -> Result<(), SurfaceError>;
689
690    /// Unconfigure `self` on `device`.
691    ///
692    /// # Safety
693    ///
694    /// - All GPU work that uses `surface` must have been completed.
695    /// - All [`AcquiredSurfaceTexture`]s must have been destroyed.
696    /// - All [`Api::TextureView`]s derived from the [`AcquiredSurfaceTexture`]s must have been destroyed.
697    /// - The surface `self` must have been configured on `device`.
698    unsafe fn unconfigure(&self, device: &<Self::A as Api>::Device);
699
700    /// Return the next texture to be presented by `self`, for the caller to draw on.
701    ///
702    /// On success, return an [`AcquiredSurfaceTexture`] representing the
703    /// texture into which the caller should draw the image to be displayed on
704    /// `self`.
705    ///
706    /// If `timeout` elapses before `self` has a texture ready to be acquired,
707    /// return `Err(SurfaceError::Timeout)`. If `timeout` is `None`, wait
708    /// indefinitely, with no timeout.
709    ///
710    /// # Using an [`AcquiredSurfaceTexture`]
711    ///
712    /// On success, this function returns an [`AcquiredSurfaceTexture`] whose
713    /// [`texture`] field is a [`SurfaceTexture`] from which the caller can
714    /// [`borrow`] a [`Texture`] to draw on. The [`AcquiredSurfaceTexture`] also
715    /// carries some metadata about that [`SurfaceTexture`].
716    ///
717    /// All calls to [`Queue::submit`] that draw on that [`Texture`] must also
718    /// include the [`SurfaceTexture`] in the `surface_textures` argument.
719    ///
720    /// When you are done drawing on the texture, you can display it on `self`
721    /// by passing the [`SurfaceTexture`] and `self` to [`Queue::present`].
722    ///
723    /// If you do not wish to display the texture, you must pass the
724    /// [`SurfaceTexture`] to [`self.discard_texture`], so that it can be reused
725    /// by future acquisitions.
726    ///
727    /// The fence is internally synchronised by the hal.
728    ///
729    /// # Portability
730    ///
731    /// Some backends can't support a timeout when acquiring a texture. On these
732    /// backends, `timeout` is ignored.
733    ///
734    /// On macOS, this returns `Err(SurfaceError::Timeout)` when the window is
735    /// not visible (minimized, fully occluded, or on another virtual desktop)
736    /// to avoid blocking in `CAMetalLayer.nextDrawable()`.
737    ///
738    /// # Safety
739    ///
740    /// - The surface `self` must currently be configured on some [`Device`].
741    ///
742    /// - The `fence` argument must be the same [`Fence`] passed to all calls to
743    ///   [`Queue::submit`] that used [`Texture`]s acquired from this surface.
744    ///
745    /// - You may only have one texture acquired from `self` at a time. When
746    ///   `acquire_texture` returns `Ok(ast)`, you must pass the returned
747    ///   [`SurfaceTexture`] `ast.texture` to either [`Queue::present`] or
748    ///   [`Surface::discard_texture`] before calling `acquire_texture` again.
749    ///
750    /// [`texture`]: AcquiredSurfaceTexture::texture
751    /// [`SurfaceTexture`]: Api::SurfaceTexture
752    /// [`borrow`]: alloc::borrow::Borrow::borrow
753    /// [`Texture`]: Api::Texture
754    /// [`Fence`]: Api::Fence
755    /// [`self.discard_texture`]: Surface::discard_texture
756    unsafe fn acquire_texture(
757        &self,
758        timeout: Option<core::time::Duration>,
759        fence: &<Self::A as Api>::Fence,
760    ) -> Result<AcquiredSurfaceTexture<Self::A>, SurfaceError>;
761
762    /// Relinquish an acquired texture without presenting it.
763    ///
764    /// After this call, the texture underlying [`SurfaceTexture`] may be
765    /// returned by subsequent calls to [`self.acquire_texture`].
766    ///
767    /// # Safety
768    ///
769    /// - The surface `self` must currently be configured on some [`Device`].
770    ///
771    /// - `texture` must be a [`SurfaceTexture`] returned by a call to
772    ///   [`self.acquire_texture`] that has not yet been passed to
773    ///   [`Queue::present`].
774    ///
775    /// [`SurfaceTexture`]: Api::SurfaceTexture
776    /// [`self.acquire_texture`]: Surface::acquire_texture
777    unsafe fn discard_texture(&self, texture: <Self::A as Api>::SurfaceTexture);
778}
779
780pub trait Adapter: WasmNotSendSync {
781    type A: Api;
782
783    unsafe fn open(
784        &self,
785        features: wgt::Features,
786        limits: &wgt::Limits,
787        memory_hints: &wgt::MemoryHints,
788    ) -> Result<OpenDevice<Self::A>, DeviceError>;
789
790    /// Return the set of supported capabilities for a texture format.
791    unsafe fn texture_format_capabilities(
792        &self,
793        format: wgt::TextureFormat,
794    ) -> TextureFormatCapabilities;
795
796    /// Returns the capabilities of working with a specified surface.
797    ///
798    /// `None` means presentation is not supported for it.
799    unsafe fn surface_capabilities(
800        &self,
801        surface: &<Self::A as Api>::Surface,
802    ) -> Option<SurfaceCapabilities>;
803
804    /// Returns the HDR / luminance characteristics of the display backing
805    /// `surface`, queried from the OS on each call.
806    ///
807    /// `None` means no information is available; wgpu-core maps it to
808    /// [`wgt::DisplayHdrInfo::default`]. Implementors must not panic; degrade any
809    /// OS-query failure to `None`. The default implementation returns `None`.
810    ///
811    /// Implemented by Metal (macOS only, and only from the main thread), DX12, and
812    /// Vulkan (Win32 `HWND` surfaces only); GLES and noop keep the default `None`.
813    unsafe fn surface_display_hdr_info(
814        &self,
815        surface: &<Self::A as Api>::Surface,
816    ) -> Option<wgt::DisplayHdrInfo> {
817        let _ = surface;
818        None
819    }
820
821    /// Creates a [`PresentationTimestamp`] using the adapter's WSI.
822    ///
823    /// [`PresentationTimestamp`]: wgt::PresentationTimestamp
824    unsafe fn get_presentation_timestamp(&self) -> wgt::PresentationTimestamp;
825
826    /// The combination of all usages that the are guaranteed to be be ordered by the hardware.
827    /// If a usage is ordered, then if the buffer state doesn't change between draw calls,
828    /// there are no barriers needed for synchronization.
829    fn get_ordered_buffer_usages(&self) -> wgt::BufferUses;
830
831    /// The combination of all usages that the are guaranteed to be be ordered by the hardware.
832    /// If a usage is ordered, then if the buffer state doesn't change between draw calls,
833    /// there are no barriers needed for synchronization.
834    fn get_ordered_texture_usages(&self) -> wgt::TextureUses;
835}
836
837/// A connection to a GPU and a pool of resources to use with it.
838///
839/// A `wgpu-hal` `Device` represents an open connection to a specific graphics
840/// processor, controlled via the backend [`Device::A`]. A `Device` is mostly
841/// used for creating resources. Each `Device` has an associated [`Queue`] used
842/// for command submission.
843///
844/// On Vulkan a `Device` corresponds to a logical device ([`VkDevice`]). Other
845/// backends don't have an exact analog: for example, [`ID3D12Device`]s and
846/// [`MTLDevice`]s are owned by the backends' [`wgpu_hal::Adapter`]
847/// implementations, and shared by all [`wgpu_hal::Device`]s created from that
848/// `Adapter`.
849///
850/// A `Device`'s life cycle is generally:
851///
852/// 1)  Obtain a `Device` and its associated [`Queue`] by calling
853///     [`Adapter::open`].
854///
855///     Alternatively, the backend-specific types that implement [`Adapter`] often
856///     have methods for creating a `wgpu-hal` `Device` from a platform-specific
857///     handle. For example, [`vulkan::Adapter::device_from_raw`] can create a
858///     [`vulkan::Device`] from an [`ash::Device`].
859///
860/// 1)  Create resources to use on the device by calling methods like
861///     [`Device::create_texture`] or [`Device::create_shader_module`].
862///
863/// 1)  Call [`Device::create_command_encoder`] to obtain a [`CommandEncoder`],
864///     which you can use to build [`CommandBuffer`]s holding commands to be
865///     executed on the GPU.
866///
867/// 1)  Call [`Queue::submit`] on the `Device`'s associated [`Queue`] to submit
868///     [`CommandBuffer`]s for execution on the GPU. If needed, call
869///     [`Device::wait`] to wait for them to finish execution.
870///
871/// 1)  Free resources with methods like [`Device::destroy_texture`] or
872///     [`Device::destroy_shader_module`].
873///
874/// 1)  Drop the device.
875///
876/// [`vkDevice`]: https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VkDevice
877/// [`ID3D12Device`]: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/nn-d3d12-id3d12device
878/// [`MTLDevice`]: https://developer.apple.com/documentation/metal/mtldevice
879/// [`wgpu_hal::Adapter`]: Adapter
880/// [`wgpu_hal::Device`]: Device
881/// [`vulkan::Adapter::device_from_raw`]: vulkan/struct.Adapter.html#method.device_from_raw
882/// [`vulkan::Device`]: vulkan/struct.Device.html
883/// [`ash::Device`]: https://docs.rs/ash/latest/ash/struct.Device.html
884/// [`CommandBuffer`]: Api::CommandBuffer
885///
886/// # Safety
887///
888/// As with other `wgpu-hal` APIs, [validation] is the caller's
889/// responsibility. Here are the general requirements for all `Device`
890/// methods:
891///
892/// - Any resource passed to a `Device` method must have been created by that
893///   `Device`. For example, a [`Texture`] passed to [`Device::destroy_texture`] must
894///   have been created with the `Device` passed as `self`.
895///
896/// - Resources may not be destroyed if they are used by any submitted command
897///   buffers that have not yet finished execution.
898///
899/// [validation]: index.html#validation-is-the-calling-codes-responsibility-not-wgpu-hals
900/// [`Texture`]: Api::Texture
901pub trait Device: WasmNotSendSync {
902    type A: Api;
903
904    /// Creates a new buffer.
905    ///
906    /// The initial usage is `wgt::BufferUses::empty()`.
907    unsafe fn create_buffer(
908        &self,
909        desc: &BufferDescriptor,
910    ) -> Result<<Self::A as Api>::Buffer, DeviceError>;
911
912    /// Free `buffer` and any GPU resources it owns.
913    ///
914    /// Note that backends are allowed to allocate GPU memory for buffers from
915    /// allocation pools, and this call is permitted to simply return `buffer`'s
916    /// storage to that pool, without making it available to other applications.
917    ///
918    /// # Safety
919    ///
920    /// - The given `buffer` must not currently be mapped.
921    unsafe fn destroy_buffer(&self, buffer: <Self::A as Api>::Buffer);
922
923    /// A hook for when a wgpu-core buffer is created from a raw wgpu-hal buffer.
924    unsafe fn add_raw_buffer(&self, buffer: &<Self::A as Api>::Buffer);
925
926    /// Return a pointer to CPU memory mapping the contents of `buffer`.
927    ///
928    /// Buffer mappings are persistent: the buffer may remain mapped on the CPU
929    /// while the GPU reads or writes to it. (Note that `wgpu_core` does not use
930    /// this feature: when a `wgpu_core::Buffer` is unmapped, the underlying
931    /// `wgpu_hal` buffer is also unmapped.)
932    ///
933    /// If this function returns `Ok(mapping)`, then:
934    ///
935    /// - `mapping.ptr` is the CPU address of the start of the mapped memory.
936    ///
937    /// - If `mapping.is_coherent` is `true`, then CPU writes to the mapped
938    ///   memory are immediately visible on the GPU, and vice versa.
939    ///
940    /// # Safety
941    ///
942    /// - The given `buffer` must have been created with the [`MAP_READ`] or
943    ///   [`MAP_WRITE`] flags set in [`BufferDescriptor::usage`].
944    ///
945    /// - The given `range` must fall within the size of `buffer`.
946    ///
947    /// - The caller must avoid data races between the CPU and the GPU. A data
948    ///   race is any pair of accesses to a particular byte, one of which is a
949    ///   write, that are not ordered with respect to each other by some sort of
950    ///   synchronization operation.
951    ///
952    /// - If this function returns `Ok(mapping)` and `mapping.is_coherent` is
953    ///   `false`, then:
954    ///
955    ///   - Every CPU write to a mapped byte followed by a GPU read of that byte
956    ///     must have at least one call to [`Device::flush_mapped_ranges`]
957    ///     covering that byte that occurs between those two accesses.
958    ///
959    ///   - Every GPU write to a mapped byte followed by a CPU read of that byte
960    ///     must have at least one call to [`Device::invalidate_mapped_ranges`]
961    ///     covering that byte that occurs between those two accesses.
962    ///
963    ///   Note that the data race rule above requires that all such access pairs
964    ///   be ordered, so it is meaningful to talk about what must occur
965    ///   "between" them.
966    ///
967    /// - Zero-sized mappings are not allowed.
968    ///
969    /// - The returned [`BufferMapping::ptr`] must not be used after a call to
970    ///   [`Device::unmap_buffer`].
971    ///
972    /// [`MAP_READ`]: wgt::BufferUses::MAP_READ
973    /// [`MAP_WRITE`]: wgt::BufferUses::MAP_WRITE
974    unsafe fn map_buffer(
975        &self,
976        buffer: &<Self::A as Api>::Buffer,
977        range: MemoryRange,
978    ) -> Result<BufferMapping, DeviceError>;
979
980    /// Remove the mapping established by the last call to [`Device::map_buffer`].
981    ///
982    /// # Safety
983    ///
984    /// - The given `buffer` must be currently mapped.
985    unsafe fn unmap_buffer(&self, buffer: &<Self::A as Api>::Buffer);
986
987    /// Indicate that CPU writes to mapped buffer memory should be made visible to the GPU.
988    ///
989    /// # Safety
990    ///
991    /// - The given `buffer` must be currently mapped.
992    ///
993    /// - All ranges produced by `ranges` must fall within `buffer`'s size.
994    unsafe fn flush_mapped_ranges<I>(&self, buffer: &<Self::A as Api>::Buffer, ranges: I)
995    where
996        I: Iterator<Item = MemoryRange>;
997
998    /// Indicate that GPU writes to mapped buffer memory should be made visible to the CPU.
999    ///
1000    /// # Safety
1001    ///
1002    /// - The given `buffer` must be currently mapped.
1003    ///
1004    /// - All ranges produced by `ranges` must fall within `buffer`'s size.
1005    unsafe fn invalidate_mapped_ranges<I>(&self, buffer: &<Self::A as Api>::Buffer, ranges: I)
1006    where
1007        I: Iterator<Item = MemoryRange>;
1008
1009    /// Creates a new texture.
1010    ///
1011    /// The initial usage for all subresources is `wgt::TextureUses::UNINITIALIZED`.
1012    unsafe fn create_texture(
1013        &self,
1014        desc: &TextureDescriptor,
1015    ) -> Result<<Self::A as Api>::Texture, DeviceError>;
1016    unsafe fn destroy_texture(&self, texture: <Self::A as Api>::Texture);
1017
1018    /// A hook for when a wgpu-core texture is created from a raw wgpu-hal texture.
1019    unsafe fn add_raw_texture(&self, texture: &<Self::A as Api>::Texture);
1020
1021    unsafe fn create_texture_view(
1022        &self,
1023        texture: &<Self::A as Api>::Texture,
1024        desc: &TextureViewDescriptor,
1025    ) -> Result<<Self::A as Api>::TextureView, DeviceError>;
1026    unsafe fn destroy_texture_view(&self, view: <Self::A as Api>::TextureView);
1027    unsafe fn create_sampler(
1028        &self,
1029        desc: &SamplerDescriptor,
1030    ) -> Result<<Self::A as Api>::Sampler, DeviceError>;
1031    unsafe fn destroy_sampler(&self, sampler: <Self::A as Api>::Sampler);
1032
1033    /// Create a fresh [`CommandEncoder`].
1034    ///
1035    /// The new `CommandEncoder` is in the "closed" state.
1036    unsafe fn create_command_encoder(
1037        &self,
1038        desc: &CommandEncoderDescriptor<<Self::A as Api>::Queue>,
1039    ) -> Result<<Self::A as Api>::CommandEncoder, DeviceError>;
1040
1041    /// Creates a bind group layout.
1042    unsafe fn create_bind_group_layout(
1043        &self,
1044        desc: &BindGroupLayoutDescriptor,
1045    ) -> Result<<Self::A as Api>::BindGroupLayout, DeviceError>;
1046    unsafe fn destroy_bind_group_layout(&self, bg_layout: <Self::A as Api>::BindGroupLayout);
1047    unsafe fn create_pipeline_layout(
1048        &self,
1049        desc: &PipelineLayoutDescriptor<<Self::A as Api>::BindGroupLayout>,
1050    ) -> Result<<Self::A as Api>::PipelineLayout, DeviceError>;
1051    unsafe fn destroy_pipeline_layout(&self, pipeline_layout: <Self::A as Api>::PipelineLayout);
1052
1053    #[allow(clippy::type_complexity)]
1054    unsafe fn create_bind_group(
1055        &self,
1056        desc: &BindGroupDescriptor<
1057            <Self::A as Api>::BindGroupLayout,
1058            <Self::A as Api>::Buffer,
1059            <Self::A as Api>::Sampler,
1060            <Self::A as Api>::TextureView,
1061            <Self::A as Api>::AccelerationStructure,
1062        >,
1063    ) -> Result<<Self::A as Api>::BindGroup, DeviceError>;
1064    unsafe fn destroy_bind_group(&self, group: <Self::A as Api>::BindGroup);
1065
1066    unsafe fn create_shader_module(
1067        &self,
1068        desc: &ShaderModuleDescriptor,
1069        shader: ShaderInput,
1070    ) -> Result<<Self::A as Api>::ShaderModule, ShaderError>;
1071    unsafe fn destroy_shader_module(&self, module: <Self::A as Api>::ShaderModule);
1072
1073    #[allow(clippy::type_complexity)]
1074    unsafe fn create_render_pipeline(
1075        &self,
1076        desc: &RenderPipelineDescriptor<
1077            <Self::A as Api>::PipelineLayout,
1078            <Self::A as Api>::ShaderModule,
1079            <Self::A as Api>::PipelineCache,
1080        >,
1081    ) -> Result<<Self::A as Api>::RenderPipeline, PipelineError>;
1082    unsafe fn destroy_render_pipeline(&self, pipeline: <Self::A as Api>::RenderPipeline);
1083
1084    #[allow(clippy::type_complexity)]
1085    unsafe fn create_compute_pipeline(
1086        &self,
1087        desc: &ComputePipelineDescriptor<
1088            <Self::A as Api>::PipelineLayout,
1089            <Self::A as Api>::ShaderModule,
1090            <Self::A as Api>::PipelineCache,
1091        >,
1092    ) -> Result<<Self::A as Api>::ComputePipeline, PipelineError>;
1093    unsafe fn destroy_compute_pipeline(&self, pipeline: <Self::A as Api>::ComputePipeline);
1094
1095    #[allow(clippy::type_complexity)]
1096    unsafe fn create_ray_tracing_pipeline(
1097        &self,
1098        desc: &RayTracingPipelineDescriptor<
1099            <Self::A as Api>::PipelineLayout,
1100            <Self::A as Api>::ShaderModule,
1101            <Self::A as Api>::PipelineCache,
1102        >,
1103    ) -> Result<<Self::A as Api>::RayTracingPipeline, PipelineError>;
1104    unsafe fn destroy_ray_tracing_pipeline(&self, pipeline: <Self::A as Api>::RayTracingPipeline);
1105    /// Obtain the opaque data from each group, behaves as if group 0 is the ray generation, group 1
1106    /// is the miss shader, and group 2.. are the intersection groups.
1107    unsafe fn get_raytracing_pipeline_group_data(
1108        &self,
1109        pipeline: &<Self::A as Api>::RayTracingPipeline,
1110        groups: Range<u32>,
1111    ) -> Result<Vec<u8>, DeviceError>;
1112
1113    unsafe fn create_pipeline_cache(
1114        &self,
1115        desc: &PipelineCacheDescriptor<'_>,
1116    ) -> Result<<Self::A as Api>::PipelineCache, PipelineCacheError>;
1117    fn pipeline_cache_validation_key(&self) -> Option<[u8; 16]> {
1118        None
1119    }
1120    unsafe fn destroy_pipeline_cache(&self, cache: <Self::A as Api>::PipelineCache);
1121
1122    unsafe fn create_query_set(
1123        &self,
1124        desc: &wgt::QuerySetDescriptor<Label>,
1125    ) -> Result<<Self::A as Api>::QuerySet, DeviceError>;
1126    unsafe fn destroy_query_set(&self, set: <Self::A as Api>::QuerySet);
1127    unsafe fn create_fence(&self) -> Result<<Self::A as Api>::Fence, DeviceError>;
1128    unsafe fn destroy_fence(&self, fence: <Self::A as Api>::Fence);
1129    unsafe fn get_fence_value(
1130        &self,
1131        fence: &<Self::A as Api>::Fence,
1132    ) -> Result<FenceValue, DeviceError>;
1133
1134    /// Wait for `fence` to reach `value`.
1135    ///
1136    /// Operations like [`Queue::submit`] can accept a [`Fence`] and a
1137    /// [`FenceValue`] to store in it, so you can use this `wait` function
1138    /// to wait for a given queue submission to finish execution.
1139    ///
1140    /// The `value` argument must not exceed the highest value that an actual
1141    /// operation you have already presented to the device is going to store in
1142    /// `fence`. You cannot wait for values yet to be submitted. (This
1143    /// restriction accommodates implementations like the `vulkan` backend's
1144    /// [`FencePool`] that must allocate a distinct synchronization object for
1145    /// each fence value one is able to wait for.)
1146    ///
1147    /// Calling `wait` with a lower [`FenceValue`] than `fence`'s current value
1148    /// returns immediately.
1149    ///
1150    /// If `timeout` is not provided, the function will block indefinitely or until
1151    /// an error is encountered.
1152    ///
1153    /// Returns `Ok(true)` on success and `Ok(false)` on timeout.
1154    ///
1155    /// [`Fence`]: Api::Fence
1156    /// [`FencePool`]: vulkan/enum.Fence.html#variant.FencePool
1157    unsafe fn wait(
1158        &self,
1159        fence: &<Self::A as Api>::Fence,
1160        value: FenceValue,
1161        timeout: Option<core::time::Duration>,
1162    ) -> Result<bool, DeviceError>;
1163
1164    /// Start a graphics debugger capture.
1165    ///
1166    /// # Safety
1167    ///
1168    /// See [`wgpu::Device::start_graphics_debugger_capture`][api] for more details.
1169    ///
1170    /// [api]: ../wgpu/struct.Device.html#method.start_graphics_debugger_capture
1171    unsafe fn start_graphics_debugger_capture(&self) -> bool;
1172
1173    /// Stop a graphics debugger capture.
1174    ///
1175    /// # Safety
1176    ///
1177    /// See [`wgpu::Device::stop_graphics_debugger_capture`][api] for more details.
1178    ///
1179    /// [api]: ../wgpu/struct.Device.html#method.stop_graphics_debugger_capture
1180    unsafe fn stop_graphics_debugger_capture(&self);
1181
1182    #[allow(unused_variables)]
1183    unsafe fn pipeline_cache_get_data(
1184        &self,
1185        cache: &<Self::A as Api>::PipelineCache,
1186    ) -> Option<Vec<u8>> {
1187        None
1188    }
1189
1190    unsafe fn create_acceleration_structure(
1191        &self,
1192        desc: &AccelerationStructureDescriptor,
1193    ) -> Result<<Self::A as Api>::AccelerationStructure, DeviceError>;
1194    unsafe fn get_acceleration_structure_build_sizes(
1195        &self,
1196        desc: &GetAccelerationStructureBuildSizesDescriptor<<Self::A as Api>::Buffer>,
1197    ) -> AccelerationStructureBuildSizes;
1198    unsafe fn get_acceleration_structure_device_address(
1199        &self,
1200        acceleration_structure: &<Self::A as Api>::AccelerationStructure,
1201    ) -> wgt::BufferAddress;
1202    unsafe fn destroy_acceleration_structure(
1203        &self,
1204        acceleration_structure: <Self::A as Api>::AccelerationStructure,
1205    );
1206    fn tlas_instance_to_bytes(&self, instance: TlasInstance) -> Vec<u8>;
1207
1208    fn get_internal_counters(&self) -> wgt::HalCounters;
1209
1210    fn generate_allocator_report(&self) -> Option<wgt::AllocatorReport> {
1211        None
1212    }
1213
1214    fn check_if_oom(&self) -> Result<(), DeviceError>;
1215}
1216
1217pub trait Queue: WasmNotSendSync {
1218    type A: Api;
1219
1220    /// Submit `command_buffers` for execution on GPU.
1221    ///
1222    /// Update `fence` to `value` when the operation is complete. See
1223    /// [`Fence`] for details.
1224    ///
1225    /// All command buffers submitted to a `wgpu_hal` queue are executed in the
1226    /// order they're submitted, with each buffer able to observe the effects of
1227    /// previous buffers' execution. Specifically:
1228    ///
1229    /// - If two calls to `submit` on a single `Queue` occur in a particular
1230    ///   order (that is, they happen on the same thread, or on two threads that
1231    ///   have synchronized to establish an ordering), then the first
1232    ///   submission's commands all complete execution before any of the second
1233    ///   submission's commands begin. All results produced by one submission
1234    ///   are visible to the next.
1235    ///
1236    /// - Within a submission, command buffers execute in the order in which they
1237    ///   appear in `command_buffers`. All results produced by one buffer are
1238    ///   visible to the next.
1239    ///
1240    /// If two calls to `submit` on a single `Queue` from different threads are
1241    /// not synchronized to occur in a particular order, they must pass distinct
1242    /// [`Fence`]s. As explained in the [`Fence`] documentation, waiting for
1243    /// operations to complete is only trustworthy when operations finish in
1244    /// order of increasing fence value, but submissions from different threads
1245    /// cannot determine how to order the fence values if the submissions
1246    /// themselves are unordered. If each thread uses a separate [`Fence`], this
1247    /// problem does not arise.
1248    ///
1249    /// # Safety
1250    ///
1251    /// - Each [`CommandBuffer`][cb] in `command_buffers` must have been created
1252    ///   from a [`CommandEncoder`][ce] that was constructed from the
1253    ///   [`Device`][d] associated with this [`Queue`].
1254    ///
1255    /// - Each [`CommandBuffer`][cb] must remain alive until the submitted
1256    ///   commands have finished execution. Since command buffers must not
1257    ///   outlive their encoders, this implies that the encoders must remain
1258    ///   alive as well.
1259    ///
1260    /// - All resources used by a submitted [`CommandBuffer`][cb]
1261    ///   ([`Texture`][t]s, [`BindGroup`][bg]s, [`RenderPipeline`][rp]s, and so
1262    ///   on) must remain alive until the command buffer finishes execution.
1263    ///
1264    /// - Every [`SurfaceTexture`][st] that any command in `command_buffers`
1265    ///   writes to must appear in the `surface_textures` argument.
1266    ///
1267    /// - No [`SurfaceTexture`][st] may appear in the `surface_textures`
1268    ///   argument more than once.
1269    ///
1270    /// - Each [`SurfaceTexture`][st] in `surface_textures` must be configured
1271    ///   for use with the [`Device`][d] associated with this [`Queue`],
1272    ///   typically by calling [`Surface::configure`].
1273    ///
1274    /// - All calls to this function that include a given [`SurfaceTexture`][st]
1275    ///   in `surface_textures` must use the same [`Fence`].
1276    ///
1277    /// - The [`Fence`] passed as `signal_fence.0` must remain alive until
1278    ///   all submissions that will signal it have completed.
1279    ///
1280    /// [`Fence`]: Api::Fence
1281    /// [cb]: Api::CommandBuffer
1282    /// [ce]: Api::CommandEncoder
1283    /// [d]: Api::Device
1284    /// [t]: Api::Texture
1285    /// [bg]: Api::BindGroup
1286    /// [rp]: Api::RenderPipeline
1287    /// [st]: Api::SurfaceTexture
1288    unsafe fn submit(
1289        &self,
1290        command_buffers: &[&<Self::A as Api>::CommandBuffer],
1291        surface_textures: &[&<Self::A as Api>::SurfaceTexture],
1292        signal_fence: (&<Self::A as Api>::Fence, FenceValue),
1293    ) -> Result<(), DeviceError>;
1294    /// Present a surface texture to the screen.
1295    ///
1296    /// This consumes the surface texture, returning it to the swapchain.
1297    ///
1298    /// # Safety
1299    ///
1300    /// - `texture` must have been acquired from `surface` via
1301    ///   [`Surface::acquire_texture`] and not yet presented or discarded.
1302    /// - `surface` must be configured for use with the [`Device`][d] associated
1303    ///   with this [`Queue`].
1304    /// - `texture` must be in the "present" state. Either:
1305    ///   - It was passed in [`submit`][s]'s `surface_textures` argument
1306    ///     (which transitions it to the present state), or
1307    ///   - The caller has otherwise transitioned it (e.g. via a clear +
1308    ///     barrier to `PRESENT` for textures that were never rendered to).
1309    /// - Any command buffers that write to `texture` must have been submitted
1310    ///   via [`submit`][s] before this call. The submissions do not need to
1311    ///   have completed on the GPU; platform-level synchronization handles the
1312    ///   ordering between rendering and display.
1313    /// - Must be externally synchronized with all other queue operations
1314    ///   ([`submit`][s], [`present`][Queue::present],
1315    ///   [`wait_for_idle`][Queue::wait_for_idle]) on the same queue.
1316    ///
1317    /// [d]: Api::Device
1318    /// [s]: Queue::submit
1319    unsafe fn present(
1320        &self,
1321        surface: &<Self::A as Api>::Surface,
1322        texture: <Self::A as Api>::SurfaceTexture,
1323    ) -> Result<(), SurfaceError>;
1324    /// Block until all previously submitted work on this queue has completed,
1325    /// including any pending presentations.
1326    ///
1327    /// # Safety
1328    ///
1329    /// - Must be externally synchronized with all other queue operations
1330    ///   ([`submit`][Queue::submit], [`present`][Queue::present],
1331    ///   [`wait_for_idle`][Queue::wait_for_idle]) on the same queue.
1332    unsafe fn wait_for_idle(&self) -> Result<(), DeviceError>;
1333    unsafe fn get_timestamp_period(&self) -> f32;
1334}
1335
1336/// Encoder and allocation pool for `CommandBuffer`s.
1337///
1338/// A `CommandEncoder` not only constructs `CommandBuffer`s but also
1339/// acts as the allocation pool that owns the buffers' underlying
1340/// storage. Thus, `CommandBuffer`s must not outlive the
1341/// `CommandEncoder` that created them.
1342///
1343/// The life cycle of a `CommandBuffer` is as follows:
1344///
1345/// - Call [`Device::create_command_encoder`] to create a new
1346///   `CommandEncoder`, in the "closed" state.
1347///
1348/// - Call `begin_encoding` on a closed `CommandEncoder` to begin
1349///   recording commands. This puts the `CommandEncoder` in the
1350///   "recording" state.
1351///
1352/// - Call methods like `copy_buffer_to_buffer`, `begin_render_pass`,
1353///   etc. on a "recording" `CommandEncoder` to add commands to the
1354///   list. (If an error occurs, you must call `discard_encoding`; see
1355///   below.)
1356///
1357/// - Call `end_encoding` on a recording `CommandEncoder` to close the
1358///   encoder and construct a fresh `CommandBuffer` consisting of the
1359///   list of commands recorded up to that point.
1360///
1361/// - Call `discard_encoding` on a recording `CommandEncoder` to drop
1362///   the commands recorded thus far and close the encoder. This is
1363///   the only safe thing to do on a `CommandEncoder` if an error has
1364///   occurred while recording commands.
1365///
1366/// - Call `reset_all` on a closed `CommandEncoder`, passing all the
1367///   live `CommandBuffers` built from it. All the `CommandBuffer`s
1368///   are destroyed, and their resources are freed.
1369///
1370/// # Safety
1371///
1372/// - The `CommandEncoder` must be in the states described above to
1373///   make the given calls.
1374///
1375/// - A `CommandBuffer` that has been submitted for execution on the
1376///   GPU must live until its execution is complete.
1377///
1378/// - A `CommandBuffer` must not outlive the `CommandEncoder` that
1379///   built it.
1380///
1381/// It is the user's responsibility to meet this requirements. This
1382/// allows `CommandEncoder` implementations to keep their state
1383/// tracking to a minimum.
1384pub trait CommandEncoder: WasmNotSendSync + fmt::Debug {
1385    type A: Api;
1386
1387    /// Begin encoding a new command buffer.
1388    ///
1389    /// This puts this `CommandEncoder` in the "recording" state.
1390    ///
1391    /// # Safety
1392    ///
1393    /// This `CommandEncoder` must be in the "closed" state.
1394    unsafe fn begin_encoding(&mut self, label: Label) -> Result<(), DeviceError>;
1395
1396    /// Discard the command list under construction.
1397    ///
1398    /// If an error has occurred while recording commands, this
1399    /// is the only safe thing to do with the encoder.
1400    ///
1401    /// This puts this `CommandEncoder` in the "closed" state.
1402    ///
1403    /// # Safety
1404    ///
1405    /// This `CommandEncoder` must be in the "recording" state.
1406    ///
1407    /// Callers must not assume that implementations of this
1408    /// function are idempotent, and thus should not call it
1409    /// multiple times in a row.
1410    unsafe fn discard_encoding(&mut self);
1411
1412    /// Return a fresh [`CommandBuffer`] holding the recorded commands.
1413    ///
1414    /// The returned [`CommandBuffer`] holds all the commands recorded
1415    /// on this `CommandEncoder` since the last call to
1416    /// [`begin_encoding`].
1417    ///
1418    /// This puts this `CommandEncoder` in the "closed" state.
1419    ///
1420    /// # Safety
1421    ///
1422    /// This `CommandEncoder` must be in the "recording" state.
1423    ///
1424    /// The returned [`CommandBuffer`] must not outlive this
1425    /// `CommandEncoder`. Implementations are allowed to build
1426    /// `CommandBuffer`s that depend on storage owned by this
1427    /// `CommandEncoder`.
1428    ///
1429    /// [`CommandBuffer`]: Api::CommandBuffer
1430    /// [`begin_encoding`]: CommandEncoder::begin_encoding
1431    unsafe fn end_encoding(&mut self) -> Result<<Self::A as Api>::CommandBuffer, DeviceError>;
1432
1433    /// Reclaim all resources belonging to this `CommandEncoder`.
1434    ///
1435    /// # Safety
1436    ///
1437    /// This `CommandEncoder` must be in the "closed" state.
1438    ///
1439    /// The `command_buffers` iterator must produce all the live
1440    /// [`CommandBuffer`]s built using this `CommandEncoder` --- that
1441    /// is, every extant `CommandBuffer` returned from `end_encoding`.
1442    ///
1443    /// [`CommandBuffer`]: Api::CommandBuffer
1444    unsafe fn reset_all<I>(&mut self, command_buffers: I)
1445    where
1446        I: Iterator<Item = <Self::A as Api>::CommandBuffer>;
1447
1448    unsafe fn transition_buffers<'a, T>(&mut self, barriers: T)
1449    where
1450        T: Iterator<Item = BufferBarrier<'a, <Self::A as Api>::Buffer>>;
1451
1452    unsafe fn transition_textures<'a, T>(&mut self, barriers: T)
1453    where
1454        T: Iterator<Item = TextureBarrier<'a, <Self::A as Api>::Texture>>;
1455
1456    // copy operations
1457
1458    unsafe fn clear_buffer(&mut self, buffer: &<Self::A as Api>::Buffer, range: MemoryRange);
1459
1460    unsafe fn copy_buffer_to_buffer<T>(
1461        &mut self,
1462        src: &<Self::A as Api>::Buffer,
1463        dst: &<Self::A as Api>::Buffer,
1464        regions: T,
1465    ) where
1466        T: Iterator<Item = BufferCopy>;
1467
1468    /// Copy from an external image to an internal texture.
1469    /// Works with a single array layer.
1470    /// Note: `dst` current usage has to be `wgt::TextureUses::COPY_DST`.
1471    /// Note: the copy extent is in physical size (rounded to the block size)
1472    #[cfg(webgl)]
1473    unsafe fn copy_external_image_to_texture<T>(
1474        &mut self,
1475        src: &wgt::CopyExternalImageSourceInfo,
1476        dst: &<Self::A as Api>::Texture,
1477        dst_premultiplication: bool,
1478        regions: T,
1479    ) where
1480        T: Iterator<Item = TextureCopy>;
1481
1482    /// Copy from one texture to another.
1483    /// Works with a single array layer.
1484    /// Note: `dst` current usage has to be `wgt::TextureUses::COPY_DST`.
1485    /// Note: the copy extent is in physical size (rounded to the block size)
1486    unsafe fn copy_texture_to_texture<T>(
1487        &mut self,
1488        src: &<Self::A as Api>::Texture,
1489        src_usage: wgt::TextureUses,
1490        dst: &<Self::A as Api>::Texture,
1491        regions: T,
1492    ) where
1493        T: Iterator<Item = TextureCopy>;
1494
1495    /// Copy from buffer to texture.
1496    /// Works with a single array layer.
1497    /// Note: `dst` current usage has to be `wgt::TextureUses::COPY_DST`.
1498    /// Note: the copy extent is in physical size (rounded to the block size)
1499    unsafe fn copy_buffer_to_texture<T>(
1500        &mut self,
1501        src: &<Self::A as Api>::Buffer,
1502        dst: &<Self::A as Api>::Texture,
1503        regions: T,
1504    ) where
1505        T: Iterator<Item = BufferTextureCopy>;
1506
1507    /// Copy from texture to buffer.
1508    /// Works with a single array layer.
1509    /// Note: the copy extent is in physical size (rounded to the block size)
1510    unsafe fn copy_texture_to_buffer<T>(
1511        &mut self,
1512        src: &<Self::A as Api>::Texture,
1513        src_usage: wgt::TextureUses,
1514        dst: &<Self::A as Api>::Buffer,
1515        regions: T,
1516    ) where
1517        T: Iterator<Item = BufferTextureCopy>;
1518
1519    unsafe fn copy_acceleration_structure_to_acceleration_structure(
1520        &mut self,
1521        src: &<Self::A as Api>::AccelerationStructure,
1522        dst: &<Self::A as Api>::AccelerationStructure,
1523        copy: wgt::AccelerationStructureCopy,
1524    );
1525    // pass common
1526
1527    /// Sets the bind group at `index` to `group`.
1528    ///
1529    /// If this is not the first call to `set_bind_group` within the current
1530    /// render or compute pass:
1531    ///
1532    /// - If `layout` contains `n` bind group layouts, then any previously set
1533    ///   bind groups at indices `n` or higher are cleared.
1534    ///
1535    /// - If the first `m` bind group layouts of `layout` are equal to those of
1536    ///   the previously passed layout, but no more, then any previously set
1537    ///   bind groups at indices `m` or higher are cleared.
1538    ///
1539    /// It follows from the above that passing the same layout as before doesn't
1540    /// clear any bind groups.
1541    ///
1542    /// # Safety
1543    ///
1544    /// - This [`CommandEncoder`] must be within a render or compute pass.
1545    ///
1546    /// - `index` must be the valid index of some bind group layout in `layout`.
1547    ///   Call this the "relevant bind group layout".
1548    ///
1549    /// - The layout of `group` must be equal to the relevant bind group layout.
1550    ///
1551    /// - The length of `dynamic_offsets` must match the number of buffer
1552    ///   bindings [with dynamic offsets][hdo] in the relevant bind group
1553    ///   layout.
1554    ///
1555    /// - If those buffer bindings are ordered by increasing [`binding` number]
1556    ///   and paired with elements from `dynamic_offsets`, then each offset must
1557    ///   be a valid offset for the binding's corresponding buffer in `group`.
1558    ///
1559    /// [hdo]: wgt::BindingType::Buffer::has_dynamic_offset
1560    /// [`binding` number]: wgt::BindGroupLayoutEntry::binding
1561    unsafe fn set_bind_group(
1562        &mut self,
1563        layout: &<Self::A as Api>::PipelineLayout,
1564        index: u32,
1565        group: &<Self::A as Api>::BindGroup,
1566        dynamic_offsets: &[wgt::DynamicOffset],
1567    );
1568
1569    /// Sets a range in immediate data.
1570    ///
1571    /// IMPORTANT: while the data is passed as words, the offset is in bytes!
1572    ///
1573    /// # Safety
1574    ///
1575    /// - `offset_bytes` must be a multiple of 4.
1576    /// - The range of immediates written must be valid for the pipeline layout at draw time.
1577    unsafe fn set_immediates(
1578        &mut self,
1579        layout: &<Self::A as Api>::PipelineLayout,
1580        offset_bytes: u32,
1581        data: &[u32],
1582    );
1583
1584    unsafe fn insert_debug_marker(&mut self, label: &str);
1585    unsafe fn begin_debug_marker(&mut self, group_label: &str);
1586    unsafe fn end_debug_marker(&mut self);
1587
1588    // queries
1589
1590    /// # Safety:
1591    ///
1592    /// - If `set` is an occlusion query set, it must be the same one as used in the [`RenderPassDescriptor::occlusion_query_set`] parameter.
1593    unsafe fn begin_query(&mut self, set: &<Self::A as Api>::QuerySet, index: u32);
1594    /// # Safety:
1595    ///
1596    /// - If `set` is an occlusion query set, it must be the same one as used in the [`RenderPassDescriptor::occlusion_query_set`] parameter.
1597    unsafe fn end_query(&mut self, set: &<Self::A as Api>::QuerySet, index: u32);
1598    unsafe fn write_timestamp(&mut self, set: &<Self::A as Api>::QuerySet, index: u32);
1599    unsafe fn reset_queries(&mut self, set: &<Self::A as Api>::QuerySet, range: Range<u32>);
1600    unsafe fn copy_query_results(
1601        &mut self,
1602        set: &<Self::A as Api>::QuerySet,
1603        range: Range<u32>,
1604        buffer: &<Self::A as Api>::Buffer,
1605        offset: wgt::BufferAddress,
1606        stride: wgt::BufferSize,
1607    );
1608
1609    // render passes
1610
1611    /// Begin a new render pass, clearing all active bindings.
1612    ///
1613    /// This clears any bindings established by the following calls:
1614    ///
1615    /// - [`set_bind_group`](CommandEncoder::set_bind_group)
1616    /// - [`set_immediates`](CommandEncoder::set_immediates)
1617    /// - [`begin_query`](CommandEncoder::begin_query)
1618    /// - [`set_render_pipeline`](CommandEncoder::set_render_pipeline)
1619    /// - [`set_index_buffer`](CommandEncoder::set_index_buffer)
1620    /// - [`set_vertex_buffer`](CommandEncoder::set_vertex_buffer)
1621    ///
1622    /// # Safety
1623    ///
1624    /// - All prior calls to [`begin_render_pass`] on this [`CommandEncoder`] must have been followed
1625    ///   by a call to [`end_render_pass`].
1626    ///
1627    /// - All prior calls to [`begin_compute_pass`] on this [`CommandEncoder`] must have been followed
1628    ///   by a call to [`end_compute_pass`].
1629    ///
1630    /// - All prior calls to [`begin_ray_tracing_pass`] on this [`CommandEncoder`] must have been followed
1631    ///   by a call to [`end_ray_tracing_pass`].
1632    ///
1633    /// [`begin_render_pass`]: CommandEncoder::begin_render_pass
1634    /// [`begin_compute_pass`]: CommandEncoder::begin_compute_pass
1635    /// [`begin_ray_tracing_pass`]: CommandEncoder::begin_ray_tracing_pass
1636    /// [`end_render_pass`]: CommandEncoder::end_render_pass
1637    /// [`end_compute_pass`]: CommandEncoder::end_compute_pass
1638    /// [`end_ray_tracing_pass`]: CommandEncoder::end_ray_tracing_pass
1639    unsafe fn begin_render_pass(
1640        &mut self,
1641        desc: &RenderPassDescriptor<<Self::A as Api>::QuerySet, <Self::A as Api>::TextureView>,
1642    ) -> Result<(), DeviceError>;
1643
1644    /// End the current render pass.
1645    ///
1646    /// # Safety
1647    ///
1648    /// - There must have been a prior call to [`begin_render_pass`] on this [`CommandEncoder`]
1649    ///   that has not been followed by a call to [`end_render_pass`].
1650    ///
1651    /// [`begin_render_pass`]: CommandEncoder::begin_render_pass
1652    /// [`end_render_pass`]: CommandEncoder::end_render_pass
1653    unsafe fn end_render_pass(&mut self);
1654
1655    unsafe fn set_render_pipeline(&mut self, pipeline: &<Self::A as Api>::RenderPipeline);
1656
1657    unsafe fn set_index_buffer<'a>(
1658        &mut self,
1659        binding: BufferBinding<'a, <Self::A as Api>::Buffer>,
1660        format: wgt::IndexFormat,
1661    );
1662    unsafe fn set_vertex_buffer<'a>(
1663        &mut self,
1664        index: u32,
1665        binding: BufferBinding<'a, <Self::A as Api>::Buffer>,
1666    );
1667    unsafe fn set_viewport(&mut self, rect: &Rect<f32>, depth_range: Range<f32>);
1668    unsafe fn set_scissor_rect(&mut self, rect: &Rect<u32>);
1669    unsafe fn set_stencil_reference(&mut self, value: u32);
1670    unsafe fn set_blend_constants(&mut self, color: &[f32; 4]);
1671
1672    unsafe fn draw(
1673        &mut self,
1674        first_vertex: u32,
1675        vertex_count: u32,
1676        first_instance: u32,
1677        instance_count: u32,
1678    );
1679    unsafe fn draw_indexed(
1680        &mut self,
1681        first_index: u32,
1682        index_count: u32,
1683        base_vertex: i32,
1684        first_instance: u32,
1685        instance_count: u32,
1686    );
1687    unsafe fn draw_indirect(
1688        &mut self,
1689        buffer: &<Self::A as Api>::Buffer,
1690        offset: wgt::BufferAddress,
1691        draw_count: u32,
1692    );
1693    unsafe fn draw_indexed_indirect(
1694        &mut self,
1695        buffer: &<Self::A as Api>::Buffer,
1696        offset: wgt::BufferAddress,
1697        draw_count: u32,
1698    );
1699    unsafe fn draw_indirect_count(
1700        &mut self,
1701        buffer: &<Self::A as Api>::Buffer,
1702        offset: wgt::BufferAddress,
1703        count_buffer: &<Self::A as Api>::Buffer,
1704        count_offset: wgt::BufferAddress,
1705        max_count: u32,
1706    );
1707    unsafe fn draw_indexed_indirect_count(
1708        &mut self,
1709        buffer: &<Self::A as Api>::Buffer,
1710        offset: wgt::BufferAddress,
1711        count_buffer: &<Self::A as Api>::Buffer,
1712        count_offset: wgt::BufferAddress,
1713        max_count: u32,
1714    );
1715    unsafe fn draw_mesh_tasks(
1716        &mut self,
1717        group_count_x: u32,
1718        group_count_y: u32,
1719        group_count_z: u32,
1720    );
1721    unsafe fn draw_mesh_tasks_indirect(
1722        &mut self,
1723        buffer: &<Self::A as Api>::Buffer,
1724        offset: wgt::BufferAddress,
1725        draw_count: u32,
1726    );
1727    unsafe fn draw_mesh_tasks_indirect_count(
1728        &mut self,
1729        buffer: &<Self::A as Api>::Buffer,
1730        offset: wgt::BufferAddress,
1731        count_buffer: &<Self::A as Api>::Buffer,
1732        count_offset: wgt::BufferAddress,
1733        max_count: u32,
1734    );
1735
1736    // compute passes
1737
1738    /// Begin a new compute pass, clearing all active bindings.
1739    ///
1740    /// This clears any bindings established by the following calls:
1741    ///
1742    /// - [`set_bind_group`](CommandEncoder::set_bind_group)
1743    /// - [`set_immediates`](CommandEncoder::set_immediates)
1744    /// - [`begin_query`](CommandEncoder::begin_query)
1745    /// - [`set_compute_pipeline`](CommandEncoder::set_compute_pipeline)
1746    ///
1747    /// # Safety
1748    ///
1749    /// - All prior calls to [`begin_render_pass`] on this [`CommandEncoder`] must have been followed
1750    ///   by a call to [`end_render_pass`].
1751    ///
1752    /// - All prior calls to [`begin_compute_pass`] on this [`CommandEncoder`] must have been followed
1753    ///   by a call to [`end_compute_pass`].
1754    ///
1755    /// - All prior calls to [`begin_ray_tracing_pass`] on this [`CommandEncoder`] must have been followed
1756    ///   by a call to [`end_ray_tracing_pass`].
1757    ///
1758    /// [`begin_render_pass`]: CommandEncoder::begin_render_pass
1759    /// [`begin_compute_pass`]: CommandEncoder::begin_compute_pass
1760    /// [`begin_ray_tracing_pass`]: CommandEncoder::begin_ray_tracing_pass
1761    /// [`end_render_pass`]: CommandEncoder::end_render_pass
1762    /// [`end_compute_pass`]: CommandEncoder::end_compute_pass
1763    /// [`end_ray_tracing_pass`]: CommandEncoder::end_ray_tracing_pass
1764    unsafe fn begin_compute_pass(
1765        &mut self,
1766        desc: &ComputePassDescriptor<<Self::A as Api>::QuerySet>,
1767    );
1768
1769    /// End the current compute pass.
1770    ///
1771    /// # Safety
1772    ///
1773    /// - There must have been a prior call to [`begin_compute_pass`] on this [`CommandEncoder`]
1774    ///   that has not been followed by a call to [`end_compute_pass`].
1775    ///
1776    /// [`begin_compute_pass`]: CommandEncoder::begin_compute_pass
1777    /// [`end_compute_pass`]: CommandEncoder::end_compute_pass
1778    unsafe fn end_compute_pass(&mut self);
1779
1780    unsafe fn set_compute_pipeline(&mut self, pipeline: &<Self::A as Api>::ComputePipeline);
1781
1782    unsafe fn dispatch_workgroups(&mut self, count: [u32; 3]);
1783    unsafe fn dispatch_workgroups_indirect(
1784        &mut self,
1785        buffer: &<Self::A as Api>::Buffer,
1786        offset: wgt::BufferAddress,
1787    );
1788
1789    /// Begin a new ray tracing pass, clearing all active bindings.
1790    ///
1791    /// This clears any bindings established by the following calls:
1792    ///
1793    /// - [`set_bind_group`](CommandEncoder::set_bind_group)
1794    /// - [`set_immediates`](CommandEncoder::set_immediates)
1795    /// - [`begin_query`](CommandEncoder::begin_query)
1796    /// - [`set_ray_tracing_pipeline`](CommandEncoder::set_compute_pipeline)
1797    ///
1798    /// # Safety
1799    ///
1800    /// - All prior calls to [`begin_render_pass`] on this [`CommandEncoder`] must have been followed
1801    ///   by a call to [`end_render_pass`].
1802    ///
1803    /// - All prior calls to [`begin_compute_pass`] on this [`CommandEncoder`] must have been followed
1804    ///   by a call to [`end_compute_pass`].
1805    ///
1806    /// - All prior calls to [`begin_ray_tracing_pass`] on this [`CommandEncoder`] must have been followed
1807    ///   by a call to [`end_ray_tracing_pass`].
1808    ///
1809    /// [`begin_render_pass`]: CommandEncoder::begin_render_pass
1810    /// [`begin_compute_pass`]: CommandEncoder::begin_compute_pass
1811    /// [`begin_ray_tracing_pass`]: CommandEncoder::begin_ray_tracing_pass
1812    /// [`end_render_pass`]: CommandEncoder::end_render_pass
1813    /// [`end_compute_pass`]: CommandEncoder::end_compute_pass
1814    /// [`end_ray_tracing_pass`]: CommandEncoder::end_ray_tracing_pass
1815    unsafe fn begin_ray_tracing_pass(&mut self, desc: &RayTracingPassDescriptor);
1816
1817    /// End the current compute pass.
1818    ///
1819    /// # Safety
1820    ///
1821    /// - There must have been a prior call to [`begin_ray_tracing_pass`] on this [`CommandEncoder`]
1822    ///   that has not been followed by a call to [`end_ray_tracing_pass`].
1823    ///
1824    /// [`begin_ray_tracing_pass`]: CommandEncoder::begin_ray_tracing_pass
1825    /// [`end_ray_tracing_pass`]: CommandEncoder::end_ray_tracing_pass
1826    unsafe fn end_ray_tracing_pass(&mut self);
1827
1828    /// # Safety
1829    ///
1830    /// - Pipeline must not be destroyed
1831    unsafe fn set_ray_tracing_pipeline(&mut self, pipeline: &<Self::A as Api>::RayTracingPipeline);
1832
1833    unsafe fn trace_rays<'a>(
1834        &mut self,
1835        count: [u32; 3],
1836        ray_generation_group_data: PipelineGroupData<'a, <Self::A as Api>::Buffer>,
1837        miss_group_data: PipelineGroupData<'a, <Self::A as Api>::Buffer>,
1838        intersection_group_data: PipelineGroupData<'a, <Self::A as Api>::Buffer>,
1839    );
1840
1841    /// To get the required sizes for the buffer allocations use `get_acceleration_structure_build_sizes` per descriptor
1842    /// All buffers must be synchronized externally
1843    /// All buffer regions, which are written to may only be passed once per function call,
1844    /// with the exception of updates in the same descriptor.
1845    /// Consequences of this limitation:
1846    /// - scratch buffers need to be unique
1847    /// - a tlas can't be build in the same call with a blas it contains
1848    unsafe fn build_acceleration_structures<'a, T>(
1849        &mut self,
1850        descriptor_count: u32,
1851        descriptors: T,
1852    ) where
1853        Self::A: 'a,
1854        T: IntoIterator<
1855            Item = BuildAccelerationStructureDescriptor<
1856                'a,
1857                <Self::A as Api>::Buffer,
1858                <Self::A as Api>::AccelerationStructure,
1859            >,
1860        >;
1861    unsafe fn place_acceleration_structure_barrier(
1862        &mut self,
1863        barrier: AccelerationStructureBarrier,
1864    );
1865    // modeled off dx12, because this is able to be polyfilled in vulkan as opposed to the other way round
1866    unsafe fn read_acceleration_structure_compact_size(
1867        &mut self,
1868        acceleration_structure: &<Self::A as Api>::AccelerationStructure,
1869        buf: &<Self::A as Api>::Buffer,
1870    );
1871    unsafe fn set_acceleration_structure_dependencies(
1872        command_buffers: &[&<Self::A as Api>::CommandBuffer],
1873        dependencies: &[&<Self::A as Api>::AccelerationStructure],
1874    );
1875}
1876
1877bitflags!(
1878    /// Pipeline layout creation flags.
1879    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1880    pub struct PipelineLayoutFlags: u32 {
1881        /// D3D12: Add support for `first_vertex` and `first_instance` builtins
1882        /// via immediates for direct execution.
1883        const FIRST_VERTEX_INSTANCE = 1 << 0;
1884        /// D3D12: Add support for `num_workgroups` builtins via immediates
1885        /// for direct execution.
1886        const NUM_WORK_GROUPS = 1 << 1;
1887        /// D3D12: Add support for the builtins that the other flags enable for
1888        /// indirect execution.
1889        const INDIRECT_BUILTIN_UPDATE = 1 << 2;
1890    }
1891);
1892
1893bitflags!(
1894    /// Pipeline layout creation flags.
1895    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1896    pub struct BindGroupLayoutFlags: u32 {
1897        /// Allows for bind group binding arrays to be shorter than the array in the BGL.
1898        const PARTIALLY_BOUND = 1 << 0;
1899    }
1900);
1901
1902bitflags!(
1903    /// Texture format capability flags.
1904    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1905    pub struct TextureFormatCapabilities: u32 {
1906        /// Format can be sampled.
1907        const SAMPLED = 1 << 0;
1908        /// Format can be sampled with a linear sampler.
1909        const SAMPLED_LINEAR = 1 << 1;
1910        /// Format can be sampled with a min/max reduction sampler.
1911        const SAMPLED_MINMAX = 1 << 2;
1912
1913        /// Format can be used as storage with read-only access.
1914        const STORAGE_READ_ONLY = 1 << 3;
1915        /// Format can be used as storage with write-only access.
1916        const STORAGE_WRITE_ONLY = 1 << 4;
1917        /// Format can be used as storage with both read and write access.
1918        const STORAGE_READ_WRITE = 1 << 5;
1919        /// Format can be used as storage with atomics.
1920        const STORAGE_ATOMIC = 1 << 6;
1921
1922        /// Format can be used as color and input attachment.
1923        const COLOR_ATTACHMENT = 1 << 7;
1924        /// Format can be used as color (with blending) and input attachment.
1925        const COLOR_ATTACHMENT_BLEND = 1 << 8;
1926        /// Format can be used as depth-stencil and input attachment.
1927        const DEPTH_STENCIL_ATTACHMENT = 1 << 9;
1928
1929        /// Format can be multisampled by x2.
1930        const MULTISAMPLE_X2   = 1 << 10;
1931        /// Format can be multisampled by x4.
1932        const MULTISAMPLE_X4   = 1 << 11;
1933        /// Format can be multisampled by x8.
1934        const MULTISAMPLE_X8   = 1 << 12;
1935        /// Format can be multisampled by x16.
1936        const MULTISAMPLE_X16  = 1 << 13;
1937
1938        /// Format can be used for render pass resolve targets.
1939        const MULTISAMPLE_RESOLVE = 1 << 14;
1940
1941        /// Format can be copied from.
1942        const COPY_SRC = 1 << 15;
1943        /// Format can be copied to.
1944        const COPY_DST = 1 << 16;
1945    }
1946);
1947
1948bitflags!(
1949    /// Texture format capability flags.
1950    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1951    pub struct FormatAspects: u8 {
1952        const COLOR = 1 << 0;
1953        const DEPTH = 1 << 1;
1954        const STENCIL = 1 << 2;
1955        const PLANE_0 = 1 << 3;
1956        const PLANE_1 = 1 << 4;
1957        const PLANE_2 = 1 << 5;
1958
1959        const DEPTH_STENCIL = Self::DEPTH.bits() | Self::STENCIL.bits();
1960    }
1961);
1962
1963impl FormatAspects {
1964    pub fn new(format: wgt::TextureFormat, aspect: wgt::TextureAspect) -> Self {
1965        let aspect_mask = match aspect {
1966            wgt::TextureAspect::All => Self::all(),
1967            wgt::TextureAspect::DepthOnly => Self::DEPTH,
1968            wgt::TextureAspect::StencilOnly => Self::STENCIL,
1969            wgt::TextureAspect::Plane0 => Self::PLANE_0,
1970            wgt::TextureAspect::Plane1 => Self::PLANE_1,
1971            wgt::TextureAspect::Plane2 => Self::PLANE_2,
1972        };
1973        Self::from(format) & aspect_mask
1974    }
1975
1976    /// Returns `true` if only one flag is set
1977    pub fn is_one(&self) -> bool {
1978        self.bits().is_power_of_two()
1979    }
1980
1981    pub fn map(&self) -> wgt::TextureAspect {
1982        match *self {
1983            Self::COLOR => wgt::TextureAspect::All,
1984            Self::DEPTH => wgt::TextureAspect::DepthOnly,
1985            Self::STENCIL => wgt::TextureAspect::StencilOnly,
1986            Self::PLANE_0 => wgt::TextureAspect::Plane0,
1987            Self::PLANE_1 => wgt::TextureAspect::Plane1,
1988            Self::PLANE_2 => wgt::TextureAspect::Plane2,
1989            _ => unreachable!(),
1990        }
1991    }
1992}
1993
1994impl From<wgt::TextureFormat> for FormatAspects {
1995    fn from(format: wgt::TextureFormat) -> Self {
1996        match format {
1997            wgt::TextureFormat::Stencil8 => Self::STENCIL,
1998            wgt::TextureFormat::Depth16Unorm
1999            | wgt::TextureFormat::Depth32Float
2000            | wgt::TextureFormat::Depth24Plus => Self::DEPTH,
2001            wgt::TextureFormat::Depth32FloatStencil8 | wgt::TextureFormat::Depth24PlusStencil8 => {
2002                Self::DEPTH_STENCIL
2003            }
2004            wgt::TextureFormat::NV12 | wgt::TextureFormat::P010 => Self::PLANE_0 | Self::PLANE_1,
2005            _ => Self::COLOR,
2006        }
2007    }
2008}
2009
2010bitflags!(
2011    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
2012    pub struct MemoryFlags: u32 {
2013        const TRANSIENT = 1 << 0;
2014        const PREFER_COHERENT = 1 << 1;
2015    }
2016);
2017
2018bitflags!(
2019    /// Attachment load and store operations.
2020    ///
2021    /// There must be at least one flag from the LOAD group and one from the STORE group set.
2022    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
2023    pub struct AttachmentOps: u8 {
2024        /// Load the existing contents of the attachment.
2025        const LOAD = 1 << 0;
2026        /// Clear the attachment to a specified value.
2027        const LOAD_CLEAR = 1 << 1;
2028        /// The contents of the attachment are undefined.
2029        const LOAD_DONT_CARE = 1 << 2;
2030        /// Store the contents of the attachment.
2031        const STORE = 1 << 3;
2032        /// The contents of the attachment are undefined after the pass.
2033        const STORE_DISCARD = 1 << 4;
2034    }
2035);
2036
2037#[derive(Debug)]
2038pub struct InstanceDescriptor<'a> {
2039    pub name: &'a str,
2040    pub flags: wgt::InstanceFlags,
2041    pub memory_budget_thresholds: wgt::MemoryBudgetThresholds,
2042    pub backend_options: wgt::BackendOptions,
2043    pub telemetry: Option<Telemetry>,
2044    /// This is a borrow because the surrounding `core::Instance` keeps the owned display handle
2045    /// alive already.
2046    pub display: Option<DisplayHandle<'a>>,
2047}
2048
2049#[derive(Clone, Debug)]
2050pub struct Alignments {
2051    /// The alignment of the start of the buffer used as a GPU copy source.
2052    pub buffer_copy_offset: wgt::BufferSize,
2053
2054    /// The alignment of the row pitch of the texture data stored in a buffer that is
2055    /// used in a GPU copy operation.
2056    pub buffer_copy_pitch: wgt::BufferSize,
2057
2058    /// The finest alignment of bound range checking for uniform buffers.
2059    ///
2060    /// When `wgpu_hal` restricts shader references to the [accessible
2061    /// region][ar] of a [`Uniform`] buffer, the size of the accessible region
2062    /// is the bind group binding's stated [size], rounded up to the next
2063    /// multiple of this value.
2064    ///
2065    /// We don't need an analogous field for storage buffer bindings, because
2066    /// all our backends promise to enforce the size at least to a four-byte
2067    /// alignment, and `wgpu_hal` requires bound range lengths to be a multiple
2068    /// of four anyway.
2069    ///
2070    /// [ar]: struct.BufferBinding.html#accessible-region
2071    /// [`Uniform`]: wgt::BufferBindingType::Uniform
2072    /// [size]: BufferBinding::size
2073    pub uniform_bounds_check_alignment: wgt::BufferSize,
2074
2075    /// The size of the raw TLAS instance
2076    pub raw_tlas_instance_size: u32,
2077
2078    /// What the scratch buffer for building an acceleration structure must be aligned to
2079    pub ray_tracing_scratch_buffer_alignment: u32,
2080
2081    /// How large a single piece of group data is. That is, how large the vector returned
2082    /// from `device.get_raytracing_pipeline_group_data(&pipeline, n..(n+1))` is.
2083    ///
2084    /// If ray tracing pipelines are implemented, this must be non zero.
2085    pub ray_tracing_pipeline_group_data_size: u32,
2086
2087    /// If ray tracing pipelines are implemented, this must be a power of two (and non zero).
2088    pub ray_tracing_pipeline_group_data_alignment: u32,
2089
2090    /// If ray tracing pipelines are implemented, this must be a power of two (and non zero).
2091    ///
2092    /// The offset within `PipelineGroupData` must be a multiple of this
2093    pub ray_tracing_pipeline_data_offset_alignment: u32,
2094}
2095
2096#[derive(Clone, Debug)]
2097pub struct Capabilities {
2098    pub limits: wgt::Limits,
2099    pub alignments: Alignments,
2100    pub downlevel: wgt::DownlevelCapabilities,
2101    /// Supported cooperative matrix configurations.
2102    ///
2103    /// Empty if cooperative matrices are not supported.
2104    pub cooperative_matrix_properties: Vec<wgt::CooperativeMatrixProperties>,
2105}
2106
2107/// An adapter with all the information needed to reason about its capabilities.
2108///
2109/// These are either made by [`Instance::enumerate_adapters`] or by backend specific
2110/// methods on the backend [`Instance`] or [`Adapter`].
2111#[derive(Debug)]
2112pub struct ExposedAdapter<A: Api> {
2113    pub adapter: A::Adapter,
2114    pub info: wgt::AdapterInfo,
2115    pub features: wgt::Features,
2116    pub capabilities: Capabilities,
2117}
2118
2119/// Describes information about what a `Surface`'s presentation capabilities are.
2120/// Fetch this with [Adapter::surface_capabilities].
2121#[derive(Debug, Clone)]
2122pub struct SurfaceCapabilities {
2123    /// List of supported texture formats together with the color spaces
2124    /// supported for each format.
2125    ///
2126    /// Must be at least one. At most one entry per format, each with a
2127    /// non-empty set of color spaces.
2128    pub formats: Vec<wgt::SurfaceFormatCapabilities>,
2129
2130    /// Range for the number of queued frames.
2131    ///
2132    /// This adjusts either the swapchain frame count to value + 1 - or sets SetMaximumFrameLatency to the value given,
2133    /// 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.
2134    ///
2135    /// - `maximum_frame_latency.start` must be at least 1.
2136    /// - `maximum_frame_latency.end` must be larger or equal to `maximum_frame_latency.start`.
2137    pub maximum_frame_latency: RangeInclusive<u32>,
2138
2139    /// Current extent of the surface, if known.
2140    pub current_extent: Option<wgt::Extent3d>,
2141
2142    /// Supported texture usage flags.
2143    ///
2144    /// Must have at least `wgt::TextureUses::COLOR_TARGET`
2145    pub usage: wgt::TextureUses,
2146
2147    /// List of supported V-sync modes.
2148    ///
2149    /// Must be at least one.
2150    pub present_modes: Vec<wgt::PresentMode>,
2151
2152    /// List of supported alpha composition modes.
2153    ///
2154    /// Must be at least one.
2155    pub composite_alpha_modes: Vec<wgt::CompositeAlphaMode>,
2156}
2157
2158impl SurfaceCapabilities {
2159    /// Returns the supported texture formats, dropping the per-format color-space
2160    /// information carried in [`Self::formats`].
2161    pub fn texture_formats(&self) -> impl Iterator<Item = wgt::TextureFormat> + '_ {
2162        self.formats.iter().map(|fc| fc.format)
2163    }
2164}
2165
2166#[derive(Debug)]
2167pub struct AcquiredSurfaceTexture<A: Api> {
2168    pub texture: A::SurfaceTexture,
2169    /// The presentation configuration no longer matches
2170    /// the surface properties exactly, but can still be used to present
2171    /// to the surface successfully.
2172    pub suboptimal: bool,
2173}
2174
2175/// An open connection to a device and a queue.
2176///
2177/// This can be created from [`Adapter::open`] or backend
2178/// specific methods on the backend's [`Instance`] or [`Adapter`].
2179#[derive(Debug)]
2180pub struct OpenDevice<A: Api> {
2181    pub device: A::Device,
2182    pub queue: A::Queue,
2183}
2184
2185#[derive(Clone, Debug)]
2186pub struct BufferMapping {
2187    pub ptr: NonNull<u8>,
2188    pub is_coherent: bool,
2189}
2190
2191#[derive(Clone, Debug)]
2192pub struct BufferDescriptor<'a> {
2193    pub label: Label<'a>,
2194    pub size: wgt::BufferAddress,
2195    pub usage: wgt::BufferUses,
2196    pub memory_flags: MemoryFlags,
2197}
2198
2199#[derive(Clone, Debug)]
2200pub struct TextureDescriptor<'a> {
2201    pub label: Label<'a>,
2202    pub size: wgt::Extent3d,
2203    pub mip_level_count: u32,
2204    pub sample_count: u32,
2205    pub dimension: wgt::TextureDimension,
2206    pub format: wgt::TextureFormat,
2207    pub usage: wgt::TextureUses,
2208    pub memory_flags: MemoryFlags,
2209    /// Allows views of this texture to have a different format
2210    /// than the texture does.
2211    pub view_formats: Vec<wgt::TextureFormat>,
2212}
2213
2214impl TextureDescriptor<'_> {
2215    pub fn copy_extent(&self) -> CopyExtent {
2216        CopyExtent::map_extent_to_copy_size(&self.size, self.dimension)
2217    }
2218
2219    pub fn is_cube_compatible(&self) -> bool {
2220        self.dimension == wgt::TextureDimension::D2
2221            && self.size.depth_or_array_layers.is_multiple_of(6)
2222            && self.sample_count == 1
2223            && self.size.width == self.size.height
2224    }
2225
2226    pub fn array_layer_count(&self) -> u32 {
2227        match self.dimension {
2228            wgt::TextureDimension::D1 | wgt::TextureDimension::D3 => 1,
2229            wgt::TextureDimension::D2 => self.size.depth_or_array_layers,
2230        }
2231    }
2232}
2233
2234/// TextureView descriptor.
2235///
2236/// Valid usage:
2237///. - `format` has to be the same as `TextureDescriptor::format`
2238///. - `dimension` has to be compatible with `TextureDescriptor::dimension`
2239///. - `usage` has to be a subset of `TextureDescriptor::usage`
2240///. - `range` has to be a subset of parent texture
2241#[derive(Clone, Debug)]
2242pub struct TextureViewDescriptor<'a> {
2243    pub label: Label<'a>,
2244    pub format: wgt::TextureFormat,
2245    pub dimension: wgt::TextureViewDimension,
2246    pub usage: wgt::TextureUses,
2247    pub range: wgt::ImageSubresourceRange,
2248}
2249
2250#[derive(Clone, Debug)]
2251pub struct SamplerDescriptor<'a> {
2252    pub label: Label<'a>,
2253    pub address_modes: [wgt::AddressMode; 3],
2254    pub mag_filter: wgt::FilterMode,
2255    pub min_filter: wgt::FilterMode,
2256    pub mipmap_filter: wgt::MipmapFilterMode,
2257    pub lod_clamp: Range<f32>,
2258    pub compare: Option<wgt::CompareFunction>,
2259    // Must in the range [1, 16].
2260    //
2261    // Anisotropic filtering must be supported if this is not 1.
2262    pub anisotropy_clamp: u16,
2263    pub border_color: Option<wgt::SamplerBorderColor>,
2264}
2265
2266/// BindGroupLayout descriptor.
2267///
2268/// Valid usage:
2269/// - `entries` are sorted by ascending `wgt::BindGroupLayoutEntry::binding`
2270#[derive(Clone, Debug)]
2271pub struct BindGroupLayoutDescriptor<'a> {
2272    pub label: Label<'a>,
2273    pub flags: BindGroupLayoutFlags,
2274    pub entries: &'a [wgt::BindGroupLayoutEntry],
2275}
2276
2277#[derive(Clone, Debug)]
2278pub struct PipelineLayoutDescriptor<'a, B: DynBindGroupLayout + ?Sized> {
2279    pub label: Label<'a>,
2280    pub flags: PipelineLayoutFlags,
2281    pub bind_group_layouts: &'a [Option<&'a B>],
2282    pub immediate_size: u32,
2283}
2284
2285/// A region of a buffer made visible to shaders via a [`BindGroup`].
2286///
2287/// [`BindGroup`]: Api::BindGroup
2288///
2289/// ## Construction
2290///
2291/// The recommended way to construct a `BufferBinding` is using the `binding`
2292/// method on a wgpu-core `Buffer`, which will validate the binding size
2293/// against the buffer size. A `new_unchecked` constructor is also provided for
2294/// cases where direct construction is necessary.
2295///
2296/// ## Accessible region
2297///
2298/// `wgpu_hal` guarantees that shaders compiled with
2299/// [`ShaderModuleDescriptor::runtime_checks`] set to `true` cannot read or
2300/// write data via this binding outside the *accessible region* of a buffer:
2301///
2302/// - The accessible region starts at [`offset`].
2303///
2304/// - For [`Storage`] bindings, the size of the accessible region is [`size`],
2305///   which must be a multiple of 4.
2306///
2307/// - For [`Uniform`] bindings, the size of the accessible region is [`size`]
2308///   rounded up to the next multiple of
2309///   [`Alignments::uniform_bounds_check_alignment`].
2310///
2311/// Note that this guarantee is stricter than WGSL's requirements for
2312/// [out-of-bounds accesses][woob], as WGSL allows them to return values from
2313/// elsewhere in the buffer. But this guarantee is necessary anyway, to permit
2314/// `wgpu-core` to avoid clearing uninitialized regions of buffers that will
2315/// never be read by the application before they are overwritten. This
2316/// optimization consults bind group buffer binding regions to determine which
2317/// parts of which buffers shaders might observe. This optimization is only
2318/// sound if shader access is bounds-checked.
2319///
2320/// ## Zero-length bindings
2321///
2322/// Some back ends cannot tolerate zero-length regions; for example, see
2323/// [VUID-VkDescriptorBufferInfo-offset-00340][340] and
2324/// [VUID-VkDescriptorBufferInfo-range-00341][341], or the
2325/// documentation for GLES's [glBindBufferRange][bbr]. This documentation
2326/// previously stated that a `BufferBinding` must have `offset` strictly less
2327/// than the size of the buffer, but this restriction was not honored elsewhere
2328/// in the code, so has been removed. However, it remains the case that
2329/// some backends do not support zero-length bindings, so additional
2330/// logic is needed somewhere to handle this properly. See
2331/// [#3170](https://github.com/gfx-rs/wgpu/issues/3170).
2332///
2333/// [`offset`]: BufferBinding::offset
2334/// [`size`]: BufferBinding::size
2335/// [`Storage`]: wgt::BufferBindingType::Storage
2336/// [`Uniform`]: wgt::BufferBindingType::Uniform
2337/// [340]: https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-VkDescriptorBufferInfo-offset-00340
2338/// [341]: https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-VkDescriptorBufferInfo-range-00341
2339/// [bbr]: https://registry.khronos.org/OpenGL-Refpages/es3.0/html/glBindBufferRange.xhtml
2340/// [woob]: https://gpuweb.github.io/gpuweb/wgsl/#out-of-bounds-access-sec
2341#[derive(Debug)]
2342pub struct BufferBinding<'a, B: DynBuffer + ?Sized> {
2343    /// The buffer being bound.
2344    ///
2345    /// This is not fully `pub` to prevent direct construction of
2346    /// `BufferBinding`s, while still allowing public read access to the `offset`
2347    /// and `size` properties.
2348    pub(crate) buffer: &'a B,
2349
2350    /// The offset at which the bound region starts.
2351    ///
2352    /// This must be less or equal to the size of the buffer.
2353    pub offset: wgt::BufferAddress,
2354
2355    /// The size of the region bound, in bytes.
2356    ///
2357    /// If `None`, the region extends from `offset` to the end of the
2358    /// buffer. Given the restrictions on `offset`, this means that
2359    /// the size is always greater than zero.
2360    pub size: Option<wgt::BufferSize>,
2361}
2362
2363// We must implement this manually because `B` is not necessarily `Clone`.
2364impl<B: DynBuffer + ?Sized> Clone for BufferBinding<'_, B> {
2365    fn clone(&self) -> Self {
2366        BufferBinding {
2367            buffer: self.buffer,
2368            offset: self.offset,
2369            size: self.size,
2370        }
2371    }
2372}
2373
2374/// Temporary convenience trait to let us call `.get()` on `u64`s in code that
2375/// really wants to be using `NonZeroU64`.
2376/// TODO(<https://github.com/gfx-rs/wgpu/issues/3170>): remove this
2377pub trait ShouldBeNonZeroExt {
2378    fn get(&self) -> u64;
2379}
2380
2381impl ShouldBeNonZeroExt for NonZeroU64 {
2382    fn get(&self) -> u64 {
2383        NonZeroU64::get(*self)
2384    }
2385}
2386
2387impl ShouldBeNonZeroExt for u64 {
2388    fn get(&self) -> u64 {
2389        *self
2390    }
2391}
2392
2393impl ShouldBeNonZeroExt for Option<NonZeroU64> {
2394    fn get(&self) -> u64 {
2395        match *self {
2396            Some(non_zero) => non_zero.get(),
2397            None => 0,
2398        }
2399    }
2400}
2401
2402impl<'a, B: DynBuffer + ?Sized> BufferBinding<'a, B> {
2403    /// Construct a `BufferBinding` with the given contents.
2404    ///
2405    /// When possible, use the `binding` method on a wgpu-core `Buffer` instead
2406    /// of this method. `Buffer::binding` validates the size of the binding
2407    /// against the size of the buffer.
2408    ///
2409    /// It is more difficult to provide a validating constructor here, due to
2410    /// not having direct access to the size of a `DynBuffer`.
2411    ///
2412    /// SAFETY: The caller is responsible for ensuring that a binding of `size`
2413    /// bytes starting at `offset` is contained within the buffer.
2414    ///
2415    /// The `S` type parameter is a temporary convenience to allow callers to
2416    /// pass a zero size. When the zero-size binding issue is resolved, the
2417    /// argument should just match the type of the member.
2418    /// TODO(<https://github.com/gfx-rs/wgpu/issues/3170>): remove the parameter
2419    pub fn new_unchecked<S: Into<Option<NonZeroU64>>>(
2420        buffer: &'a B,
2421        offset: wgt::BufferAddress,
2422        size: S,
2423    ) -> Self {
2424        Self {
2425            buffer,
2426            offset,
2427            size: size.into(),
2428        }
2429    }
2430}
2431
2432#[derive(Debug)]
2433pub struct TextureBinding<'a, T: DynTextureView + ?Sized> {
2434    pub view: &'a T,
2435    pub usage: wgt::TextureUses,
2436}
2437
2438impl<'a, T: DynTextureView + ?Sized> Clone for TextureBinding<'a, T> {
2439    fn clone(&self) -> Self {
2440        TextureBinding {
2441            view: self.view,
2442            usage: self.usage,
2443        }
2444    }
2445}
2446
2447#[derive(Debug)]
2448pub struct ExternalTextureBinding<'a, B: DynBuffer + ?Sized, T: DynTextureView + ?Sized> {
2449    pub planes: [TextureBinding<'a, T>; 3],
2450    pub params: BufferBinding<'a, B>,
2451}
2452
2453impl<'a, B: DynBuffer + ?Sized, T: DynTextureView + ?Sized> Clone
2454    for ExternalTextureBinding<'a, B, T>
2455{
2456    fn clone(&self) -> Self {
2457        ExternalTextureBinding {
2458            planes: self.planes.clone(),
2459            params: self.params.clone(),
2460        }
2461    }
2462}
2463
2464/// cbindgen:ignore
2465#[derive(Clone, Debug)]
2466pub struct BindGroupEntry {
2467    pub binding: u32,
2468    pub resource_index: u32,
2469    pub count: u32,
2470}
2471
2472/// BindGroup descriptor.
2473///
2474/// Valid usage:
2475///. - `entries` has to be sorted by ascending `BindGroupEntry::binding`
2476///. - `entries` has to have the same set of `BindGroupEntry::binding` as `layout`
2477///. - each entry has to be compatible with the `layout`
2478///. - each entry's `BindGroupEntry::resource_index` is within range
2479///    of the corresponding resource array, selected by the relevant
2480///    `BindGroupLayoutEntry`.
2481#[derive(Clone, Debug)]
2482pub struct BindGroupDescriptor<
2483    'a,
2484    Bgl: DynBindGroupLayout + ?Sized,
2485    B: DynBuffer + ?Sized,
2486    S: DynSampler + ?Sized,
2487    T: DynTextureView + ?Sized,
2488    A: DynAccelerationStructure + ?Sized,
2489> {
2490    pub label: Label<'a>,
2491    pub layout: &'a Bgl,
2492    pub buffers: &'a [BufferBinding<'a, B>],
2493    pub samplers: &'a [&'a S],
2494    pub textures: &'a [TextureBinding<'a, T>],
2495    pub entries: &'a [BindGroupEntry],
2496    pub acceleration_structures: &'a [&'a A],
2497    pub external_textures: &'a [ExternalTextureBinding<'a, B, T>],
2498}
2499
2500#[derive(Clone, Debug)]
2501pub struct CommandEncoderDescriptor<'a, Q: DynQueue + ?Sized> {
2502    pub label: Label<'a>,
2503    pub queue: &'a Q,
2504}
2505
2506/// Naga shader module.
2507#[derive(Default)]
2508pub struct NagaShader {
2509    /// Shader module IR.
2510    pub module: Cow<'static, naga::Module>,
2511    /// Analysis information of the module.
2512    pub info: naga::valid::ModuleInfo,
2513    /// Source codes for debug
2514    pub debug_source: Option<DebugSource>,
2515}
2516
2517// Custom implementation avoids the need to generate Debug impl code
2518// for the whole Naga module and info.
2519impl fmt::Debug for NagaShader {
2520    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
2521        write!(formatter, "Naga shader")
2522    }
2523}
2524
2525/// Shader input.
2526pub enum ShaderInput<'a> {
2527    Naga(NagaShader),
2528    MetalLib {
2529        file: &'a [u8],
2530        num_workgroups: hashbrown::HashMap<String, (u32, u32, u32)>,
2531    },
2532    Msl {
2533        shader: &'a str,
2534        num_workgroups: hashbrown::HashMap<String, (u32, u32, u32)>,
2535    },
2536    SpirV(&'a [u32]),
2537    Dxil {
2538        shader: &'a [u8],
2539    },
2540    Hlsl {
2541        shader: &'a str,
2542    },
2543    Glsl {
2544        shader: &'a str,
2545    },
2546}
2547
2548impl fmt::Debug for ShaderInput<'_> {
2549    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2550        match self {
2551            // Don't include the entire shader source, especially for binary formats, because it
2552            // would be spammy.
2553            Self::Naga { .. } => f.debug_tuple("Naga").finish_non_exhaustive(),
2554            Self::MetalLib { .. } => f.debug_tuple("MetalLib").finish_non_exhaustive(),
2555            Self::Msl { .. } => f.debug_tuple("Msl").finish_non_exhaustive(),
2556            Self::SpirV { .. } => f.debug_tuple("SpirV").finish_non_exhaustive(),
2557            Self::Dxil { .. } => f.debug_tuple("Dxil").finish_non_exhaustive(),
2558            Self::Hlsl { .. } => f.debug_tuple("Hlsl").finish_non_exhaustive(),
2559            Self::Glsl { .. } => f.debug_tuple("Glsl").finish_non_exhaustive(),
2560        }
2561    }
2562}
2563
2564#[derive(Debug)]
2565pub struct ShaderModuleDescriptor<'a> {
2566    pub label: Label<'a>,
2567
2568    /// # Safety
2569    ///
2570    /// See the documentation for each flag in [`ShaderRuntimeChecks`][src].
2571    ///
2572    /// [src]: wgt::ShaderRuntimeChecks
2573    pub runtime_checks: wgt::ShaderRuntimeChecks,
2574}
2575
2576#[derive(Debug, Clone)]
2577pub struct DebugSource {
2578    pub file_name: Cow<'static, str>,
2579    pub source_code: Cow<'static, str>,
2580}
2581
2582/// Describes a programmable pipeline stage.
2583#[derive(Debug)]
2584pub struct ProgrammableStage<'a, M: DynShaderModule + ?Sized> {
2585    /// The compiled shader module for this stage.
2586    pub module: &'a M,
2587    /// The name of the entry point in the compiled shader. There must be a function with this name
2588    ///  in the shader.
2589    pub entry_point: &'a str,
2590    /// Pipeline constants
2591    pub constants: &'a naga::back::PipelineConstants,
2592    /// Whether workgroup scoped memory will be initialized with zero values for this stage.
2593    ///
2594    /// This is required by the WebGPU spec, but may have overhead which can be avoided
2595    /// for cross-platform applications
2596    pub zero_initialize_workgroup_memory: bool,
2597}
2598
2599impl<M: DynShaderModule + ?Sized> Clone for ProgrammableStage<'_, M> {
2600    fn clone(&self) -> Self {
2601        Self {
2602            module: self.module,
2603            entry_point: self.entry_point,
2604            constants: self.constants,
2605            zero_initialize_workgroup_memory: self.zero_initialize_workgroup_memory,
2606        }
2607    }
2608}
2609
2610/// Describes a compute pipeline.
2611#[derive(Clone, Debug)]
2612pub struct ComputePipelineDescriptor<
2613    'a,
2614    Pl: DynPipelineLayout + ?Sized,
2615    M: DynShaderModule + ?Sized,
2616    Pc: DynPipelineCache + ?Sized,
2617> {
2618    pub label: Label<'a>,
2619    /// The layout of bind groups for this pipeline.
2620    pub layout: &'a Pl,
2621    /// The compiled compute stage and its entry point.
2622    pub stage: ProgrammableStage<'a, M>,
2623    /// The cache which will be used and filled when compiling this pipeline
2624    pub cache: Option<&'a Pc>,
2625}
2626
2627#[derive(Debug)]
2628pub struct PipelineCacheDescriptor<'a> {
2629    pub label: Label<'a>,
2630    pub data: Option<&'a [u8]>,
2631}
2632
2633/// Describes how the vertex buffer is interpreted.
2634#[derive(Clone, Debug)]
2635pub struct VertexBufferLayout<'a> {
2636    /// The stride, in bytes, between elements of this buffer.
2637    pub array_stride: wgt::BufferAddress,
2638    /// How often this vertex buffer is "stepped" forward.
2639    pub step_mode: wgt::VertexStepMode,
2640    /// The list of attributes which comprise a single vertex.
2641    pub attributes: &'a [wgt::VertexAttribute],
2642}
2643
2644#[derive(Clone, Debug)]
2645pub enum VertexProcessor<'a, M: DynShaderModule + ?Sized> {
2646    Standard {
2647        /// The format of any vertex buffers used with this pipeline.
2648        vertex_buffers: &'a [Option<VertexBufferLayout<'a>>],
2649        /// The vertex stage for this pipeline.
2650        vertex_stage: ProgrammableStage<'a, M>,
2651    },
2652    Mesh {
2653        task_stage: Option<ProgrammableStage<'a, M>>,
2654        mesh_stage: ProgrammableStage<'a, M>,
2655    },
2656}
2657
2658/// Describes a render (graphics) pipeline.
2659#[derive(Clone, Debug)]
2660pub struct RenderPipelineDescriptor<
2661    'a,
2662    Pl: DynPipelineLayout + ?Sized,
2663    M: DynShaderModule + ?Sized,
2664    Pc: DynPipelineCache + ?Sized,
2665> {
2666    pub label: Label<'a>,
2667    /// The layout of bind groups for this pipeline.
2668    pub layout: &'a Pl,
2669    /// The vertex processing state(vertex shader + buffers or task + mesh shaders)
2670    pub vertex_processor: VertexProcessor<'a, M>,
2671    /// The properties of the pipeline at the primitive assembly and rasterization level.
2672    pub primitive: wgt::PrimitiveState,
2673    /// The effect of draw calls on the depth and stencil aspects of the output target, if any.
2674    pub depth_stencil: Option<wgt::DepthStencilState>,
2675    /// The multi-sampling properties of the pipeline.
2676    pub multisample: wgt::MultisampleState,
2677    /// The fragment stage for this pipeline.
2678    pub fragment_stage: Option<ProgrammableStage<'a, M>>,
2679    /// The effect of draw calls on the color aspect of the output target.
2680    pub color_targets: &'a [Option<wgt::ColorTargetState>],
2681    /// If the pipeline will be used with a multiview render pass, this indicates how many array
2682    /// layers the attachments will have.
2683    pub multiview_mask: Option<NonZeroU32>,
2684    /// The cache which will be used and filled when compiling this pipeline
2685    pub cache: Option<&'a Pc>,
2686}
2687
2688#[derive(Clone, Debug)]
2689pub struct RayObjectIntersectionState<'a, M: DynShaderModule + ?Sized> {
2690    pub closest_hit: ProgrammableStage<'a, M>,
2691    pub any_hit: Option<ProgrammableStage<'a, M>>,
2692}
2693
2694/// Describes a ray tracing pipeline.
2695#[derive(Clone, Debug)]
2696pub struct RayTracingPipelineDescriptor<
2697    'a,
2698    Pl: DynPipelineLayout + ?Sized,
2699    M: DynShaderModule + ?Sized,
2700    Pc: DynPipelineCache + ?Sized,
2701> {
2702    pub label: Label<'a>,
2703    /// The layout of bind groups for this pipeline.
2704    pub layout: &'a Pl,
2705    /// The ray generation stage.
2706    pub ray_generation: ProgrammableStage<'a, M>,
2707    /// The miss stage.
2708    pub miss: ProgrammableStage<'a, M>,
2709    /// All the object intersection stages.
2710    pub intersection: &'a [RayObjectIntersectionState<'a, M>],
2711    /// The maximum recursion depth allowed for the ray tracing (ray_generation shader counts as depth 0).
2712    pub max_recursion_depth: u32,
2713    /// The cache which will be used and filled when compiling this pipeline
2714    pub cache: Option<&'a Pc>,
2715}
2716
2717#[derive(Debug, Clone)]
2718pub struct SurfaceConfiguration {
2719    /// Maximum number of queued frames. Must be in
2720    /// `SurfaceCapabilities::maximum_frame_latency` range.
2721    pub maximum_frame_latency: u32,
2722    /// Vertical synchronization mode.
2723    pub present_mode: wgt::PresentMode,
2724    /// Alpha composition mode.
2725    pub composite_alpha_mode: wgt::CompositeAlphaMode,
2726    /// Format of the surface textures.
2727    pub format: wgt::TextureFormat,
2728    /// Color space in which the presentation engine interprets the surface
2729    /// textures. Never [`wgt::SurfaceColorSpace::Auto`]; `wgpu-core` resolves
2730    /// `Auto` to a concrete color space before configuring the surface, and
2731    /// the (format, color space) pair must be listed in
2732    /// `SurfaceCapabilities::formats`.
2733    pub color_space: wgt::SurfaceColorSpace,
2734    /// Requested texture extent. Must be in
2735    /// `SurfaceCapabilities::extents` range.
2736    pub extent: wgt::Extent3d,
2737    /// Allowed usage of surface textures,
2738    pub usage: wgt::TextureUses,
2739    /// Allows views of swapchain texture to have a different format
2740    /// than the texture does.
2741    pub view_formats: Vec<wgt::TextureFormat>,
2742}
2743
2744#[derive(Debug, Clone)]
2745pub struct Rect<T> {
2746    pub x: T,
2747    pub y: T,
2748    pub w: T,
2749    pub h: T,
2750}
2751
2752#[derive(Debug, Clone, PartialEq)]
2753pub struct StateTransition<T> {
2754    pub from: T,
2755    pub to: T,
2756}
2757
2758#[derive(Debug, Clone)]
2759pub struct BufferBarrier<'a, B: DynBuffer + ?Sized> {
2760    pub buffer: &'a B,
2761    pub usage: StateTransition<wgt::BufferUses>,
2762}
2763
2764#[derive(Debug, Clone)]
2765pub struct TextureBarrier<'a, T: DynTexture + ?Sized> {
2766    pub texture: &'a T,
2767    pub range: wgt::ImageSubresourceRange,
2768    pub usage: StateTransition<wgt::TextureUses>,
2769}
2770
2771#[derive(Clone, Copy, Debug)]
2772pub struct BufferCopy {
2773    pub src_offset: wgt::BufferAddress,
2774    pub dst_offset: wgt::BufferAddress,
2775    pub size: wgt::BufferSize,
2776}
2777
2778#[derive(Clone, Debug)]
2779pub struct TextureCopyBase {
2780    pub mip_level: u32,
2781    pub array_layer: u32,
2782    /// Origin within a texture.
2783    /// Note: for 1D and 2D textures, Z must be 0.
2784    pub origin: wgt::Origin3d,
2785    pub aspect: FormatAspects,
2786}
2787
2788#[derive(Clone, Copy, Debug)]
2789pub struct CopyExtent {
2790    pub width: u32,
2791    pub height: u32,
2792    pub depth: u32,
2793}
2794
2795impl From<wgt::Extent3d> for CopyExtent {
2796    fn from(value: wgt::Extent3d) -> Self {
2797        let wgt::Extent3d {
2798            width,
2799            height,
2800            depth_or_array_layers,
2801        } = value;
2802        Self {
2803            width,
2804            height,
2805            depth: depth_or_array_layers,
2806        }
2807    }
2808}
2809
2810impl From<CopyExtent> for wgt::Extent3d {
2811    fn from(value: CopyExtent) -> Self {
2812        let CopyExtent {
2813            width,
2814            height,
2815            depth,
2816        } = value;
2817        Self {
2818            width,
2819            height,
2820            depth_or_array_layers: depth,
2821        }
2822    }
2823}
2824
2825#[derive(Clone, Debug)]
2826pub struct TextureCopy {
2827    pub src_base: TextureCopyBase,
2828    pub dst_base: TextureCopyBase,
2829    pub size: CopyExtent,
2830}
2831
2832#[derive(Clone, Debug)]
2833pub struct BufferTextureCopy {
2834    pub buffer_layout: wgt::TexelCopyBufferLayout,
2835    pub texture_base: TextureCopyBase,
2836    pub size: CopyExtent,
2837}
2838
2839#[derive(Clone, Debug)]
2840pub struct Attachment<'a, T: DynTextureView + ?Sized> {
2841    pub view: &'a T,
2842    /// Contains either a single mutating usage as a target,
2843    /// or a valid combination of read-only usages.
2844    pub usage: wgt::TextureUses,
2845}
2846
2847#[derive(Clone, Debug)]
2848pub struct ColorAttachment<'a, T: DynTextureView + ?Sized> {
2849    pub target: Attachment<'a, T>,
2850    pub depth_slice: Option<u32>,
2851    pub resolve_target: Option<Attachment<'a, T>>,
2852    pub ops: AttachmentOps,
2853    pub clear_value: wgt::Color,
2854}
2855
2856#[derive(Clone, Debug)]
2857pub struct DepthStencilAttachment<'a, T: DynTextureView + ?Sized> {
2858    pub target: Attachment<'a, T>,
2859    pub depth_ops: AttachmentOps,
2860    pub stencil_ops: AttachmentOps,
2861    pub clear_value: (f32, u32),
2862}
2863
2864#[derive(Clone, Debug)]
2865pub struct PassTimestampWrites<'a, Q: DynQuerySet + ?Sized> {
2866    pub query_set: &'a Q,
2867    pub beginning_of_pass_write_index: Option<u32>,
2868    pub end_of_pass_write_index: Option<u32>,
2869}
2870
2871#[derive(Clone, Debug)]
2872pub struct RenderPassDescriptor<'a, Q: DynQuerySet + ?Sized, T: DynTextureView + ?Sized> {
2873    pub label: Label<'a>,
2874    pub extent: wgt::Extent3d,
2875    pub sample_count: u32,
2876    pub color_attachments: &'a [Option<ColorAttachment<'a, T>>],
2877    pub depth_stencil_attachment: Option<DepthStencilAttachment<'a, T>>,
2878    pub multiview_mask: Option<NonZeroU32>,
2879    pub timestamp_writes: Option<PassTimestampWrites<'a, Q>>,
2880    pub occlusion_query_set: Option<&'a Q>,
2881}
2882
2883#[derive(Clone, Debug)]
2884pub struct ComputePassDescriptor<'a, Q: DynQuerySet + ?Sized> {
2885    pub label: Label<'a>,
2886    pub timestamp_writes: Option<PassTimestampWrites<'a, Q>>,
2887}
2888
2889#[derive(Clone, Debug)]
2890pub struct RayTracingPassDescriptor<'a> {
2891    pub label: Label<'a>,
2892}
2893
2894#[test]
2895fn test_default_limits() {
2896    let limits = wgt::Limits::default();
2897    assert!(limits.max_bind_groups <= MAX_BIND_GROUPS as u32);
2898}
2899
2900#[derive(Clone, Debug)]
2901pub struct AccelerationStructureDescriptor<'a> {
2902    pub label: Label<'a>,
2903    pub size: wgt::BufferAddress,
2904    pub format: AccelerationStructureFormat,
2905    pub allow_compaction: bool,
2906}
2907
2908#[derive(Debug, Clone, Copy, Eq, PartialEq)]
2909pub enum AccelerationStructureFormat {
2910    TopLevel,
2911    BottomLevel,
2912}
2913
2914#[derive(Debug, Clone, Copy, Eq, PartialEq)]
2915pub enum AccelerationStructureBuildMode {
2916    Build,
2917    Update,
2918}
2919
2920/// Information of the required size for a corresponding entries struct (+ flags)
2921#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
2922pub struct AccelerationStructureBuildSizes {
2923    pub acceleration_structure_size: wgt::BufferAddress,
2924    pub update_scratch_size: wgt::BufferAddress,
2925    pub build_scratch_size: wgt::BufferAddress,
2926}
2927
2928/// Updates use source_acceleration_structure if present, else the update will be performed in place.
2929/// For updates, only the data is allowed to change (not the meta data or sizes).
2930#[derive(Clone, Debug)]
2931pub struct BuildAccelerationStructureDescriptor<
2932    'a,
2933    B: DynBuffer + ?Sized,
2934    A: DynAccelerationStructure + ?Sized,
2935> {
2936    pub entries: &'a AccelerationStructureEntries<'a, B>,
2937    pub mode: AccelerationStructureBuildMode,
2938    pub flags: AccelerationStructureBuildFlags,
2939    pub source_acceleration_structure: Option<&'a A>,
2940    pub destination_acceleration_structure: &'a A,
2941    pub scratch_buffer: &'a B,
2942    pub scratch_buffer_offset: wgt::BufferAddress,
2943}
2944
2945/// - All buffers, buffer addresses and offsets will be ignored.
2946/// - The build mode will be ignored.
2947/// - Reducing the amount of Instances, Triangle groups or AABB groups (or the number of Triangles/AABBs in corresponding groups),
2948///   may result in reduced size requirements.
2949/// - Any other change may result in a bigger or smaller size requirement.
2950#[derive(Clone, Debug)]
2951pub struct GetAccelerationStructureBuildSizesDescriptor<'a, B: DynBuffer + ?Sized> {
2952    pub entries: &'a AccelerationStructureEntries<'a, B>,
2953    pub flags: AccelerationStructureBuildFlags,
2954}
2955
2956/// Entries for a single descriptor
2957/// * `Instances` - Multiple instances for a top level acceleration structure
2958/// * `Triangles` - Multiple triangle meshes for a bottom level acceleration structure
2959/// * `AABBs` - List of list of axis aligned bounding boxes for a bottom level acceleration structure
2960#[derive(Debug)]
2961pub enum AccelerationStructureEntries<'a, B: DynBuffer + ?Sized> {
2962    Instances(AccelerationStructureInstances<'a, B>),
2963    Triangles(Vec<AccelerationStructureTriangles<'a, B>>),
2964    AABBs(Vec<AccelerationStructureAABBs<'a, B>>),
2965}
2966
2967/// * `first_vertex` - offset in the vertex buffer (as number of vertices)
2968/// * `indices` - optional index buffer with attributes
2969/// * `transform` - optional transform
2970#[derive(Clone, Debug)]
2971pub struct AccelerationStructureTriangles<'a, B: DynBuffer + ?Sized> {
2972    pub vertex_buffer: Option<&'a B>,
2973    pub vertex_format: wgt::VertexFormat,
2974    pub first_vertex: u32,
2975    pub vertex_count: u32,
2976    pub vertex_stride: wgt::BufferAddress,
2977    pub indices: Option<AccelerationStructureTriangleIndices<'a, B>>,
2978    pub transform: Option<AccelerationStructureTriangleTransform<'a, B>>,
2979    pub flags: AccelerationStructureGeometryFlags,
2980}
2981
2982/// * `offset` - offset in bytes
2983#[derive(Clone, Debug)]
2984pub struct AccelerationStructureAABBs<'a, B: DynBuffer + ?Sized> {
2985    pub buffer: Option<&'a B>,
2986    pub offset: u32,
2987    pub count: u32,
2988    pub stride: wgt::BufferAddress,
2989    pub flags: AccelerationStructureGeometryFlags,
2990}
2991
2992#[derive(Clone, Debug)]
2993pub struct AccelerationStructureCopy {
2994    pub copy_flags: wgt::AccelerationStructureCopy,
2995    pub type_flags: wgt::AccelerationStructureType,
2996}
2997
2998/// * `offset` - offset in bytes
2999#[derive(Clone, Debug)]
3000pub struct AccelerationStructureInstances<'a, B: DynBuffer + ?Sized> {
3001    pub buffer: Option<&'a B>,
3002    pub offset: u32,
3003    pub count: u32,
3004}
3005
3006/// * `offset` - offset in bytes
3007#[derive(Clone, Debug)]
3008pub struct AccelerationStructureTriangleIndices<'a, B: DynBuffer + ?Sized> {
3009    pub format: wgt::IndexFormat,
3010    pub buffer: Option<&'a B>,
3011    pub offset: u32,
3012    pub count: u32,
3013}
3014
3015/// * `offset` - offset in bytes
3016#[derive(Clone, Debug)]
3017pub struct AccelerationStructureTriangleTransform<'a, B: DynBuffer + ?Sized> {
3018    pub buffer: &'a B,
3019    pub offset: u32,
3020}
3021
3022pub use wgt::AccelerationStructureFlags as AccelerationStructureBuildFlags;
3023pub use wgt::AccelerationStructureGeometryFlags;
3024
3025bitflags::bitflags! {
3026    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
3027    pub struct AccelerationStructureUses: u8 {
3028        // For blas used as input for tlas
3029        const BUILD_INPUT = 1 << 0;
3030        // Target for acceleration structure build
3031        const BUILD_OUTPUT = 1 << 1;
3032        // Tlas used in a shader
3033        const SHADER_INPUT = 1 << 2;
3034        // Blas used to query compacted size
3035        const QUERY_INPUT = 1 << 3;
3036        // BLAS used as a src for a copy operation
3037        const COPY_SRC = 1 << 4;
3038        // BLAS used as a dst for a copy operation
3039        const COPY_DST = 1 << 5;
3040    }
3041}
3042
3043#[derive(Debug, Clone)]
3044pub struct AccelerationStructureBarrier {
3045    pub usage: StateTransition<AccelerationStructureUses>,
3046}
3047
3048#[derive(Debug, Copy, Clone)]
3049pub struct TlasInstance {
3050    pub transform: [f32; 12],
3051    pub custom_data: u32,
3052    pub mask: u8,
3053    pub blas_address: u64,
3054    /// The offset for the index into the intersection hit
3055    /// group calculation. Number is in hit groups.
3056    pub pipeline_intersection_data_offset: u32,
3057}
3058
3059#[cfg(dx12)]
3060#[derive(Debug)]
3061pub enum D3D12ExposeAdapterResult {
3062    CreateDeviceError(dx12::CreateDeviceError),
3063    UnknownFeatureLevel(i32),
3064    ResourceBindingTier2Requirement,
3065    ShaderModel6Requirement,
3066    Success(dx12::FeatureLevel, dx12::ShaderModel),
3067}
3068
3069/// Pluggable telemetry, mainly to be used by Firefox.
3070#[derive(Debug, Clone, Copy)]
3071pub struct Telemetry {
3072    #[cfg(dx12)]
3073    pub d3d12_expose_adapter: fn(
3074        desc: &windows::Win32::Graphics::Dxgi::DXGI_ADAPTER_DESC2,
3075        driver_version: Result<[u16; 4], windows_core::HRESULT>,
3076        result: D3D12ExposeAdapterResult,
3077    ),
3078}
3079
3080#[derive(Debug)]
3081pub struct PipelineGroupData<'a, B: DynBuffer + ?Sized> {
3082    pub buffer: &'a B,
3083    pub offset: wgt::BufferAddress,
3084    pub stride: u64,
3085    pub count: u64,
3086}