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