Skip to main content

wgpu_hal/
lib.rs

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