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 #![allow(
18     // for `if_then_panic` until it reaches stable
19     unknown_lints,
20     // We use loops for getting early-out of scope without closures.
21     clippy::never_loop,
22     // We don't use syntax sugar where it's not necessary.
23     clippy::match_like_matches_macro,
24     // Redundant matching is more explicit.
25     clippy::redundant_pattern_matching,
26     // Explicit lifetimes are often easier to reason about.
27     clippy::needless_lifetimes,
28     // No need for defaults in the internal types.
29     clippy::new_without_default,
30     // Matches are good and extendable, no need to make an exception here.
31     clippy::single_match,
32     // Push commands are more regular than macros.
33     clippy::vec_init_then_push,
34     // "if panic" is a good uniform construct.
35     clippy::if_then_panic,
36     // We unsafe impl `Send` for a reason.
37     clippy::non_send_fields_in_send_ty,
38     // TODO!
39     clippy::missing_safety_doc,
40 )]
41 #![warn(
42     trivial_casts,
43     trivial_numeric_casts,
44     unused_extern_crates,
45     unused_qualifications,
46     // We don't match on a reference, unless required.
47     clippy::pattern_type_mismatch,
48 )]
49 
50 #[cfg(all(feature = "metal", not(any(target_os = "macos", target_os = "ios"))))]
51 compile_error!("Metal API enabled on non-Apple OS. If your project is not using resolver=\"2\" in Cargo.toml, it should.");
52 #[cfg(all(feature = "dx12", not(windows)))]
53 compile_error!("DX12 API enabled on non-Windows OS. If your project is not using resolver=\"2\" in Cargo.toml, it should.");
54 
55 #[cfg(all(feature = "dx12", windows))]
56 mod dx12;
57 mod empty;
58 #[cfg(all(feature = "gles"))]
59 mod gles;
60 #[cfg(all(feature = "metal"))]
61 mod metal;
62 #[cfg(feature = "vulkan")]
63 mod vulkan;
64 
65 pub mod auxil;
66 pub mod api {
67     #[cfg(feature = "dx12")]
68     pub use super::dx12::Api as Dx12;
69     pub use super::empty::Api as Empty;
70     #[cfg(feature = "gles")]
71     pub use super::gles::Api as Gles;
72     #[cfg(feature = "metal")]
73     pub use super::metal::Api as Metal;
74     #[cfg(feature = "vulkan")]
75     pub use super::vulkan::Api as Vulkan;
76 }
77 
78 #[cfg(feature = "vulkan")]
79 pub use vulkan::UpdateAfterBindTypes;
80 
81 use std::{
82     borrow::Borrow,
83     fmt,
84     num::{NonZeroU32, NonZeroU8},
85     ops::{Range, RangeInclusive},
86     ptr::NonNull,
87 };
88 
89 use bitflags::bitflags;
90 use thiserror::Error;
91 
92 pub const MAX_ANISOTROPY: u8 = 16;
93 pub const MAX_BIND_GROUPS: usize = 8;
94 pub const MAX_VERTEX_BUFFERS: usize = 16;
95 pub const MAX_COLOR_TARGETS: usize = 4;
96 pub const MAX_MIP_LEVELS: u32 = 16;
97 /// Size of a single occlusion/timestamp query, when copied into a buffer, in bytes.
98 pub const QUERY_SIZE: wgt::BufferAddress = 8;
99 
100 pub type Label<'a> = Option<&'a str>;
101 pub type MemoryRange = Range<wgt::BufferAddress>;
102 pub type FenceValue = u64;
103 
104 #[derive(Clone, Debug, PartialEq, Error)]
105 pub enum DeviceError {
106     #[error("out of memory")]
107     OutOfMemory,
108     #[error("device is lost")]
109     Lost,
110 }
111 
112 #[derive(Clone, Debug, PartialEq, Error)]
113 pub enum ShaderError {
114     #[error("compilation failed: {0:?}")]
115     Compilation(String),
116     #[error(transparent)]
117     Device(#[from] DeviceError),
118 }
119 
120 #[derive(Clone, Debug, PartialEq, Error)]
121 pub enum PipelineError {
122     #[error("linkage failed for stage {0:?}: {1}")]
123     Linkage(wgt::ShaderStages, String),
124     #[error("entry point for stage {0:?} is invalid")]
125     EntryPoint(naga::ShaderStage),
126     #[error(transparent)]
127     Device(#[from] DeviceError),
128 }
129 
130 #[derive(Clone, Debug, PartialEq, Error)]
131 pub enum SurfaceError {
132     #[error("surface is lost")]
133     Lost,
134     #[error("surface is outdated, needs to be re-created")]
135     Outdated,
136     #[error(transparent)]
137     Device(#[from] DeviceError),
138     #[error("other reason: {0}")]
139     Other(&'static str),
140 }
141 
142 #[derive(Clone, Debug, PartialEq, Error)]
143 #[error("Not supported")]
144 pub struct InstanceError;
145 
146 pub trait Api: Clone + Sized {
147     type Instance: Instance<Self>;
148     type Surface: Surface<Self>;
149     type Adapter: Adapter<Self>;
150     type Device: Device<Self>;
151 
152     type Queue: Queue<Self>;
153     type CommandEncoder: CommandEncoder<Self>;
154     type CommandBuffer: Send + Sync;
155 
156     type Buffer: fmt::Debug + Send + Sync + 'static;
157     type Texture: fmt::Debug + Send + Sync + 'static;
158     type SurfaceTexture: fmt::Debug + Send + Sync + Borrow<Self::Texture>;
159     type TextureView: fmt::Debug + Send + Sync;
160     type Sampler: fmt::Debug + Send + Sync;
161     type QuerySet: fmt::Debug + Send + Sync;
162     type Fence: fmt::Debug + Send + Sync;
163 
164     type BindGroupLayout: Send + Sync;
165     type BindGroup: fmt::Debug + Send + Sync;
166     type PipelineLayout: Send + Sync;
167     type ShaderModule: fmt::Debug + Send + Sync;
168     type RenderPipeline: Send + Sync;
169     type ComputePipeline: Send + Sync;
170 }
171 
172 pub trait Instance<A: Api>: Sized + Send + Sync {
init(desc: &InstanceDescriptor) -> Result<Self, InstanceError>173     unsafe fn init(desc: &InstanceDescriptor) -> Result<Self, InstanceError>;
create_surface( &self, rwh: &impl raw_window_handle::HasRawWindowHandle, ) -> Result<A::Surface, InstanceError>174     unsafe fn create_surface(
175         &self,
176         rwh: &impl raw_window_handle::HasRawWindowHandle,
177     ) -> Result<A::Surface, InstanceError>;
destroy_surface(&self, surface: A::Surface)178     unsafe fn destroy_surface(&self, surface: A::Surface);
enumerate_adapters(&self) -> Vec<ExposedAdapter<A>>179     unsafe fn enumerate_adapters(&self) -> Vec<ExposedAdapter<A>>;
180 }
181 
182 pub trait Surface<A: Api>: Send + Sync {
configure( &mut self, device: &A::Device, config: &SurfaceConfiguration, ) -> Result<(), SurfaceError>183     unsafe fn configure(
184         &mut self,
185         device: &A::Device,
186         config: &SurfaceConfiguration,
187     ) -> Result<(), SurfaceError>;
188 
unconfigure(&mut self, device: &A::Device)189     unsafe fn unconfigure(&mut self, device: &A::Device);
190 
191     /// Returns `None` on timing out.
acquire_texture( &mut self, timeout_ms: u32, ) -> Result<Option<AcquiredSurfaceTexture<A>>, SurfaceError>192     unsafe fn acquire_texture(
193         &mut self,
194         timeout_ms: u32,
195     ) -> Result<Option<AcquiredSurfaceTexture<A>>, SurfaceError>;
discard_texture(&mut self, texture: A::SurfaceTexture)196     unsafe fn discard_texture(&mut self, texture: A::SurfaceTexture);
197 }
198 
199 pub trait Adapter<A: Api>: Send + Sync {
open( &self, features: wgt::Features, limits: &wgt::Limits, ) -> Result<OpenDevice<A>, DeviceError>200     unsafe fn open(
201         &self,
202         features: wgt::Features,
203         limits: &wgt::Limits,
204     ) -> Result<OpenDevice<A>, DeviceError>;
205 
206     /// Return the set of supported capabilities for a texture format.
texture_format_capabilities( &self, format: wgt::TextureFormat, ) -> TextureFormatCapabilities207     unsafe fn texture_format_capabilities(
208         &self,
209         format: wgt::TextureFormat,
210     ) -> TextureFormatCapabilities;
211 
212     /// Returns the capabilities of working with a specified surface.
213     ///
214     /// `None` means presentation is not supported for it.
surface_capabilities(&self, surface: &A::Surface) -> Option<SurfaceCapabilities>215     unsafe fn surface_capabilities(&self, surface: &A::Surface) -> Option<SurfaceCapabilities>;
216 }
217 
218 pub trait Device<A: Api>: Send + Sync {
219     /// Exit connection to this logical device.
exit(self, queue: A::Queue)220     unsafe fn exit(self, queue: A::Queue);
221     /// Creates a new buffer.
222     ///
223     /// The initial usage is `BufferUses::empty()`.
create_buffer(&self, desc: &BufferDescriptor) -> Result<A::Buffer, DeviceError>224     unsafe fn create_buffer(&self, desc: &BufferDescriptor) -> Result<A::Buffer, DeviceError>;
destroy_buffer(&self, buffer: A::Buffer)225     unsafe fn destroy_buffer(&self, buffer: A::Buffer);
226     //TODO: clarify if zero-sized mapping is allowed
map_buffer( &self, buffer: &A::Buffer, range: MemoryRange, ) -> Result<BufferMapping, DeviceError>227     unsafe fn map_buffer(
228         &self,
229         buffer: &A::Buffer,
230         range: MemoryRange,
231     ) -> Result<BufferMapping, DeviceError>;
unmap_buffer(&self, buffer: &A::Buffer) -> Result<(), DeviceError>232     unsafe fn unmap_buffer(&self, buffer: &A::Buffer) -> Result<(), DeviceError>;
flush_mapped_ranges<I>(&self, buffer: &A::Buffer, ranges: I) where I: Iterator<Item = MemoryRange>233     unsafe fn flush_mapped_ranges<I>(&self, buffer: &A::Buffer, ranges: I)
234     where
235         I: Iterator<Item = MemoryRange>;
invalidate_mapped_ranges<I>(&self, buffer: &A::Buffer, ranges: I) where I: Iterator<Item = MemoryRange>236     unsafe fn invalidate_mapped_ranges<I>(&self, buffer: &A::Buffer, ranges: I)
237     where
238         I: Iterator<Item = MemoryRange>;
239 
240     /// Creates a new texture.
241     ///
242     /// The initial usage for all subresources is `TextureUses::UNINITIALIZED`.
create_texture(&self, desc: &TextureDescriptor) -> Result<A::Texture, DeviceError>243     unsafe fn create_texture(&self, desc: &TextureDescriptor) -> Result<A::Texture, DeviceError>;
destroy_texture(&self, texture: A::Texture)244     unsafe fn destroy_texture(&self, texture: A::Texture);
create_texture_view( &self, texture: &A::Texture, desc: &TextureViewDescriptor, ) -> Result<A::TextureView, DeviceError>245     unsafe fn create_texture_view(
246         &self,
247         texture: &A::Texture,
248         desc: &TextureViewDescriptor,
249     ) -> Result<A::TextureView, DeviceError>;
destroy_texture_view(&self, view: A::TextureView)250     unsafe fn destroy_texture_view(&self, view: A::TextureView);
create_sampler(&self, desc: &SamplerDescriptor) -> Result<A::Sampler, DeviceError>251     unsafe fn create_sampler(&self, desc: &SamplerDescriptor) -> Result<A::Sampler, DeviceError>;
destroy_sampler(&self, sampler: A::Sampler)252     unsafe fn destroy_sampler(&self, sampler: A::Sampler);
253 
create_command_encoder( &self, desc: &CommandEncoderDescriptor<A>, ) -> Result<A::CommandEncoder, DeviceError>254     unsafe fn create_command_encoder(
255         &self,
256         desc: &CommandEncoderDescriptor<A>,
257     ) -> Result<A::CommandEncoder, DeviceError>;
destroy_command_encoder(&self, pool: A::CommandEncoder)258     unsafe fn destroy_command_encoder(&self, pool: A::CommandEncoder);
259 
260     /// Creates a bind group layout.
create_bind_group_layout( &self, desc: &BindGroupLayoutDescriptor, ) -> Result<A::BindGroupLayout, DeviceError>261     unsafe fn create_bind_group_layout(
262         &self,
263         desc: &BindGroupLayoutDescriptor,
264     ) -> Result<A::BindGroupLayout, DeviceError>;
destroy_bind_group_layout(&self, bg_layout: A::BindGroupLayout)265     unsafe fn destroy_bind_group_layout(&self, bg_layout: A::BindGroupLayout);
create_pipeline_layout( &self, desc: &PipelineLayoutDescriptor<A>, ) -> Result<A::PipelineLayout, DeviceError>266     unsafe fn create_pipeline_layout(
267         &self,
268         desc: &PipelineLayoutDescriptor<A>,
269     ) -> Result<A::PipelineLayout, DeviceError>;
destroy_pipeline_layout(&self, pipeline_layout: A::PipelineLayout)270     unsafe fn destroy_pipeline_layout(&self, pipeline_layout: A::PipelineLayout);
create_bind_group( &self, desc: &BindGroupDescriptor<A>, ) -> Result<A::BindGroup, DeviceError>271     unsafe fn create_bind_group(
272         &self,
273         desc: &BindGroupDescriptor<A>,
274     ) -> Result<A::BindGroup, DeviceError>;
destroy_bind_group(&self, group: A::BindGroup)275     unsafe fn destroy_bind_group(&self, group: A::BindGroup);
276 
create_shader_module( &self, desc: &ShaderModuleDescriptor, shader: ShaderInput, ) -> Result<A::ShaderModule, ShaderError>277     unsafe fn create_shader_module(
278         &self,
279         desc: &ShaderModuleDescriptor,
280         shader: ShaderInput,
281     ) -> Result<A::ShaderModule, ShaderError>;
destroy_shader_module(&self, module: A::ShaderModule)282     unsafe fn destroy_shader_module(&self, module: A::ShaderModule);
create_render_pipeline( &self, desc: &RenderPipelineDescriptor<A>, ) -> Result<A::RenderPipeline, PipelineError>283     unsafe fn create_render_pipeline(
284         &self,
285         desc: &RenderPipelineDescriptor<A>,
286     ) -> Result<A::RenderPipeline, PipelineError>;
destroy_render_pipeline(&self, pipeline: A::RenderPipeline)287     unsafe fn destroy_render_pipeline(&self, pipeline: A::RenderPipeline);
create_compute_pipeline( &self, desc: &ComputePipelineDescriptor<A>, ) -> Result<A::ComputePipeline, PipelineError>288     unsafe fn create_compute_pipeline(
289         &self,
290         desc: &ComputePipelineDescriptor<A>,
291     ) -> Result<A::ComputePipeline, PipelineError>;
destroy_compute_pipeline(&self, pipeline: A::ComputePipeline)292     unsafe fn destroy_compute_pipeline(&self, pipeline: A::ComputePipeline);
293 
create_query_set( &self, desc: &wgt::QuerySetDescriptor<Label>, ) -> Result<A::QuerySet, DeviceError>294     unsafe fn create_query_set(
295         &self,
296         desc: &wgt::QuerySetDescriptor<Label>,
297     ) -> Result<A::QuerySet, DeviceError>;
destroy_query_set(&self, set: A::QuerySet)298     unsafe fn destroy_query_set(&self, set: A::QuerySet);
create_fence(&self) -> Result<A::Fence, DeviceError>299     unsafe fn create_fence(&self) -> Result<A::Fence, DeviceError>;
destroy_fence(&self, fence: A::Fence)300     unsafe fn destroy_fence(&self, fence: A::Fence);
get_fence_value(&self, fence: &A::Fence) -> Result<FenceValue, DeviceError>301     unsafe fn get_fence_value(&self, fence: &A::Fence) -> Result<FenceValue, DeviceError>;
wait( &self, fence: &A::Fence, value: FenceValue, timeout_ms: u32, ) -> Result<bool, DeviceError>302     unsafe fn wait(
303         &self,
304         fence: &A::Fence,
305         value: FenceValue,
306         timeout_ms: u32,
307     ) -> Result<bool, DeviceError>;
308 
start_capture(&self) -> bool309     unsafe fn start_capture(&self) -> bool;
stop_capture(&self)310     unsafe fn stop_capture(&self);
311 }
312 
313 pub trait Queue<A: Api>: Send + Sync {
314     /// Submits the command buffers for execution on GPU.
315     ///
316     /// Valid usage:
317     /// - all of the command buffers were created from command pools
318     ///   that are associated with this queue.
319     /// - all of the command buffers had `CommadBuffer::finish()` called.
submit( &mut self, command_buffers: &[&A::CommandBuffer], signal_fence: Option<(&mut A::Fence, FenceValue)>, ) -> Result<(), DeviceError>320     unsafe fn submit(
321         &mut self,
322         command_buffers: &[&A::CommandBuffer],
323         signal_fence: Option<(&mut A::Fence, FenceValue)>,
324     ) -> Result<(), DeviceError>;
present( &mut self, surface: &mut A::Surface, texture: A::SurfaceTexture, ) -> Result<(), SurfaceError>325     unsafe fn present(
326         &mut self,
327         surface: &mut A::Surface,
328         texture: A::SurfaceTexture,
329     ) -> Result<(), SurfaceError>;
get_timestamp_period(&self) -> f32330     unsafe fn get_timestamp_period(&self) -> f32;
331 }
332 
333 /// Encoder for commands in command buffers.
334 /// Serves as a parent for all the encoded command buffers.
335 /// Works in bursts of action: one or more command buffers are recorded,
336 /// then submitted to a queue, and then it needs to be `reset_all()`.
337 pub trait CommandEncoder<A: Api>: Send + Sync {
338     /// Begin encoding a new command buffer.
begin_encoding(&mut self, label: Label) -> Result<(), DeviceError>339     unsafe fn begin_encoding(&mut self, label: Label) -> Result<(), DeviceError>;
340     /// Discard currently recorded list, if any.
discard_encoding(&mut self)341     unsafe fn discard_encoding(&mut self);
end_encoding(&mut self) -> Result<A::CommandBuffer, DeviceError>342     unsafe fn end_encoding(&mut self) -> Result<A::CommandBuffer, DeviceError>;
343     /// Reclaims all resources that are allocated for this encoder.
344     /// Must get all of the produced command buffers back,
345     /// and they must not be used by GPU at this moment.
reset_all<I>(&mut self, command_buffers: I) where I: Iterator<Item = A::CommandBuffer>346     unsafe fn reset_all<I>(&mut self, command_buffers: I)
347     where
348         I: Iterator<Item = A::CommandBuffer>;
349 
transition_buffers<'a, T>(&mut self, barriers: T) where T: Iterator<Item = BufferBarrier<'a, A>>350     unsafe fn transition_buffers<'a, T>(&mut self, barriers: T)
351     where
352         T: Iterator<Item = BufferBarrier<'a, A>>;
353 
transition_textures<'a, T>(&mut self, barriers: T) where T: Iterator<Item = TextureBarrier<'a, A>>354     unsafe fn transition_textures<'a, T>(&mut self, barriers: T)
355     where
356         T: Iterator<Item = TextureBarrier<'a, A>>;
357 
358     // copy operations
359 
clear_buffer(&mut self, buffer: &A::Buffer, range: MemoryRange)360     unsafe fn clear_buffer(&mut self, buffer: &A::Buffer, range: MemoryRange);
361 
copy_buffer_to_buffer<T>(&mut self, src: &A::Buffer, dst: &A::Buffer, regions: T) where T: Iterator<Item = BufferCopy>362     unsafe fn copy_buffer_to_buffer<T>(&mut self, src: &A::Buffer, dst: &A::Buffer, regions: T)
363     where
364         T: Iterator<Item = BufferCopy>;
365 
366     /// Copy from one texture to another.
367     /// Works with a single array layer.
368     /// Note: `dst` current usage has to be `TextureUses::COPY_DST`.
369     /// Note: the copy extent is in physical size (rounded to the block size)
copy_texture_to_texture<T>( &mut self, src: &A::Texture, src_usage: TextureUses, dst: &A::Texture, regions: T, ) where T: Iterator<Item = TextureCopy>370     unsafe fn copy_texture_to_texture<T>(
371         &mut self,
372         src: &A::Texture,
373         src_usage: TextureUses,
374         dst: &A::Texture,
375         regions: T,
376     ) where
377         T: Iterator<Item = TextureCopy>;
378 
379     /// Copy from buffer to texture.
380     /// Works with a single array layer.
381     /// Note: `dst` current usage has to be `TextureUses::COPY_DST`.
382     /// Note: the copy extent is in physical size (rounded to the block size)
copy_buffer_to_texture<T>(&mut self, src: &A::Buffer, dst: &A::Texture, regions: T) where T: Iterator<Item = BufferTextureCopy>383     unsafe fn copy_buffer_to_texture<T>(&mut self, src: &A::Buffer, dst: &A::Texture, regions: T)
384     where
385         T: Iterator<Item = BufferTextureCopy>;
386 
387     /// Copy from texture to buffer.
388     /// Works with a single array layer.
389     /// Note: the copy extent is in physical size (rounded to the block size)
copy_texture_to_buffer<T>( &mut self, src: &A::Texture, src_usage: TextureUses, dst: &A::Buffer, regions: T, ) where T: Iterator<Item = BufferTextureCopy>390     unsafe fn copy_texture_to_buffer<T>(
391         &mut self,
392         src: &A::Texture,
393         src_usage: TextureUses,
394         dst: &A::Buffer,
395         regions: T,
396     ) where
397         T: Iterator<Item = BufferTextureCopy>;
398 
399     // pass common
400 
401     /// Sets the bind group at `index` to `group`, assuming the layout
402     /// of all the preceeding groups to be taken from `layout`.
set_bind_group( &mut self, layout: &A::PipelineLayout, index: u32, group: &A::BindGroup, dynamic_offsets: &[wgt::DynamicOffset], )403     unsafe fn set_bind_group(
404         &mut self,
405         layout: &A::PipelineLayout,
406         index: u32,
407         group: &A::BindGroup,
408         dynamic_offsets: &[wgt::DynamicOffset],
409     );
410 
set_push_constants( &mut self, layout: &A::PipelineLayout, stages: wgt::ShaderStages, offset: u32, data: &[u32], )411     unsafe fn set_push_constants(
412         &mut self,
413         layout: &A::PipelineLayout,
414         stages: wgt::ShaderStages,
415         offset: u32,
416         data: &[u32],
417     );
418 
insert_debug_marker(&mut self, label: &str)419     unsafe fn insert_debug_marker(&mut self, label: &str);
begin_debug_marker(&mut self, group_label: &str)420     unsafe fn begin_debug_marker(&mut self, group_label: &str);
end_debug_marker(&mut self)421     unsafe fn end_debug_marker(&mut self);
422 
423     // queries
424 
begin_query(&mut self, set: &A::QuerySet, index: u32)425     unsafe fn begin_query(&mut self, set: &A::QuerySet, index: u32);
end_query(&mut self, set: &A::QuerySet, index: u32)426     unsafe fn end_query(&mut self, set: &A::QuerySet, index: u32);
write_timestamp(&mut self, set: &A::QuerySet, index: u32)427     unsafe fn write_timestamp(&mut self, set: &A::QuerySet, index: u32);
reset_queries(&mut self, set: &A::QuerySet, range: Range<u32>)428     unsafe fn reset_queries(&mut self, set: &A::QuerySet, range: Range<u32>);
copy_query_results( &mut self, set: &A::QuerySet, range: Range<u32>, buffer: &A::Buffer, offset: wgt::BufferAddress, stride: wgt::BufferSize, )429     unsafe fn copy_query_results(
430         &mut self,
431         set: &A::QuerySet,
432         range: Range<u32>,
433         buffer: &A::Buffer,
434         offset: wgt::BufferAddress,
435         stride: wgt::BufferSize,
436     );
437 
438     // render passes
439 
440     // Begins a render pass, clears all active bindings.
begin_render_pass(&mut self, desc: &RenderPassDescriptor<A>)441     unsafe fn begin_render_pass(&mut self, desc: &RenderPassDescriptor<A>);
end_render_pass(&mut self)442     unsafe fn end_render_pass(&mut self);
443 
set_render_pipeline(&mut self, pipeline: &A::RenderPipeline)444     unsafe fn set_render_pipeline(&mut self, pipeline: &A::RenderPipeline);
445 
set_index_buffer<'a>( &mut self, binding: BufferBinding<'a, A>, format: wgt::IndexFormat, )446     unsafe fn set_index_buffer<'a>(
447         &mut self,
448         binding: BufferBinding<'a, A>,
449         format: wgt::IndexFormat,
450     );
set_vertex_buffer<'a>(&mut self, index: u32, binding: BufferBinding<'a, A>)451     unsafe fn set_vertex_buffer<'a>(&mut self, index: u32, binding: BufferBinding<'a, A>);
set_viewport(&mut self, rect: &Rect<f32>, depth_range: Range<f32>)452     unsafe fn set_viewport(&mut self, rect: &Rect<f32>, depth_range: Range<f32>);
set_scissor_rect(&mut self, rect: &Rect<u32>)453     unsafe fn set_scissor_rect(&mut self, rect: &Rect<u32>);
set_stencil_reference(&mut self, value: u32)454     unsafe fn set_stencil_reference(&mut self, value: u32);
set_blend_constants(&mut self, color: &[f32; 4])455     unsafe fn set_blend_constants(&mut self, color: &[f32; 4]);
456 
draw( &mut self, start_vertex: u32, vertex_count: u32, start_instance: u32, instance_count: u32, )457     unsafe fn draw(
458         &mut self,
459         start_vertex: u32,
460         vertex_count: u32,
461         start_instance: u32,
462         instance_count: u32,
463     );
draw_indexed( &mut self, start_index: u32, index_count: u32, base_vertex: i32, start_instance: u32, instance_count: u32, )464     unsafe fn draw_indexed(
465         &mut self,
466         start_index: u32,
467         index_count: u32,
468         base_vertex: i32,
469         start_instance: u32,
470         instance_count: u32,
471     );
draw_indirect( &mut self, buffer: &A::Buffer, offset: wgt::BufferAddress, draw_count: u32, )472     unsafe fn draw_indirect(
473         &mut self,
474         buffer: &A::Buffer,
475         offset: wgt::BufferAddress,
476         draw_count: u32,
477     );
draw_indexed_indirect( &mut self, buffer: &A::Buffer, offset: wgt::BufferAddress, draw_count: u32, )478     unsafe fn draw_indexed_indirect(
479         &mut self,
480         buffer: &A::Buffer,
481         offset: wgt::BufferAddress,
482         draw_count: u32,
483     );
draw_indirect_count( &mut self, buffer: &A::Buffer, offset: wgt::BufferAddress, count_buffer: &A::Buffer, count_offset: wgt::BufferAddress, max_count: u32, )484     unsafe fn draw_indirect_count(
485         &mut self,
486         buffer: &A::Buffer,
487         offset: wgt::BufferAddress,
488         count_buffer: &A::Buffer,
489         count_offset: wgt::BufferAddress,
490         max_count: u32,
491     );
draw_indexed_indirect_count( &mut self, buffer: &A::Buffer, offset: wgt::BufferAddress, count_buffer: &A::Buffer, count_offset: wgt::BufferAddress, max_count: u32, )492     unsafe fn draw_indexed_indirect_count(
493         &mut self,
494         buffer: &A::Buffer,
495         offset: wgt::BufferAddress,
496         count_buffer: &A::Buffer,
497         count_offset: wgt::BufferAddress,
498         max_count: u32,
499     );
500 
501     // compute passes
502 
503     // Begins a compute pass, clears all active bindings.
begin_compute_pass(&mut self, desc: &ComputePassDescriptor)504     unsafe fn begin_compute_pass(&mut self, desc: &ComputePassDescriptor);
end_compute_pass(&mut self)505     unsafe fn end_compute_pass(&mut self);
506 
set_compute_pipeline(&mut self, pipeline: &A::ComputePipeline)507     unsafe fn set_compute_pipeline(&mut self, pipeline: &A::ComputePipeline);
508 
dispatch(&mut self, count: [u32; 3])509     unsafe fn dispatch(&mut self, count: [u32; 3]);
dispatch_indirect(&mut self, buffer: &A::Buffer, offset: wgt::BufferAddress)510     unsafe fn dispatch_indirect(&mut self, buffer: &A::Buffer, offset: wgt::BufferAddress);
511 }
512 
513 bitflags!(
514     /// Instance initialization flags.
515     pub struct InstanceFlags: u32 {
516         /// Generate debug information in shaders and objects.
517         const DEBUG = 1 << 0;
518         /// Enable validation, if possible.
519         const VALIDATION = 1 << 1;
520     }
521 );
522 
523 bitflags!(
524     /// Pipeline layout creation flags.
525     pub struct PipelineLayoutFlags: u32 {
526         /// Include support for base vertex/instance drawing.
527         const BASE_VERTEX_INSTANCE = 1 << 0;
528         /// Include support for num work groups builtin.
529         const NUM_WORK_GROUPS = 1 << 1;
530     }
531 );
532 
533 bitflags!(
534     /// Pipeline layout creation flags.
535     pub struct BindGroupLayoutFlags: u32 {
536         /// Allows for bind group binding arrays to be shorter than the array in the BGL.
537         const PARTIALLY_BOUND = 1 << 0;
538     }
539 );
540 
541 bitflags!(
542     /// Texture format capability flags.
543     pub struct TextureFormatCapabilities: u32 {
544         /// Format can be sampled.
545         const SAMPLED = 1 << 0;
546         /// Format can be sampled with a linear sampler.
547         const SAMPLED_LINEAR = 1 << 1;
548         /// Format can be sampled with a min/max reduction sampler.
549         const SAMPLED_MINMAX = 1 << 2;
550 
551         /// Format can be used as storage with write-only access.
552         const STORAGE = 1 << 3;
553         /// Format can be used as storage with read and read/write access.
554         const STORAGE_READ_WRITE = 1 << 4;
555         /// Format can be used as storage with atomics.
556         const STORAGE_ATOMIC = 1 << 5;
557 
558         /// Format can be used as color and input attachment.
559         const COLOR_ATTACHMENT = 1 << 6;
560         /// Format can be used as color (with blending) and input attachment.
561         const COLOR_ATTACHMENT_BLEND = 1 << 7;
562         /// Format can be used as depth-stencil and input attachment.
563         const DEPTH_STENCIL_ATTACHMENT = 1 << 8;
564 
565         /// Format can be multisampled.
566         const MULTISAMPLE = 1 << 9;
567         /// Format can be used for render pass resolve targets.
568         const MULTISAMPLE_RESOLVE = 1 << 10;
569 
570         /// Format can be copied from.
571         const COPY_SRC = 1 << 11;
572         /// Format can be copied to.
573         const COPY_DST = 1 << 12;
574     }
575 );
576 
577 bitflags!(
578     /// Texture format capability flags.
579     pub struct FormatAspects: u8 {
580         const COLOR = 1 << 0;
581         const DEPTH = 1 << 1;
582         const STENCIL = 1 << 2;
583     }
584 );
585 
586 impl From<wgt::TextureAspect> for FormatAspects {
from(aspect: wgt::TextureAspect) -> Self587     fn from(aspect: wgt::TextureAspect) -> Self {
588         match aspect {
589             wgt::TextureAspect::All => Self::all(),
590             wgt::TextureAspect::DepthOnly => Self::DEPTH,
591             wgt::TextureAspect::StencilOnly => Self::STENCIL,
592         }
593     }
594 }
595 
596 impl From<wgt::TextureFormat> for FormatAspects {
from(format: wgt::TextureFormat) -> Self597     fn from(format: wgt::TextureFormat) -> Self {
598         match format {
599             wgt::TextureFormat::Depth32Float | wgt::TextureFormat::Depth24Plus => Self::DEPTH,
600             wgt::TextureFormat::Depth24PlusStencil8 => Self::DEPTH | Self::STENCIL,
601             _ => Self::COLOR,
602         }
603     }
604 }
605 
606 bitflags!(
607     pub struct MemoryFlags: u32 {
608         const TRANSIENT = 1 << 0;
609         const PREFER_COHERENT = 1 << 1;
610     }
611 );
612 
613 //TODO: it's not intuitive for the backends to consider `LOAD` being optional.
614 
615 bitflags!(
616     pub struct AttachmentOps: u8 {
617         const LOAD = 1 << 0;
618         const STORE = 1 << 1;
619     }
620 );
621 
622 bitflags::bitflags! {
623     /// Similar to `wgt::BufferUsages` but for internal use.
624     pub struct BufferUses: u32 {
625         const MAP_READ = 1 << 0;
626         const MAP_WRITE = 1 << 1;
627         const COPY_SRC = 1 << 2;
628         const COPY_DST = 1 << 3;
629         const INDEX = 1 << 4;
630         const VERTEX = 1 << 5;
631         const UNIFORM = 1 << 6;
632         const STORAGE_READ = 1 << 7;
633         const STORAGE_WRITE = 1 << 8;
634         const INDIRECT = 1 << 9;
635         /// The combination of usages that can be used together (read-only).
636         const INCLUSIVE = Self::MAP_READ.bits | Self::COPY_SRC.bits |
637             Self::INDEX.bits | Self::VERTEX.bits | Self::UNIFORM.bits |
638             Self::STORAGE_READ.bits | Self::INDIRECT.bits;
639         /// The combination of exclusive usages (write-only and read-write).
640         /// These usages may still show up with others, but can't automatically be combined.
641         const EXCLUSIVE = Self::MAP_WRITE.bits | Self::COPY_DST.bits | Self::STORAGE_WRITE.bits;
642         /// The combination of all usages that the are guaranteed to be be ordered by the hardware.
643         /// If a usage is not ordered, then even if it doesn't change between draw calls, there
644         /// still need to be pipeline barriers inserted for synchronization.
645         const ORDERED = Self::INCLUSIVE.bits | Self::MAP_WRITE.bits;
646     }
647 }
648 
649 bitflags::bitflags! {
650     /// Similar to `wgt::TextureUsages` but for internal use.
651     pub struct TextureUses: u32 {
652         const COPY_SRC = 1 << 0;
653         const COPY_DST = 1 << 1;
654         const RESOURCE = 1 << 2;
655         const COLOR_TARGET = 1 << 3;
656         const DEPTH_STENCIL_READ = 1 << 4;
657         const DEPTH_STENCIL_WRITE = 1 << 5;
658         const STORAGE_READ = 1 << 6;
659         const STORAGE_WRITE = 1 << 7;
660         /// The combination of usages that can be used together (read-only).
661         const INCLUSIVE = Self::COPY_SRC.bits | Self::RESOURCE.bits | Self::DEPTH_STENCIL_READ.bits;
662         /// The combination of exclusive usages (write-only and read-write).
663         /// These usages may still show up with others, but can't automatically be combined.
664         const EXCLUSIVE = Self::COPY_DST.bits | Self::COLOR_TARGET.bits | Self::DEPTH_STENCIL_WRITE.bits | Self::STORAGE_READ.bits | Self::STORAGE_WRITE.bits;
665         /// The combination of all usages that the are guaranteed to be be ordered by the hardware.
666         /// If a usage is not ordered, then even if it doesn't change between draw calls, there
667         /// still need to be pipeline barriers inserted for synchronization.
668         const ORDERED = Self::INCLUSIVE.bits | Self::COLOR_TARGET.bits | Self::DEPTH_STENCIL_WRITE.bits | Self::STORAGE_READ.bits;
669         //TODO: remove this
670         const UNINITIALIZED = 0xFFFF;
671     }
672 }
673 
674 #[derive(Clone, Debug)]
675 pub struct InstanceDescriptor<'a> {
676     pub name: &'a str,
677     pub flags: InstanceFlags,
678 }
679 
680 #[derive(Clone, Debug)]
681 pub struct Alignments {
682     /// The alignment of the start of the buffer used as a GPU copy source.
683     pub buffer_copy_offset: wgt::BufferSize,
684     /// The alignment of the row pitch of the texture data stored in a buffer that is
685     /// used in a GPU copy operation.
686     pub buffer_copy_pitch: wgt::BufferSize,
687 }
688 
689 #[derive(Clone, Debug)]
690 pub struct Capabilities {
691     pub limits: wgt::Limits,
692     pub alignments: Alignments,
693     pub downlevel: wgt::DownlevelCapabilities,
694 }
695 
696 #[derive(Debug)]
697 pub struct ExposedAdapter<A: Api> {
698     pub adapter: A::Adapter,
699     pub info: wgt::AdapterInfo,
700     pub features: wgt::Features,
701     pub capabilities: Capabilities,
702 }
703 
704 /// Describes information about what a `Surface`'s presentation capabilities are.
705 /// Fetch this with [Adapter::surface_capabilities].
706 #[derive(Debug, Clone)]
707 pub struct SurfaceCapabilities {
708     /// List of supported texture formats.
709     ///
710     /// Must be at least one.
711     pub formats: Vec<wgt::TextureFormat>,
712 
713     /// Range for the swap chain sizes.
714     ///
715     /// - `swap_chain_sizes.start` must be at least 1.
716     /// - `swap_chain_sizes.end` must be larger or equal to `swap_chain_sizes.start`.
717     pub swap_chain_sizes: RangeInclusive<u32>,
718 
719     /// Current extent of the surface, if known.
720     pub current_extent: Option<wgt::Extent3d>,
721 
722     /// Range of supported extents.
723     ///
724     /// `current_extent` must be inside this range.
725     pub extents: RangeInclusive<wgt::Extent3d>,
726 
727     /// Supported texture usage flags.
728     ///
729     /// Must have at least `TextureUses::COLOR_TARGET`
730     pub usage: TextureUses,
731 
732     /// List of supported V-sync modes.
733     ///
734     /// Must be at least one.
735     pub present_modes: Vec<wgt::PresentMode>,
736 
737     /// List of supported alpha composition modes.
738     ///
739     /// Must be at least one.
740     pub composite_alpha_modes: Vec<CompositeAlphaMode>,
741 }
742 
743 #[derive(Debug)]
744 pub struct AcquiredSurfaceTexture<A: Api> {
745     pub texture: A::SurfaceTexture,
746     /// The presentation configuration no longer matches
747     /// the surface properties exactly, but can still be used to present
748     /// to the surface successfully.
749     pub suboptimal: bool,
750 }
751 
752 #[derive(Debug)]
753 pub struct OpenDevice<A: Api> {
754     pub device: A::Device,
755     pub queue: A::Queue,
756 }
757 
758 #[derive(Clone, Debug)]
759 pub struct BufferMapping {
760     pub ptr: NonNull<u8>,
761     pub is_coherent: bool,
762 }
763 
764 #[derive(Clone, Debug)]
765 pub struct BufferDescriptor<'a> {
766     pub label: Label<'a>,
767     pub size: wgt::BufferAddress,
768     pub usage: BufferUses,
769     pub memory_flags: MemoryFlags,
770 }
771 
772 #[derive(Clone, Debug)]
773 pub struct TextureDescriptor<'a> {
774     pub label: Label<'a>,
775     pub size: wgt::Extent3d,
776     pub mip_level_count: u32,
777     pub sample_count: u32,
778     pub dimension: wgt::TextureDimension,
779     pub format: wgt::TextureFormat,
780     pub usage: TextureUses,
781     pub memory_flags: MemoryFlags,
782 }
783 
784 /// TextureView descriptor.
785 ///
786 /// Valid usage:
787 ///. - `format` has to be the same as `TextureDescriptor::format`
788 ///. - `dimension` has to be compatible with `TextureDescriptor::dimension`
789 ///. - `usage` has to be a subset of `TextureDescriptor::usage`
790 ///. - `range` has to be a subset of parent texture
791 #[derive(Clone, Debug)]
792 pub struct TextureViewDescriptor<'a> {
793     pub label: Label<'a>,
794     pub format: wgt::TextureFormat,
795     pub dimension: wgt::TextureViewDimension,
796     pub usage: TextureUses,
797     pub range: wgt::ImageSubresourceRange,
798 }
799 
800 #[derive(Clone, Debug)]
801 pub struct SamplerDescriptor<'a> {
802     pub label: Label<'a>,
803     pub address_modes: [wgt::AddressMode; 3],
804     pub mag_filter: wgt::FilterMode,
805     pub min_filter: wgt::FilterMode,
806     pub mipmap_filter: wgt::FilterMode,
807     pub lod_clamp: Option<Range<f32>>,
808     pub compare: Option<wgt::CompareFunction>,
809     pub anisotropy_clamp: Option<NonZeroU8>,
810     pub border_color: Option<wgt::SamplerBorderColor>,
811 }
812 
813 /// BindGroupLayout descriptor.
814 ///
815 /// Valid usage:
816 /// - `entries` are sorted by ascending `wgt::BindGroupLayoutEntry::binding`
817 #[derive(Clone, Debug)]
818 pub struct BindGroupLayoutDescriptor<'a> {
819     pub label: Label<'a>,
820     pub flags: BindGroupLayoutFlags,
821     pub entries: &'a [wgt::BindGroupLayoutEntry],
822 }
823 
824 #[derive(Clone, Debug)]
825 pub struct PipelineLayoutDescriptor<'a, A: Api> {
826     pub label: Label<'a>,
827     pub flags: PipelineLayoutFlags,
828     pub bind_group_layouts: &'a [&'a A::BindGroupLayout],
829     pub push_constant_ranges: &'a [wgt::PushConstantRange],
830 }
831 
832 #[derive(Debug)]
833 pub struct BufferBinding<'a, A: Api> {
834     pub buffer: &'a A::Buffer,
835     pub offset: wgt::BufferAddress,
836     pub size: Option<wgt::BufferSize>,
837 }
838 
839 // Rust gets confused about the impl requirements for `A`
840 impl<A: Api> Clone for BufferBinding<'_, A> {
clone(&self) -> Self841     fn clone(&self) -> Self {
842         Self {
843             buffer: self.buffer,
844             offset: self.offset,
845             size: self.size,
846         }
847     }
848 }
849 
850 #[derive(Debug)]
851 pub struct TextureBinding<'a, A: Api> {
852     pub view: &'a A::TextureView,
853     pub usage: TextureUses,
854 }
855 
856 // Rust gets confused about the impl requirements for `A`
857 impl<A: Api> Clone for TextureBinding<'_, A> {
clone(&self) -> Self858     fn clone(&self) -> Self {
859         Self {
860             view: self.view,
861             usage: self.usage,
862         }
863     }
864 }
865 
866 #[derive(Clone, Debug)]
867 pub struct BindGroupEntry {
868     pub binding: u32,
869     pub resource_index: u32,
870     pub count: u32,
871 }
872 
873 /// BindGroup descriptor.
874 ///
875 /// Valid usage:
876 ///. - `entries` has to be sorted by ascending `BindGroupEntry::binding`
877 ///. - `entries` has to have the same set of `BindGroupEntry::binding` as `layout`
878 ///. - each entry has to be compatible with the `layout`
879 ///. - each entry's `BindGroupEntry::resource_index` is within range
880 ///    of the corresponding resource array, selected by the relevant
881 ///    `BindGroupLayoutEntry`.
882 #[derive(Clone, Debug)]
883 pub struct BindGroupDescriptor<'a, A: Api> {
884     pub label: Label<'a>,
885     pub layout: &'a A::BindGroupLayout,
886     pub buffers: &'a [BufferBinding<'a, A>],
887     pub samplers: &'a [&'a A::Sampler],
888     pub textures: &'a [TextureBinding<'a, A>],
889     pub entries: &'a [BindGroupEntry],
890 }
891 
892 #[derive(Clone, Debug)]
893 pub struct CommandEncoderDescriptor<'a, A: Api> {
894     pub label: Label<'a>,
895     pub queue: &'a A::Queue,
896 }
897 
898 /// Naga shader module.
899 pub struct NagaShader {
900     /// Shader module IR.
901     pub module: naga::Module,
902     /// Analysis information of the module.
903     pub info: naga::valid::ModuleInfo,
904 }
905 
906 // Custom implementation avoids the need to generate Debug impl code
907 // for the whole Naga module and info.
908 impl fmt::Debug for NagaShader {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result909     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
910         write!(formatter, "Naga shader")
911     }
912 }
913 
914 /// Shader input.
915 #[allow(clippy::large_enum_variant)]
916 pub enum ShaderInput<'a> {
917     Naga(NagaShader),
918     SpirV(&'a [u32]),
919 }
920 
921 pub struct ShaderModuleDescriptor<'a> {
922     pub label: Label<'a>,
923     pub runtime_checks: bool,
924 }
925 
926 /// Describes a programmable pipeline stage.
927 #[derive(Debug)]
928 pub struct ProgrammableStage<'a, A: Api> {
929     /// The compiled shader module for this stage.
930     pub module: &'a A::ShaderModule,
931     /// The name of the entry point in the compiled shader. There must be a function that returns
932     /// void with this name in the shader.
933     pub entry_point: &'a str,
934 }
935 
936 // Rust gets confused about the impl requirements for `A`
937 impl<A: Api> Clone for ProgrammableStage<'_, A> {
clone(&self) -> Self938     fn clone(&self) -> Self {
939         Self {
940             module: self.module,
941             entry_point: self.entry_point,
942         }
943     }
944 }
945 
946 /// Describes a compute pipeline.
947 #[derive(Clone, Debug)]
948 pub struct ComputePipelineDescriptor<'a, A: Api> {
949     pub label: Label<'a>,
950     /// The layout of bind groups for this pipeline.
951     pub layout: &'a A::PipelineLayout,
952     /// The compiled compute stage and its entry point.
953     pub stage: ProgrammableStage<'a, A>,
954 }
955 
956 /// Describes how the vertex buffer is interpreted.
957 #[derive(Clone, Debug)]
958 pub struct VertexBufferLayout<'a> {
959     /// The stride, in bytes, between elements of this buffer.
960     pub array_stride: wgt::BufferAddress,
961     /// How often this vertex buffer is "stepped" forward.
962     pub step_mode: wgt::VertexStepMode,
963     /// The list of attributes which comprise a single vertex.
964     pub attributes: &'a [wgt::VertexAttribute],
965 }
966 
967 /// Describes a render (graphics) pipeline.
968 #[derive(Clone, Debug)]
969 pub struct RenderPipelineDescriptor<'a, A: Api> {
970     pub label: Label<'a>,
971     /// The layout of bind groups for this pipeline.
972     pub layout: &'a A::PipelineLayout,
973     /// The format of any vertex buffers used with this pipeline.
974     pub vertex_buffers: &'a [VertexBufferLayout<'a>],
975     /// The vertex stage for this pipeline.
976     pub vertex_stage: ProgrammableStage<'a, A>,
977     /// The properties of the pipeline at the primitive assembly and rasterization level.
978     pub primitive: wgt::PrimitiveState,
979     /// The effect of draw calls on the depth and stencil aspects of the output target, if any.
980     pub depth_stencil: Option<wgt::DepthStencilState>,
981     /// The multi-sampling properties of the pipeline.
982     pub multisample: wgt::MultisampleState,
983     /// The fragment stage for this pipeline.
984     pub fragment_stage: Option<ProgrammableStage<'a, A>>,
985     /// The effect of draw calls on the color aspect of the output target.
986     pub color_targets: &'a [wgt::ColorTargetState],
987     /// If the pipeline will be used with a multiview render pass, this indicates how many array
988     /// layers the attachments will have.
989     pub multiview: Option<NonZeroU32>,
990 }
991 
992 /// Specifies how the alpha channel of the textures should be handled during (martin mouv i step)
993 /// compositing.
994 #[derive(Debug, Clone, Copy, PartialEq)]
995 pub enum CompositeAlphaMode {
996     /// The alpha channel, if it exists, of the textures is ignored in the
997     /// compositing process. Instead, the textures is treated as if it has a
998     /// constant alpha of 1.0.
999     Opaque,
1000     /// The alpha channel, if it exists, of the textures is respected in the
1001     /// compositing process. The non-alpha channels of the textures are
1002     /// expected to already be multiplied by the alpha channel by the
1003     /// application.
1004     PreMultiplied,
1005     /// The alpha channel, if it exists, of the textures is respected in the
1006     /// compositing process. The non-alpha channels of the textures are not
1007     /// expected to already be multiplied by the alpha channel by the
1008     /// application; instead, the compositor will multiply the non-alpha
1009     /// channels of the texture by the alpha channel during compositing.
1010     PostMultiplied,
1011 }
1012 
1013 #[derive(Debug, Clone)]
1014 pub struct SurfaceConfiguration {
1015     /// Number of textures in the swap chain. Must be in
1016     /// `SurfaceCapabilities::swap_chain_size` range.
1017     pub swap_chain_size: u32,
1018     /// Vertical synchronization mode.
1019     pub present_mode: wgt::PresentMode,
1020     /// Alpha composition mode.
1021     pub composite_alpha_mode: CompositeAlphaMode,
1022     /// Format of the surface textures.
1023     pub format: wgt::TextureFormat,
1024     /// Requested texture extent. Must be in
1025     /// `SurfaceCapabilities::extents` range.
1026     pub extent: wgt::Extent3d,
1027     /// Allowed usage of surface textures,
1028     pub usage: TextureUses,
1029 }
1030 
1031 #[derive(Debug, Clone)]
1032 pub struct Rect<T> {
1033     pub x: T,
1034     pub y: T,
1035     pub w: T,
1036     pub h: T,
1037 }
1038 
1039 #[derive(Debug, Clone)]
1040 pub struct BufferBarrier<'a, A: Api> {
1041     pub buffer: &'a A::Buffer,
1042     pub usage: Range<BufferUses>,
1043 }
1044 
1045 #[derive(Debug, Clone)]
1046 pub struct TextureBarrier<'a, A: Api> {
1047     pub texture: &'a A::Texture,
1048     pub range: wgt::ImageSubresourceRange,
1049     pub usage: Range<TextureUses>,
1050 }
1051 
1052 #[derive(Clone, Copy, Debug)]
1053 pub struct BufferCopy {
1054     pub src_offset: wgt::BufferAddress,
1055     pub dst_offset: wgt::BufferAddress,
1056     pub size: wgt::BufferSize,
1057 }
1058 
1059 #[derive(Clone, Debug)]
1060 pub struct TextureCopyBase {
1061     pub mip_level: u32,
1062     pub array_layer: u32,
1063     /// Origin within a texture.
1064     /// Note: for 1D and 2D textures, Z must be 0.
1065     pub origin: wgt::Origin3d,
1066     pub aspect: FormatAspects,
1067 }
1068 
1069 #[derive(Clone, Copy, Debug)]
1070 pub struct CopyExtent {
1071     pub width: u32,
1072     pub height: u32,
1073     pub depth: u32,
1074 }
1075 
1076 #[derive(Clone, Debug)]
1077 pub struct TextureCopy {
1078     pub src_base: TextureCopyBase,
1079     pub dst_base: TextureCopyBase,
1080     pub size: CopyExtent,
1081 }
1082 
1083 #[derive(Clone, Debug)]
1084 pub struct BufferTextureCopy {
1085     pub buffer_layout: wgt::ImageDataLayout,
1086     pub texture_base: TextureCopyBase,
1087     pub size: CopyExtent,
1088 }
1089 
1090 #[derive(Debug)]
1091 pub struct Attachment<'a, A: Api> {
1092     pub view: &'a A::TextureView,
1093     /// Contains either a single mutating usage as a target,
1094     /// or a valid combination of read-only usages.
1095     pub usage: TextureUses,
1096 }
1097 
1098 // Rust gets confused about the impl requirements for `A`
1099 impl<A: Api> Clone for Attachment<'_, A> {
clone(&self) -> Self1100     fn clone(&self) -> Self {
1101         Self {
1102             view: self.view,
1103             usage: self.usage,
1104         }
1105     }
1106 }
1107 
1108 #[derive(Debug)]
1109 pub struct ColorAttachment<'a, A: Api> {
1110     pub target: Attachment<'a, A>,
1111     pub resolve_target: Option<Attachment<'a, A>>,
1112     pub ops: AttachmentOps,
1113     pub clear_value: wgt::Color,
1114 }
1115 
1116 // Rust gets confused about the impl requirements for `A`
1117 impl<A: Api> Clone for ColorAttachment<'_, A> {
clone(&self) -> Self1118     fn clone(&self) -> Self {
1119         Self {
1120             target: self.target.clone(),
1121             resolve_target: self.resolve_target.clone(),
1122             ops: self.ops,
1123             clear_value: self.clear_value,
1124         }
1125     }
1126 }
1127 
1128 #[derive(Clone, Debug)]
1129 pub struct DepthStencilAttachment<'a, A: Api> {
1130     pub target: Attachment<'a, A>,
1131     pub depth_ops: AttachmentOps,
1132     pub stencil_ops: AttachmentOps,
1133     pub clear_value: (f32, u32),
1134 }
1135 
1136 #[derive(Clone, Debug)]
1137 pub struct RenderPassDescriptor<'a, A: Api> {
1138     pub label: Label<'a>,
1139     pub extent: wgt::Extent3d,
1140     pub sample_count: u32,
1141     pub color_attachments: &'a [ColorAttachment<'a, A>],
1142     pub depth_stencil_attachment: Option<DepthStencilAttachment<'a, A>>,
1143     pub multiview: Option<NonZeroU32>,
1144 }
1145 
1146 #[derive(Clone, Debug)]
1147 pub struct ComputePassDescriptor<'a> {
1148     pub label: Label<'a>,
1149 }
1150 
1151 #[test]
test_default_limits()1152 fn test_default_limits() {
1153     let limits = wgt::Limits::default();
1154     assert!(limits.max_bind_groups <= MAX_BIND_GROUPS as u32);
1155 }
1156