li_wgpu_hal/
lib.rs

1/*! This library describes the internal unsafe graphics abstraction API.
2 *  It follows WebGPU for the most part, re-using wgpu-types,
3 *  with the following deviations:
4 *  - Fully unsafe: zero overhead, zero validation.
5 *  - Compile-time backend selection via traits.
6 *  - Objects are passed by references and returned by value. No IDs.
7 *  - Mapping is persistent, with explicit synchronization.
8 *  - Resource transitions are explicit.
9 *  - All layouts are explicit. Binding model has compatibility.
10 *
11 *  General design direction is to follow the majority by the following weights:
12 *  - wgpu-core: 1.5
13 *  - primary backends (Vulkan/Metal/DX12): 1.0 each
14 *  - secondary backends (DX11/GLES): 0.5 each
15 */
16
17#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
18#![allow(
19    // for `if_then_panic` until it reaches stable
20    unknown_lints,
21    // We use loops for getting early-out of scope without closures.
22    clippy::never_loop,
23    // We don't use syntax sugar where it's not necessary.
24    clippy::match_like_matches_macro,
25    // Redundant matching is more explicit.
26    clippy::redundant_pattern_matching,
27    // Explicit lifetimes are often easier to reason about.
28    clippy::needless_lifetimes,
29    // No need for defaults in the internal types.
30    clippy::new_without_default,
31    // Matches are good and extendable, no need to make an exception here.
32    clippy::single_match,
33    // Push commands are more regular than macros.
34    clippy::vec_init_then_push,
35    // "if panic" is a good uniform construct.
36    clippy::if_then_panic,
37    // We unsafe impl `Send` for a reason.
38    clippy::non_send_fields_in_send_ty,
39    // TODO!
40    clippy::missing_safety_doc,
41    // Clashes with clippy::pattern_type_mismatch
42    clippy::needless_borrowed_reference,
43)]
44#![warn(
45    trivial_casts,
46    trivial_numeric_casts,
47    unsafe_op_in_unsafe_fn,
48    unused_extern_crates,
49    unused_qualifications,
50    // We don't match on a reference, unless required.
51    clippy::pattern_type_mismatch,
52)]
53
54/// DirectX11 API internals.
55#[cfg(all(feature = "dx11", windows))]
56pub mod dx11;
57/// DirectX12 API internals.
58#[cfg(all(feature = "dx12", windows))]
59pub mod dx12;
60/// A dummy API implementation.
61pub mod empty;
62/// GLES API internals.
63#[cfg(feature = "gles")]
64pub mod gles;
65/// Metal API internals.
66#[cfg(all(feature = "metal", any(target_os = "macos", target_os = "ios")))]
67pub mod metal;
68/// Vulkan API internals.
69#[cfg(all(feature = "vulkan", not(target_arch = "wasm32")))]
70pub mod vulkan;
71
72pub mod auxil;
73pub mod api {
74    #[cfg(all(feature = "dx11", windows))]
75    pub use super::dx11::Api as Dx11;
76    #[cfg(all(feature = "dx12", windows))]
77    pub use super::dx12::Api as Dx12;
78    pub use super::empty::Api as Empty;
79    #[cfg(feature = "gles")]
80    pub use super::gles::Api as Gles;
81    #[cfg(all(feature = "metal", any(target_os = "macos", target_os = "ios")))]
82    pub use super::metal::Api as Metal;
83    #[cfg(all(feature = "vulkan", not(target_arch = "wasm32")))]
84    pub use super::vulkan::Api as Vulkan;
85}
86
87use std::{
88    borrow::{Borrow, Cow},
89    fmt,
90    num::NonZeroU32,
91    ops::{Range, RangeInclusive},
92    ptr::NonNull,
93    sync::{atomic::AtomicBool, Arc},
94};
95
96use bitflags::bitflags;
97use thiserror::Error;
98use wgt::{WasmNotSend, WasmNotSync};
99
100pub const MAX_ANISOTROPY: u8 = 16;
101pub const MAX_BIND_GROUPS: usize = 8;
102pub const MAX_VERTEX_BUFFERS: usize = 16;
103pub const MAX_COLOR_ATTACHMENTS: usize = 8;
104pub const MAX_MIP_LEVELS: u32 = 16;
105/// Size of a single occlusion/timestamp query, when copied into a buffer, in bytes.
106pub const QUERY_SIZE: wgt::BufferAddress = 8;
107
108pub type Label<'a> = Option<&'a str>;
109pub type MemoryRange = Range<wgt::BufferAddress>;
110pub type FenceValue = u64;
111
112/// Drop guard to signal wgpu-hal is no longer using an externally created object.
113pub type DropGuard = Box<dyn std::any::Any + Send + Sync>;
114
115#[derive(Clone, Debug, PartialEq, Eq, Error)]
116pub enum DeviceError {
117    #[error("Out of memory")]
118    OutOfMemory,
119    #[error("Device is lost")]
120    Lost,
121    #[error("Creation of a resource failed for a reason other than running out of memory.")]
122    ResourceCreationFailed,
123}
124
125#[derive(Clone, Debug, Eq, PartialEq, Error)]
126pub enum ShaderError {
127    #[error("Compilation failed: {0:?}")]
128    Compilation(String),
129    #[error(transparent)]
130    Device(#[from] DeviceError),
131}
132
133#[derive(Clone, Debug, Eq, PartialEq, Error)]
134pub enum PipelineError {
135    #[error("Linkage failed for stage {0:?}: {1}")]
136    Linkage(wgt::ShaderStages, String),
137    #[error("Entry point for stage {0:?} is invalid")]
138    EntryPoint(naga::ShaderStage),
139    #[error(transparent)]
140    Device(#[from] DeviceError),
141}
142
143#[derive(Clone, Debug, Eq, PartialEq, Error)]
144pub enum SurfaceError {
145    #[error("Surface is lost")]
146    Lost,
147    #[error("Surface is outdated, needs to be re-created")]
148    Outdated,
149    #[error(transparent)]
150    Device(#[from] DeviceError),
151    #[error("Other reason: {0}")]
152    Other(&'static str),
153}
154
155/// Error occurring while trying to create an instance, or create a surface from an instance;
156/// typically relating to the state of the underlying graphics API or hardware.
157#[derive(Clone, Debug, Error)]
158#[error("{message}")]
159pub struct InstanceError {
160    /// These errors are very platform specific, so do not attempt to encode them as an enum.
161    ///
162    /// This message should describe the problem in sufficient detail to be useful for a
163    /// user-to-developer “why won't this work on my machine” bug report, and otherwise follow
164    /// <https://rust-lang.github.io/api-guidelines/interoperability.html#error-types-are-meaningful-and-well-behaved-c-good-err>.
165    message: String,
166
167    /// Underlying error value, if any is available.
168    #[source]
169    source: Option<Arc<dyn std::error::Error + Send + Sync + 'static>>,
170}
171
172impl InstanceError {
173    #[allow(dead_code)] // may be unused on some platforms
174    pub(crate) fn new(message: String) -> Self {
175        Self {
176            message,
177            source: None,
178        }
179    }
180    #[allow(dead_code)] // may be unused on some platforms
181    pub(crate) fn with_source(
182        message: String,
183        source: impl std::error::Error + Send + Sync + 'static,
184    ) -> Self {
185        Self {
186            message,
187            source: Some(Arc::new(source)),
188        }
189    }
190}
191
192pub trait Api: Clone + fmt::Debug + Sized {
193    type Instance: Instance<Self>;
194    type Surface: Surface<Self>;
195    type Adapter: Adapter<Self>;
196    type Device: Device<Self>;
197
198    type Queue: Queue<Self>;
199    type CommandEncoder: CommandEncoder<Self>;
200    type CommandBuffer: WasmNotSend + WasmNotSync + fmt::Debug;
201
202    type Buffer: fmt::Debug + WasmNotSend + WasmNotSync + 'static;
203    type Texture: fmt::Debug + WasmNotSend + WasmNotSync + 'static;
204    type SurfaceTexture: fmt::Debug + WasmNotSend + WasmNotSync + Borrow<Self::Texture>;
205    type TextureView: fmt::Debug + WasmNotSend + WasmNotSync;
206    type Sampler: fmt::Debug + WasmNotSend + WasmNotSync;
207    type QuerySet: fmt::Debug + WasmNotSend + WasmNotSync;
208    type Fence: fmt::Debug + WasmNotSend + WasmNotSync;
209
210    type BindGroupLayout: fmt::Debug + WasmNotSend + WasmNotSync;
211    type BindGroup: fmt::Debug + WasmNotSend + WasmNotSync;
212    type PipelineLayout: WasmNotSend + WasmNotSync;
213    type ShaderModule: fmt::Debug + WasmNotSend + WasmNotSync;
214    type RenderPipeline: WasmNotSend + WasmNotSync;
215    type ComputePipeline: WasmNotSend + WasmNotSync;
216}
217
218pub trait Instance<A: Api>: Sized + WasmNotSend + WasmNotSync {
219    unsafe fn init(desc: &InstanceDescriptor) -> Result<Self, InstanceError>;
220    unsafe fn create_surface(
221        &self,
222        display_handle: raw_window_handle::RawDisplayHandle,
223        window_handle: raw_window_handle::RawWindowHandle,
224    ) -> Result<A::Surface, InstanceError>;
225    unsafe fn destroy_surface(&self, surface: A::Surface);
226    unsafe fn enumerate_adapters(&self) -> Vec<ExposedAdapter<A>>;
227}
228
229pub trait Surface<A: Api>: WasmNotSend + WasmNotSync {
230    /// Configures the surface to use the given device.
231    ///
232    /// # Safety
233    ///
234    /// - All gpu work that uses the surface must have been completed.
235    /// - All [`AcquiredSurfaceTexture`]s must have been destroyed.
236    /// - All [`Api::TextureView`]s derived from the [`AcquiredSurfaceTexture`]s must have been destroyed.
237    /// - All surfaces created using other devices must have been unconfigured before this call.
238    unsafe fn configure(
239        &mut self,
240        device: &A::Device,
241        config: &SurfaceConfiguration,
242    ) -> Result<(), SurfaceError>;
243
244    /// Unconfigures the surface on the given device.
245    ///
246    /// # Safety
247    ///
248    /// - All gpu work that uses the surface must have been completed.
249    /// - All [`AcquiredSurfaceTexture`]s must have been destroyed.
250    /// - All [`Api::TextureView`]s derived from the [`AcquiredSurfaceTexture`]s must have been destroyed.
251    /// - The surface must have been configured on the given device.
252    unsafe fn unconfigure(&mut self, device: &A::Device);
253
254    /// Returns the next texture to be presented by the swapchain for drawing
255    ///
256    /// A `timeout` of `None` means to wait indefinitely, with no timeout.
257    ///
258    /// # Portability
259    ///
260    /// Some backends can't support a timeout when acquiring a texture and
261    /// the timeout will be ignored.
262    ///
263    /// Returns `None` on timing out.
264    unsafe fn acquire_texture(
265        &mut self,
266        timeout: Option<std::time::Duration>,
267    ) -> Result<Option<AcquiredSurfaceTexture<A>>, SurfaceError>;
268    unsafe fn discard_texture(&mut self, texture: A::SurfaceTexture);
269}
270
271pub trait Adapter<A: Api>: WasmNotSend + WasmNotSync {
272    unsafe fn open(
273        &self,
274        features: wgt::Features,
275        limits: &wgt::Limits,
276    ) -> Result<OpenDevice<A>, DeviceError>;
277
278    /// Return the set of supported capabilities for a texture format.
279    unsafe fn texture_format_capabilities(
280        &self,
281        format: wgt::TextureFormat,
282    ) -> TextureFormatCapabilities;
283
284    /// Returns the capabilities of working with a specified surface.
285    ///
286    /// `None` means presentation is not supported for it.
287    unsafe fn surface_capabilities(&self, surface: &A::Surface) -> Option<SurfaceCapabilities>;
288
289    /// Creates a [`PresentationTimestamp`] using the adapter's WSI.
290    ///
291    /// [`PresentationTimestamp`]: wgt::PresentationTimestamp
292    unsafe fn get_presentation_timestamp(&self) -> wgt::PresentationTimestamp;
293}
294
295pub trait Device<A: Api>: WasmNotSend + WasmNotSync {
296    /// Exit connection to this logical device.
297    unsafe fn exit(self, queue: A::Queue);
298    /// Creates a new buffer.
299    ///
300    /// The initial usage is `BufferUses::empty()`.
301    unsafe fn create_buffer(&self, desc: &BufferDescriptor) -> Result<A::Buffer, DeviceError>;
302    unsafe fn destroy_buffer(&self, buffer: A::Buffer);
303    //TODO: clarify if zero-sized mapping is allowed
304    unsafe fn map_buffer(
305        &self,
306        buffer: &A::Buffer,
307        range: MemoryRange,
308    ) -> Result<BufferMapping, DeviceError>;
309    unsafe fn unmap_buffer(&self, buffer: &A::Buffer) -> Result<(), DeviceError>;
310    unsafe fn flush_mapped_ranges<I>(&self, buffer: &A::Buffer, ranges: I)
311    where
312        I: Iterator<Item = MemoryRange>;
313    unsafe fn invalidate_mapped_ranges<I>(&self, buffer: &A::Buffer, ranges: I)
314    where
315        I: Iterator<Item = MemoryRange>;
316
317    /// Creates a new texture.
318    ///
319    /// The initial usage for all subresources is `TextureUses::UNINITIALIZED`.
320    unsafe fn create_texture(&self, desc: &TextureDescriptor) -> Result<A::Texture, DeviceError>;
321    unsafe fn destroy_texture(&self, texture: A::Texture);
322    unsafe fn create_texture_view(
323        &self,
324        texture: &A::Texture,
325        desc: &TextureViewDescriptor,
326    ) -> Result<A::TextureView, DeviceError>;
327    unsafe fn destroy_texture_view(&self, view: A::TextureView);
328    unsafe fn create_sampler(&self, desc: &SamplerDescriptor) -> Result<A::Sampler, DeviceError>;
329    unsafe fn destroy_sampler(&self, sampler: A::Sampler);
330
331    unsafe fn create_command_encoder(
332        &self,
333        desc: &CommandEncoderDescriptor<A>,
334    ) -> Result<A::CommandEncoder, DeviceError>;
335    unsafe fn destroy_command_encoder(&self, pool: A::CommandEncoder);
336
337    /// Creates a bind group layout.
338    unsafe fn create_bind_group_layout(
339        &self,
340        desc: &BindGroupLayoutDescriptor,
341    ) -> Result<A::BindGroupLayout, DeviceError>;
342    unsafe fn destroy_bind_group_layout(&self, bg_layout: A::BindGroupLayout);
343    unsafe fn create_pipeline_layout(
344        &self,
345        desc: &PipelineLayoutDescriptor<A>,
346    ) -> Result<A::PipelineLayout, DeviceError>;
347    unsafe fn destroy_pipeline_layout(&self, pipeline_layout: A::PipelineLayout);
348    unsafe fn create_bind_group(
349        &self,
350        desc: &BindGroupDescriptor<A>,
351    ) -> Result<A::BindGroup, DeviceError>;
352    unsafe fn destroy_bind_group(&self, group: A::BindGroup);
353
354    unsafe fn create_shader_module(
355        &self,
356        desc: &ShaderModuleDescriptor,
357        shader: ShaderInput,
358    ) -> Result<A::ShaderModule, ShaderError>;
359    unsafe fn destroy_shader_module(&self, module: A::ShaderModule);
360    unsafe fn create_render_pipeline(
361        &self,
362        desc: &RenderPipelineDescriptor<A>,
363    ) -> Result<A::RenderPipeline, PipelineError>;
364    unsafe fn destroy_render_pipeline(&self, pipeline: A::RenderPipeline);
365    unsafe fn create_compute_pipeline(
366        &self,
367        desc: &ComputePipelineDescriptor<A>,
368    ) -> Result<A::ComputePipeline, PipelineError>;
369    unsafe fn destroy_compute_pipeline(&self, pipeline: A::ComputePipeline);
370
371    unsafe fn create_query_set(
372        &self,
373        desc: &wgt::QuerySetDescriptor<Label>,
374    ) -> Result<A::QuerySet, DeviceError>;
375    unsafe fn destroy_query_set(&self, set: A::QuerySet);
376    unsafe fn create_fence(&self) -> Result<A::Fence, DeviceError>;
377    unsafe fn destroy_fence(&self, fence: A::Fence);
378    unsafe fn get_fence_value(&self, fence: &A::Fence) -> Result<FenceValue, DeviceError>;
379    /// Calling wait with a lower value than the current fence value will immediately return.
380    unsafe fn wait(
381        &self,
382        fence: &A::Fence,
383        value: FenceValue,
384        timeout_ms: u32,
385    ) -> Result<bool, DeviceError>;
386
387    unsafe fn start_capture(&self) -> bool;
388    unsafe fn stop_capture(&self);
389}
390
391pub trait Queue<A: Api>: WasmNotSend + WasmNotSync {
392    /// Submits the command buffers for execution on GPU.
393    ///
394    /// Valid usage:
395    /// - all of the command buffers were created from command pools
396    ///   that are associated with this queue.
397    /// - all of the command buffers had `CommadBuffer::finish()` called.
398    unsafe fn submit(
399        &mut self,
400        command_buffers: &[&A::CommandBuffer],
401        signal_fence: Option<(&mut A::Fence, FenceValue)>,
402    ) -> Result<(), DeviceError>;
403    unsafe fn present(
404        &mut self,
405        surface: &mut A::Surface,
406        texture: A::SurfaceTexture,
407    ) -> Result<(), SurfaceError>;
408    unsafe fn get_timestamp_period(&self) -> f32;
409}
410
411/// Encoder for commands in command buffers.
412/// Serves as a parent for all the encoded command buffers.
413/// Works in bursts of action: one or more command buffers are recorded,
414/// then submitted to a queue, and then it needs to be `reset_all()`.
415pub trait CommandEncoder<A: Api>: WasmNotSend + WasmNotSync + fmt::Debug {
416    /// Begin encoding a new command buffer.
417    unsafe fn begin_encoding(&mut self, label: Label) -> Result<(), DeviceError>;
418    /// Discard currently recorded list, if any.
419    unsafe fn discard_encoding(&mut self);
420    unsafe fn end_encoding(&mut self) -> Result<A::CommandBuffer, DeviceError>;
421    /// Reclaims all resources that are allocated for this encoder.
422    /// Must get all of the produced command buffers back,
423    /// and they must not be used by GPU at this moment.
424    unsafe fn reset_all<I>(&mut self, command_buffers: I)
425    where
426        I: Iterator<Item = A::CommandBuffer>;
427
428    unsafe fn transition_buffers<'a, T>(&mut self, barriers: T)
429    where
430        T: Iterator<Item = BufferBarrier<'a, A>>;
431
432    unsafe fn transition_textures<'a, T>(&mut self, barriers: T)
433    where
434        T: Iterator<Item = TextureBarrier<'a, A>>;
435
436    // copy operations
437
438    unsafe fn clear_buffer(&mut self, buffer: &A::Buffer, range: MemoryRange);
439
440    unsafe fn copy_buffer_to_buffer<T>(&mut self, src: &A::Buffer, dst: &A::Buffer, regions: T)
441    where
442        T: Iterator<Item = BufferCopy>;
443
444    /// Copy from an external image to an internal texture.
445    /// Works with a single array layer.
446    /// Note: `dst` current usage has to be `TextureUses::COPY_DST`.
447    /// Note: the copy extent is in physical size (rounded to the block size)
448    #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
449    unsafe fn copy_external_image_to_texture<T>(
450        &mut self,
451        src: &wgt::ImageCopyExternalImage,
452        dst: &A::Texture,
453        dst_premultiplication: bool,
454        regions: T,
455    ) where
456        T: Iterator<Item = TextureCopy>;
457
458    /// Copy from one texture to another.
459    /// Works with a single array layer.
460    /// Note: `dst` current usage has to be `TextureUses::COPY_DST`.
461    /// Note: the copy extent is in physical size (rounded to the block size)
462    unsafe fn copy_texture_to_texture<T>(
463        &mut self,
464        src: &A::Texture,
465        src_usage: TextureUses,
466        dst: &A::Texture,
467        regions: T,
468    ) where
469        T: Iterator<Item = TextureCopy>;
470
471    /// Copy from buffer to texture.
472    /// Works with a single array layer.
473    /// Note: `dst` current usage has to be `TextureUses::COPY_DST`.
474    /// Note: the copy extent is in physical size (rounded to the block size)
475    unsafe fn copy_buffer_to_texture<T>(&mut self, src: &A::Buffer, dst: &A::Texture, regions: T)
476    where
477        T: Iterator<Item = BufferTextureCopy>;
478
479    /// Copy from texture to buffer.
480    /// Works with a single array layer.
481    /// Note: the copy extent is in physical size (rounded to the block size)
482    unsafe fn copy_texture_to_buffer<T>(
483        &mut self,
484        src: &A::Texture,
485        src_usage: TextureUses,
486        dst: &A::Buffer,
487        regions: T,
488    ) where
489        T: Iterator<Item = BufferTextureCopy>;
490
491    // pass common
492
493    /// Sets the bind group at `index` to `group`, assuming the layout
494    /// of all the preceeding groups to be taken from `layout`.
495    unsafe fn set_bind_group(
496        &mut self,
497        layout: &A::PipelineLayout,
498        index: u32,
499        group: &A::BindGroup,
500        dynamic_offsets: &[wgt::DynamicOffset],
501    );
502
503    unsafe fn set_push_constants(
504        &mut self,
505        layout: &A::PipelineLayout,
506        stages: wgt::ShaderStages,
507        offset: u32,
508        data: &[u32],
509    );
510
511    unsafe fn insert_debug_marker(&mut self, label: &str);
512    unsafe fn begin_debug_marker(&mut self, group_label: &str);
513    unsafe fn end_debug_marker(&mut self);
514
515    // queries
516
517    /// # Safety:
518    ///
519    /// - If `set` is an occlusion query set, it must be the same one as used in the [`RenderPassDescriptor::occlusion_query_set`] parameter.
520    unsafe fn begin_query(&mut self, set: &A::QuerySet, index: u32);
521    /// # Safety:
522    ///
523    /// - If `set` is an occlusion query set, it must be the same one as used in the [`RenderPassDescriptor::occlusion_query_set`] parameter.
524    unsafe fn end_query(&mut self, set: &A::QuerySet, index: u32);
525    unsafe fn write_timestamp(&mut self, set: &A::QuerySet, index: u32);
526    unsafe fn reset_queries(&mut self, set: &A::QuerySet, range: Range<u32>);
527    unsafe fn copy_query_results(
528        &mut self,
529        set: &A::QuerySet,
530        range: Range<u32>,
531        buffer: &A::Buffer,
532        offset: wgt::BufferAddress,
533        stride: wgt::BufferSize,
534    );
535
536    // render passes
537
538    // Begins a render pass, clears all active bindings.
539    unsafe fn begin_render_pass(&mut self, desc: &RenderPassDescriptor<A>);
540    unsafe fn end_render_pass(&mut self);
541
542    unsafe fn set_render_pipeline(&mut self, pipeline: &A::RenderPipeline);
543
544    unsafe fn set_index_buffer<'a>(
545        &mut self,
546        binding: BufferBinding<'a, A>,
547        format: wgt::IndexFormat,
548    );
549    unsafe fn set_vertex_buffer<'a>(&mut self, index: u32, binding: BufferBinding<'a, A>);
550    unsafe fn set_viewport(&mut self, rect: &Rect<f32>, depth_range: Range<f32>);
551    unsafe fn set_scissor_rect(&mut self, rect: &Rect<u32>);
552    unsafe fn set_stencil_reference(&mut self, value: u32);
553    unsafe fn set_blend_constants(&mut self, color: &[f32; 4]);
554
555    unsafe fn draw(
556        &mut self,
557        start_vertex: u32,
558        vertex_count: u32,
559        start_instance: u32,
560        instance_count: u32,
561    );
562    unsafe fn draw_indexed(
563        &mut self,
564        start_index: u32,
565        index_count: u32,
566        base_vertex: i32,
567        start_instance: u32,
568        instance_count: u32,
569    );
570    unsafe fn draw_indirect(
571        &mut self,
572        buffer: &A::Buffer,
573        offset: wgt::BufferAddress,
574        draw_count: u32,
575    );
576    unsafe fn draw_indexed_indirect(
577        &mut self,
578        buffer: &A::Buffer,
579        offset: wgt::BufferAddress,
580        draw_count: u32,
581    );
582    unsafe fn draw_indirect_count(
583        &mut self,
584        buffer: &A::Buffer,
585        offset: wgt::BufferAddress,
586        count_buffer: &A::Buffer,
587        count_offset: wgt::BufferAddress,
588        max_count: u32,
589    );
590    unsafe fn draw_indexed_indirect_count(
591        &mut self,
592        buffer: &A::Buffer,
593        offset: wgt::BufferAddress,
594        count_buffer: &A::Buffer,
595        count_offset: wgt::BufferAddress,
596        max_count: u32,
597    );
598
599    // compute passes
600
601    // Begins a compute pass, clears all active bindings.
602    unsafe fn begin_compute_pass(&mut self, desc: &ComputePassDescriptor<A>);
603    unsafe fn end_compute_pass(&mut self);
604
605    unsafe fn set_compute_pipeline(&mut self, pipeline: &A::ComputePipeline);
606
607    unsafe fn dispatch(&mut self, count: [u32; 3]);
608    unsafe fn dispatch_indirect(&mut self, buffer: &A::Buffer, offset: wgt::BufferAddress);
609}
610
611bitflags!(
612    /// Pipeline layout creation flags.
613    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
614    pub struct PipelineLayoutFlags: u32 {
615        /// Include support for base vertex/instance drawing.
616        const BASE_VERTEX_INSTANCE = 1 << 0;
617        /// Include support for num work groups builtin.
618        const NUM_WORK_GROUPS = 1 << 1;
619    }
620);
621
622bitflags!(
623    /// Pipeline layout creation flags.
624    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
625    pub struct BindGroupLayoutFlags: u32 {
626        /// Allows for bind group binding arrays to be shorter than the array in the BGL.
627        const PARTIALLY_BOUND = 1 << 0;
628    }
629);
630
631bitflags!(
632    /// Texture format capability flags.
633    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
634    pub struct TextureFormatCapabilities: u32 {
635        /// Format can be sampled.
636        const SAMPLED = 1 << 0;
637        /// Format can be sampled with a linear sampler.
638        const SAMPLED_LINEAR = 1 << 1;
639        /// Format can be sampled with a min/max reduction sampler.
640        const SAMPLED_MINMAX = 1 << 2;
641
642        /// Format can be used as storage with write-only access.
643        const STORAGE = 1 << 3;
644        /// Format can be used as storage with read and read/write access.
645        const STORAGE_READ_WRITE = 1 << 4;
646        /// Format can be used as storage with atomics.
647        const STORAGE_ATOMIC = 1 << 5;
648
649        /// Format can be used as color and input attachment.
650        const COLOR_ATTACHMENT = 1 << 6;
651        /// Format can be used as color (with blending) and input attachment.
652        const COLOR_ATTACHMENT_BLEND = 1 << 7;
653        /// Format can be used as depth-stencil and input attachment.
654        const DEPTH_STENCIL_ATTACHMENT = 1 << 8;
655
656        /// Format can be multisampled by x2.
657        const MULTISAMPLE_X2   = 1 << 9;
658        /// Format can be multisampled by x4.
659        const MULTISAMPLE_X4   = 1 << 10;
660        /// Format can be multisampled by x8.
661        const MULTISAMPLE_X8   = 1 << 11;
662        /// Format can be multisampled by x16.
663        const MULTISAMPLE_X16  = 1 << 12;
664
665        /// Format can be used for render pass resolve targets.
666        const MULTISAMPLE_RESOLVE = 1 << 13;
667
668        /// Format can be copied from.
669        const COPY_SRC = 1 << 14;
670        /// Format can be copied to.
671        const COPY_DST = 1 << 15;
672    }
673);
674
675bitflags!(
676    /// Texture format capability flags.
677    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
678    pub struct FormatAspects: u8 {
679        const COLOR = 1 << 0;
680        const DEPTH = 1 << 1;
681        const STENCIL = 1 << 2;
682    }
683);
684
685impl FormatAspects {
686    pub fn new(format: wgt::TextureFormat, aspect: wgt::TextureAspect) -> Self {
687        let aspect_mask = match aspect {
688            wgt::TextureAspect::All => Self::all(),
689            wgt::TextureAspect::DepthOnly => Self::DEPTH,
690            wgt::TextureAspect::StencilOnly => Self::STENCIL,
691        };
692        Self::from(format) & aspect_mask
693    }
694
695    /// Returns `true` if only one flag is set
696    pub fn is_one(&self) -> bool {
697        self.bits().count_ones() == 1
698    }
699
700    pub fn map(&self) -> wgt::TextureAspect {
701        match *self {
702            Self::COLOR => wgt::TextureAspect::All,
703            Self::DEPTH => wgt::TextureAspect::DepthOnly,
704            Self::STENCIL => wgt::TextureAspect::StencilOnly,
705            _ => unreachable!(),
706        }
707    }
708}
709
710impl From<wgt::TextureFormat> for FormatAspects {
711    fn from(format: wgt::TextureFormat) -> Self {
712        match format {
713            wgt::TextureFormat::Stencil8 => Self::STENCIL,
714            wgt::TextureFormat::Depth16Unorm
715            | wgt::TextureFormat::Depth32Float
716            | wgt::TextureFormat::Depth24Plus => Self::DEPTH,
717            wgt::TextureFormat::Depth32FloatStencil8 | wgt::TextureFormat::Depth24PlusStencil8 => {
718                Self::DEPTH | Self::STENCIL
719            }
720            _ => Self::COLOR,
721        }
722    }
723}
724
725bitflags!(
726    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
727    pub struct MemoryFlags: u32 {
728        const TRANSIENT = 1 << 0;
729        const PREFER_COHERENT = 1 << 1;
730    }
731);
732
733//TODO: it's not intuitive for the backends to consider `LOAD` being optional.
734
735bitflags!(
736    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
737    pub struct AttachmentOps: u8 {
738        const LOAD = 1 << 0;
739        const STORE = 1 << 1;
740    }
741);
742
743bitflags::bitflags! {
744    /// Similar to `wgt::BufferUsages` but for internal use.
745    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
746    pub struct BufferUses: u16 {
747        /// The argument to a read-only mapping.
748        const MAP_READ = 1 << 0;
749        /// The argument to a write-only mapping.
750        const MAP_WRITE = 1 << 1;
751        /// The source of a hardware copy.
752        const COPY_SRC = 1 << 2;
753        /// The destination of a hardware copy.
754        const COPY_DST = 1 << 3;
755        /// The index buffer used for drawing.
756        const INDEX = 1 << 4;
757        /// A vertex buffer used for drawing.
758        const VERTEX = 1 << 5;
759        /// A uniform buffer bound in a bind group.
760        const UNIFORM = 1 << 6;
761        /// A read-only storage buffer used in a bind group.
762        const STORAGE_READ = 1 << 7;
763        /// A read-write or write-only buffer used in a bind group.
764        const STORAGE_READ_WRITE = 1 << 8;
765        /// The indirect or count buffer in a indirect draw or dispatch.
766        const INDIRECT = 1 << 9;
767        /// A buffer used to store query results.
768        const QUERY_RESOLVE = 1 << 10;
769        /// The combination of states that a buffer may be in _at the same time_.
770        const INCLUSIVE = Self::MAP_READ.bits() | Self::COPY_SRC.bits() |
771            Self::INDEX.bits() | Self::VERTEX.bits() | Self::UNIFORM.bits() |
772            Self::STORAGE_READ.bits() | Self::INDIRECT.bits();
773        /// The combination of states that a buffer must exclusively be in.
774        const EXCLUSIVE = Self::MAP_WRITE.bits() | Self::COPY_DST.bits() | Self::STORAGE_READ_WRITE.bits();
775        /// The combination of all usages that the are guaranteed to be be ordered by the hardware.
776        /// If a usage is ordered, then if the buffer state doesn't change between draw calls, there
777        /// are no barriers needed for synchronization.
778        const ORDERED = Self::INCLUSIVE.bits() | Self::MAP_WRITE.bits();
779    }
780}
781
782bitflags::bitflags! {
783    /// Similar to `wgt::TextureUsages` but for internal use.
784    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
785    pub struct TextureUses: u16 {
786        /// The texture is in unknown state.
787        const UNINITIALIZED = 1 << 0;
788        /// Ready to present image to the surface.
789        const PRESENT = 1 << 1;
790        /// The source of a hardware copy.
791        const COPY_SRC = 1 << 2;
792        /// The destination of a hardware copy.
793        const COPY_DST = 1 << 3;
794        /// Read-only sampled or fetched resource.
795        const RESOURCE = 1 << 4;
796        /// The color target of a renderpass.
797        const COLOR_TARGET = 1 << 5;
798        /// Read-only depth stencil usage.
799        const DEPTH_STENCIL_READ = 1 << 6;
800        /// Read-write depth stencil usage
801        const DEPTH_STENCIL_WRITE = 1 << 7;
802        /// Read-only storage buffer usage. Corresponds to a UAV in d3d, so is exclusive, despite being read only.
803        const STORAGE_READ = 1 << 8;
804        /// Read-write or write-only storage buffer usage.
805        const STORAGE_READ_WRITE = 1 << 9;
806        /// The combination of states that a texture may be in _at the same time_.
807        const INCLUSIVE = Self::COPY_SRC.bits() | Self::RESOURCE.bits() | Self::DEPTH_STENCIL_READ.bits();
808        /// The combination of states that a texture must exclusively be in.
809        const EXCLUSIVE = Self::COPY_DST.bits() | Self::COLOR_TARGET.bits() | Self::DEPTH_STENCIL_WRITE.bits() | Self::STORAGE_READ.bits() | Self::STORAGE_READ_WRITE.bits() | Self::PRESENT.bits();
810        /// The combination of all usages that the are guaranteed to be be ordered by the hardware.
811        /// If a usage is ordered, then if the texture state doesn't change between draw calls, there
812        /// are no barriers needed for synchronization.
813        const ORDERED = Self::INCLUSIVE.bits() | Self::COLOR_TARGET.bits() | Self::DEPTH_STENCIL_WRITE.bits() | Self::STORAGE_READ.bits();
814
815        /// Flag used by the wgpu-core texture tracker to say a texture is in different states for every sub-resource
816        const COMPLEX = 1 << 10;
817        /// Flag used by the wgpu-core texture tracker to say that the tracker does not know the state of the sub-resource.
818        /// This is different from UNINITIALIZED as that says the tracker does know, but the texture has not been initialized.
819        const UNKNOWN = 1 << 11;
820    }
821}
822
823#[derive(Clone, Debug)]
824pub struct InstanceDescriptor<'a> {
825    pub name: &'a str,
826    pub flags: wgt::InstanceFlags,
827    pub dx12_shader_compiler: wgt::Dx12Compiler,
828    pub gles_minor_version: wgt::Gles3MinorVersion,
829}
830
831#[derive(Clone, Debug)]
832pub struct Alignments {
833    /// The alignment of the start of the buffer used as a GPU copy source.
834    pub buffer_copy_offset: wgt::BufferSize,
835    /// The alignment of the row pitch of the texture data stored in a buffer that is
836    /// used in a GPU copy operation.
837    pub buffer_copy_pitch: wgt::BufferSize,
838}
839
840#[derive(Clone, Debug)]
841pub struct Capabilities {
842    pub limits: wgt::Limits,
843    pub alignments: Alignments,
844    pub downlevel: wgt::DownlevelCapabilities,
845}
846
847#[derive(Debug)]
848pub struct ExposedAdapter<A: Api> {
849    pub adapter: A::Adapter,
850    pub info: wgt::AdapterInfo,
851    pub features: wgt::Features,
852    pub capabilities: Capabilities,
853}
854
855/// Describes information about what a `Surface`'s presentation capabilities are.
856/// Fetch this with [Adapter::surface_capabilities].
857#[derive(Debug, Clone)]
858pub struct SurfaceCapabilities {
859    /// List of supported texture formats.
860    ///
861    /// Must be at least one.
862    pub formats: Vec<wgt::TextureFormat>,
863
864    /// Range for the swap chain sizes.
865    ///
866    /// - `swap_chain_sizes.start` must be at least 1.
867    /// - `swap_chain_sizes.end` must be larger or equal to `swap_chain_sizes.start`.
868    pub swap_chain_sizes: RangeInclusive<u32>,
869
870    /// Current extent of the surface, if known.
871    pub current_extent: Option<wgt::Extent3d>,
872
873    /// Range of supported extents.
874    ///
875    /// `current_extent` must be inside this range.
876    pub extents: RangeInclusive<wgt::Extent3d>,
877
878    /// Supported texture usage flags.
879    ///
880    /// Must have at least `TextureUses::COLOR_TARGET`
881    pub usage: TextureUses,
882
883    /// List of supported V-sync modes.
884    ///
885    /// Must be at least one.
886    pub present_modes: Vec<wgt::PresentMode>,
887
888    /// List of supported alpha composition modes.
889    ///
890    /// Must be at least one.
891    pub composite_alpha_modes: Vec<wgt::CompositeAlphaMode>,
892}
893
894#[derive(Debug)]
895pub struct AcquiredSurfaceTexture<A: Api> {
896    pub texture: A::SurfaceTexture,
897    /// The presentation configuration no longer matches
898    /// the surface properties exactly, but can still be used to present
899    /// to the surface successfully.
900    pub suboptimal: bool,
901}
902
903#[derive(Debug)]
904pub struct OpenDevice<A: Api> {
905    pub device: A::Device,
906    pub queue: A::Queue,
907}
908
909#[derive(Clone, Debug)]
910pub struct BufferMapping {
911    pub ptr: NonNull<u8>,
912    pub is_coherent: bool,
913}
914
915#[derive(Clone, Debug)]
916pub struct BufferDescriptor<'a> {
917    pub label: Label<'a>,
918    pub size: wgt::BufferAddress,
919    pub usage: BufferUses,
920    pub memory_flags: MemoryFlags,
921}
922
923#[derive(Clone, Debug)]
924pub struct TextureDescriptor<'a> {
925    pub label: Label<'a>,
926    pub size: wgt::Extent3d,
927    pub mip_level_count: u32,
928    pub sample_count: u32,
929    pub dimension: wgt::TextureDimension,
930    pub format: wgt::TextureFormat,
931    pub usage: TextureUses,
932    pub memory_flags: MemoryFlags,
933    /// Allows views of this texture to have a different format
934    /// than the texture does.
935    pub view_formats: Vec<wgt::TextureFormat>,
936}
937
938impl TextureDescriptor<'_> {
939    pub fn copy_extent(&self) -> CopyExtent {
940        CopyExtent::map_extent_to_copy_size(&self.size, self.dimension)
941    }
942
943    pub fn is_cube_compatible(&self) -> bool {
944        self.dimension == wgt::TextureDimension::D2
945            && self.size.depth_or_array_layers % 6 == 0
946            && self.sample_count == 1
947            && self.size.width == self.size.height
948    }
949
950    pub fn array_layer_count(&self) -> u32 {
951        match self.dimension {
952            wgt::TextureDimension::D1 | wgt::TextureDimension::D3 => 1,
953            wgt::TextureDimension::D2 => self.size.depth_or_array_layers,
954        }
955    }
956}
957
958/// TextureView descriptor.
959///
960/// Valid usage:
961///. - `format` has to be the same as `TextureDescriptor::format`
962///. - `dimension` has to be compatible with `TextureDescriptor::dimension`
963///. - `usage` has to be a subset of `TextureDescriptor::usage`
964///. - `range` has to be a subset of parent texture
965#[derive(Clone, Debug)]
966pub struct TextureViewDescriptor<'a> {
967    pub label: Label<'a>,
968    pub format: wgt::TextureFormat,
969    pub dimension: wgt::TextureViewDimension,
970    pub usage: TextureUses,
971    pub range: wgt::ImageSubresourceRange,
972}
973
974#[derive(Clone, Debug)]
975pub struct SamplerDescriptor<'a> {
976    pub label: Label<'a>,
977    pub address_modes: [wgt::AddressMode; 3],
978    pub mag_filter: wgt::FilterMode,
979    pub min_filter: wgt::FilterMode,
980    pub mipmap_filter: wgt::FilterMode,
981    pub lod_clamp: Range<f32>,
982    pub compare: Option<wgt::CompareFunction>,
983    // Must in the range [1, 16].
984    //
985    // Anisotropic filtering must be supported if this is not 1.
986    pub anisotropy_clamp: u16,
987    pub border_color: Option<wgt::SamplerBorderColor>,
988}
989
990/// BindGroupLayout descriptor.
991///
992/// Valid usage:
993/// - `entries` are sorted by ascending `wgt::BindGroupLayoutEntry::binding`
994#[derive(Clone, Debug)]
995pub struct BindGroupLayoutDescriptor<'a> {
996    pub label: Label<'a>,
997    pub flags: BindGroupLayoutFlags,
998    pub entries: &'a [wgt::BindGroupLayoutEntry],
999}
1000
1001#[derive(Clone, Debug)]
1002pub struct PipelineLayoutDescriptor<'a, A: Api> {
1003    pub label: Label<'a>,
1004    pub flags: PipelineLayoutFlags,
1005    pub bind_group_layouts: &'a [&'a A::BindGroupLayout],
1006    pub push_constant_ranges: &'a [wgt::PushConstantRange],
1007}
1008
1009#[derive(Debug)]
1010pub struct BufferBinding<'a, A: Api> {
1011    /// The buffer being bound.
1012    pub buffer: &'a A::Buffer,
1013
1014    /// The offset at which the bound region starts.
1015    ///
1016    /// This must be less than the size of the buffer. Some back ends
1017    /// cannot tolerate zero-length regions; for example, see
1018    /// [VUID-VkDescriptorBufferInfo-offset-00340][340] and
1019    /// [VUID-VkDescriptorBufferInfo-range-00341][341], or the
1020    /// documentation for GLES's [glBindBufferRange][bbr].
1021    ///
1022    /// [340]: https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-VkDescriptorBufferInfo-offset-00340
1023    /// [341]: https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-VkDescriptorBufferInfo-range-00341
1024    /// [bbr]: https://registry.khronos.org/OpenGL-Refpages/es3.0/html/glBindBufferRange.xhtml
1025    pub offset: wgt::BufferAddress,
1026
1027    /// The size of the region bound, in bytes.
1028    ///
1029    /// If `None`, the region extends from `offset` to the end of the
1030    /// buffer. Given the restrictions on `offset`, this means that
1031    /// the size is always greater than zero.
1032    pub size: Option<wgt::BufferSize>,
1033}
1034
1035// Rust gets confused about the impl requirements for `A`
1036impl<A: Api> Clone for BufferBinding<'_, A> {
1037    fn clone(&self) -> Self {
1038        Self {
1039            buffer: self.buffer,
1040            offset: self.offset,
1041            size: self.size,
1042        }
1043    }
1044}
1045
1046#[derive(Debug)]
1047pub struct TextureBinding<'a, A: Api> {
1048    pub view: &'a A::TextureView,
1049    pub usage: TextureUses,
1050}
1051
1052// Rust gets confused about the impl requirements for `A`
1053impl<A: Api> Clone for TextureBinding<'_, A> {
1054    fn clone(&self) -> Self {
1055        Self {
1056            view: self.view,
1057            usage: self.usage,
1058        }
1059    }
1060}
1061
1062#[derive(Clone, Debug)]
1063pub struct BindGroupEntry {
1064    pub binding: u32,
1065    pub resource_index: u32,
1066    pub count: u32,
1067}
1068
1069/// BindGroup descriptor.
1070///
1071/// Valid usage:
1072///. - `entries` has to be sorted by ascending `BindGroupEntry::binding`
1073///. - `entries` has to have the same set of `BindGroupEntry::binding` as `layout`
1074///. - each entry has to be compatible with the `layout`
1075///. - each entry's `BindGroupEntry::resource_index` is within range
1076///    of the corresponding resource array, selected by the relevant
1077///    `BindGroupLayoutEntry`.
1078#[derive(Clone, Debug)]
1079pub struct BindGroupDescriptor<'a, A: Api> {
1080    pub label: Label<'a>,
1081    pub layout: &'a A::BindGroupLayout,
1082    pub buffers: &'a [BufferBinding<'a, A>],
1083    pub samplers: &'a [&'a A::Sampler],
1084    pub textures: &'a [TextureBinding<'a, A>],
1085    pub entries: &'a [BindGroupEntry],
1086}
1087
1088#[derive(Clone, Debug)]
1089pub struct CommandEncoderDescriptor<'a, A: Api> {
1090    pub label: Label<'a>,
1091    pub queue: &'a A::Queue,
1092}
1093
1094/// Naga shader module.
1095pub struct NagaShader {
1096    /// Shader module IR.
1097    pub module: Cow<'static, naga::Module>,
1098    /// Analysis information of the module.
1099    pub info: naga::valid::ModuleInfo,
1100    /// Source codes for debug
1101    pub debug_source: Option<DebugSource>,
1102}
1103
1104// Custom implementation avoids the need to generate Debug impl code
1105// for the whole Naga module and info.
1106impl fmt::Debug for NagaShader {
1107    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1108        write!(formatter, "Naga shader")
1109    }
1110}
1111
1112/// Shader input.
1113#[allow(clippy::large_enum_variant)]
1114pub enum ShaderInput<'a> {
1115    Naga(NagaShader),
1116    SpirV(&'a [u32]),
1117}
1118
1119pub struct ShaderModuleDescriptor<'a> {
1120    pub label: Label<'a>,
1121    pub runtime_checks: bool,
1122}
1123
1124#[derive(Debug, Clone)]
1125pub struct DebugSource {
1126    pub file_name: Cow<'static, str>,
1127    pub source_code: Cow<'static, str>,
1128}
1129
1130/// Describes a programmable pipeline stage.
1131#[derive(Debug)]
1132pub struct ProgrammableStage<'a, A: Api> {
1133    /// The compiled shader module for this stage.
1134    pub module: &'a A::ShaderModule,
1135    /// The name of the entry point in the compiled shader. There must be a function with this name
1136    ///  in the shader.
1137    pub entry_point: &'a str,
1138}
1139
1140// Rust gets confused about the impl requirements for `A`
1141impl<A: Api> Clone for ProgrammableStage<'_, A> {
1142    fn clone(&self) -> Self {
1143        Self {
1144            module: self.module,
1145            entry_point: self.entry_point,
1146        }
1147    }
1148}
1149
1150/// Describes a compute pipeline.
1151#[derive(Clone, Debug)]
1152pub struct ComputePipelineDescriptor<'a, A: Api> {
1153    pub label: Label<'a>,
1154    /// The layout of bind groups for this pipeline.
1155    pub layout: &'a A::PipelineLayout,
1156    /// The compiled compute stage and its entry point.
1157    pub stage: ProgrammableStage<'a, A>,
1158}
1159
1160/// Describes how the vertex buffer is interpreted.
1161#[derive(Clone, Debug)]
1162pub struct VertexBufferLayout<'a> {
1163    /// The stride, in bytes, between elements of this buffer.
1164    pub array_stride: wgt::BufferAddress,
1165    /// How often this vertex buffer is "stepped" forward.
1166    pub step_mode: wgt::VertexStepMode,
1167    /// The list of attributes which comprise a single vertex.
1168    pub attributes: &'a [wgt::VertexAttribute],
1169}
1170
1171/// Describes a render (graphics) pipeline.
1172#[derive(Clone, Debug)]
1173pub struct RenderPipelineDescriptor<'a, A: Api> {
1174    pub label: Label<'a>,
1175    /// The layout of bind groups for this pipeline.
1176    pub layout: &'a A::PipelineLayout,
1177    /// The format of any vertex buffers used with this pipeline.
1178    pub vertex_buffers: &'a [VertexBufferLayout<'a>],
1179    /// The vertex stage for this pipeline.
1180    pub vertex_stage: ProgrammableStage<'a, A>,
1181    /// The properties of the pipeline at the primitive assembly and rasterization level.
1182    pub primitive: wgt::PrimitiveState,
1183    /// The effect of draw calls on the depth and stencil aspects of the output target, if any.
1184    pub depth_stencil: Option<wgt::DepthStencilState>,
1185    /// The multi-sampling properties of the pipeline.
1186    pub multisample: wgt::MultisampleState,
1187    /// The fragment stage for this pipeline.
1188    pub fragment_stage: Option<ProgrammableStage<'a, A>>,
1189    /// The effect of draw calls on the color aspect of the output target.
1190    pub color_targets: &'a [Option<wgt::ColorTargetState>],
1191    /// If the pipeline will be used with a multiview render pass, this indicates how many array
1192    /// layers the attachments will have.
1193    pub multiview: Option<NonZeroU32>,
1194}
1195
1196#[derive(Debug, Clone)]
1197pub struct SurfaceConfiguration {
1198    /// Number of textures in the swap chain. Must be in
1199    /// `SurfaceCapabilities::swap_chain_size` range.
1200    pub swap_chain_size: u32,
1201    /// Vertical synchronization mode.
1202    pub present_mode: wgt::PresentMode,
1203    /// Alpha composition mode.
1204    pub composite_alpha_mode: wgt::CompositeAlphaMode,
1205    /// Format of the surface textures.
1206    pub format: wgt::TextureFormat,
1207    /// Requested texture extent. Must be in
1208    /// `SurfaceCapabilities::extents` range.
1209    pub extent: wgt::Extent3d,
1210    /// Allowed usage of surface textures,
1211    pub usage: TextureUses,
1212    /// Allows views of swapchain texture to have a different format
1213    /// than the texture does.
1214    pub view_formats: Vec<wgt::TextureFormat>,
1215}
1216
1217#[derive(Debug, Clone)]
1218pub struct Rect<T> {
1219    pub x: T,
1220    pub y: T,
1221    pub w: T,
1222    pub h: T,
1223}
1224
1225#[derive(Debug, Clone)]
1226pub struct BufferBarrier<'a, A: Api> {
1227    pub buffer: &'a A::Buffer,
1228    pub usage: Range<BufferUses>,
1229}
1230
1231#[derive(Debug, Clone)]
1232pub struct TextureBarrier<'a, A: Api> {
1233    pub texture: &'a A::Texture,
1234    pub range: wgt::ImageSubresourceRange,
1235    pub usage: Range<TextureUses>,
1236}
1237
1238#[derive(Clone, Copy, Debug)]
1239pub struct BufferCopy {
1240    pub src_offset: wgt::BufferAddress,
1241    pub dst_offset: wgt::BufferAddress,
1242    pub size: wgt::BufferSize,
1243}
1244
1245#[derive(Clone, Debug)]
1246pub struct TextureCopyBase {
1247    pub mip_level: u32,
1248    pub array_layer: u32,
1249    /// Origin within a texture.
1250    /// Note: for 1D and 2D textures, Z must be 0.
1251    pub origin: wgt::Origin3d,
1252    pub aspect: FormatAspects,
1253}
1254
1255#[derive(Clone, Copy, Debug)]
1256pub struct CopyExtent {
1257    pub width: u32,
1258    pub height: u32,
1259    pub depth: u32,
1260}
1261
1262#[derive(Clone, Debug)]
1263pub struct TextureCopy {
1264    pub src_base: TextureCopyBase,
1265    pub dst_base: TextureCopyBase,
1266    pub size: CopyExtent,
1267}
1268
1269#[derive(Clone, Debug)]
1270pub struct BufferTextureCopy {
1271    pub buffer_layout: wgt::ImageDataLayout,
1272    pub texture_base: TextureCopyBase,
1273    pub size: CopyExtent,
1274}
1275
1276#[derive(Debug)]
1277pub struct Attachment<'a, A: Api> {
1278    pub view: &'a A::TextureView,
1279    /// Contains either a single mutating usage as a target,
1280    /// or a valid combination of read-only usages.
1281    pub usage: TextureUses,
1282}
1283
1284// Rust gets confused about the impl requirements for `A`
1285impl<A: Api> Clone for Attachment<'_, A> {
1286    fn clone(&self) -> Self {
1287        Self {
1288            view: self.view,
1289            usage: self.usage,
1290        }
1291    }
1292}
1293
1294#[derive(Debug)]
1295pub struct ColorAttachment<'a, A: Api> {
1296    pub target: Attachment<'a, A>,
1297    pub resolve_target: Option<Attachment<'a, A>>,
1298    pub ops: AttachmentOps,
1299    pub clear_value: wgt::Color,
1300}
1301
1302// Rust gets confused about the impl requirements for `A`
1303impl<A: Api> Clone for ColorAttachment<'_, A> {
1304    fn clone(&self) -> Self {
1305        Self {
1306            target: self.target.clone(),
1307            resolve_target: self.resolve_target.clone(),
1308            ops: self.ops,
1309            clear_value: self.clear_value,
1310        }
1311    }
1312}
1313
1314#[derive(Clone, Debug)]
1315pub struct DepthStencilAttachment<'a, A: Api> {
1316    pub target: Attachment<'a, A>,
1317    pub depth_ops: AttachmentOps,
1318    pub stencil_ops: AttachmentOps,
1319    pub clear_value: (f32, u32),
1320}
1321
1322#[derive(Debug)]
1323pub struct RenderPassTimestampWrites<'a, A: Api> {
1324    pub query_set: &'a A::QuerySet,
1325    pub beginning_of_pass_write_index: Option<u32>,
1326    pub end_of_pass_write_index: Option<u32>,
1327}
1328
1329// Rust gets confused about the impl requirements for `A`
1330impl<A: Api> Clone for RenderPassTimestampWrites<'_, A> {
1331    fn clone(&self) -> Self {
1332        Self {
1333            query_set: self.query_set,
1334            beginning_of_pass_write_index: self.beginning_of_pass_write_index,
1335            end_of_pass_write_index: self.end_of_pass_write_index,
1336        }
1337    }
1338}
1339
1340#[derive(Clone, Debug)]
1341pub struct RenderPassDescriptor<'a, A: Api> {
1342    pub label: Label<'a>,
1343    pub extent: wgt::Extent3d,
1344    pub sample_count: u32,
1345    pub color_attachments: &'a [Option<ColorAttachment<'a, A>>],
1346    pub depth_stencil_attachment: Option<DepthStencilAttachment<'a, A>>,
1347    pub multiview: Option<NonZeroU32>,
1348    pub timestamp_writes: Option<RenderPassTimestampWrites<'a, A>>,
1349    pub occlusion_query_set: Option<&'a A::QuerySet>,
1350}
1351
1352#[derive(Debug)]
1353pub struct ComputePassTimestampWrites<'a, A: Api> {
1354    pub query_set: &'a A::QuerySet,
1355    pub beginning_of_pass_write_index: Option<u32>,
1356    pub end_of_pass_write_index: Option<u32>,
1357}
1358
1359// Rust gets confused about the impl requirements for `A`
1360impl<A: Api> Clone for ComputePassTimestampWrites<'_, A> {
1361    fn clone(&self) -> Self {
1362        Self {
1363            query_set: self.query_set,
1364            beginning_of_pass_write_index: self.beginning_of_pass_write_index,
1365            end_of_pass_write_index: self.end_of_pass_write_index,
1366        }
1367    }
1368}
1369
1370#[derive(Clone, Debug)]
1371pub struct ComputePassDescriptor<'a, A: Api> {
1372    pub label: Label<'a>,
1373    pub timestamp_writes: Option<ComputePassTimestampWrites<'a, A>>,
1374}
1375
1376/// Stores if any API validation error has occurred in this process
1377/// since it was last reset.
1378///
1379/// This is used for internal wgpu testing only and _must not_ be used
1380/// as a way to check for errors.
1381///
1382/// This works as a static because `cargo nextest` runs all of our
1383/// tests in separate processes, so each test gets its own canary.
1384///
1385/// This prevents the issue of one validation error terminating the
1386/// entire process.
1387pub static VALIDATION_CANARY: ValidationCanary = ValidationCanary {
1388    inner: AtomicBool::new(false),
1389};
1390
1391/// Flag for internal testing.
1392pub struct ValidationCanary {
1393    inner: AtomicBool,
1394}
1395
1396impl ValidationCanary {
1397    #[allow(dead_code)] // in some configurations this function is dead
1398    fn set(&self) {
1399        self.inner.store(true, std::sync::atomic::Ordering::SeqCst);
1400    }
1401
1402    /// Returns true if any API validation error has occurred in this process
1403    /// since the last call to this function.
1404    pub fn get_and_reset(&self) -> bool {
1405        self.inner.swap(false, std::sync::atomic::Ordering::SeqCst)
1406    }
1407}
1408
1409#[test]
1410fn test_default_limits() {
1411    let limits = wgt::Limits::default();
1412    assert!(limits.max_bind_groups <= MAX_BIND_GROUPS as u32);
1413}