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