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