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