Skip to main content

lagrange_wgpu_hal/
lib.rs

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