Skip to main content

wgpu_hal/
lib.rs

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