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