1#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
18#![allow(
19 unknown_lints,
21 clippy::never_loop,
23 clippy::match_like_matches_macro,
25 clippy::redundant_pattern_matching,
27 clippy::needless_lifetimes,
29 clippy::new_without_default,
31 clippy::single_match,
33 clippy::vec_init_then_push,
35 clippy::if_then_panic,
37 clippy::non_send_fields_in_send_ty,
39 clippy::missing_safety_doc,
41 clippy::needless_borrowed_reference,
43)]
44#![warn(
45 trivial_casts,
46 trivial_numeric_casts,
47 unsafe_op_in_unsafe_fn,
48 unused_extern_crates,
49 unused_qualifications,
50 clippy::pattern_type_mismatch,
52)]
53
54#[cfg(all(feature = "dx11", windows))]
56pub mod dx11;
57#[cfg(all(feature = "dx12", windows))]
59pub mod dx12;
60pub mod empty;
62#[cfg(all(feature = "gles"))]
64pub mod gles;
65#[cfg(all(feature = "metal", any(target_os = "macos", target_os = "ios")))]
67pub mod metal;
68#[cfg(all(feature = "vulkan", not(target_arch = "wasm32")))]
70pub mod vulkan;
71
72pub mod auxil;
73pub mod api {
74 #[cfg(all(feature = "dx11", windows))]
75 pub use super::dx11::Api as Dx11;
76 #[cfg(all(feature = "dx12", windows))]
77 pub use super::dx12::Api as Dx12;
78 pub use super::empty::Api as Empty;
79 #[cfg(feature = "gles")]
80 pub use super::gles::Api as Gles;
81 #[cfg(all(feature = "metal", any(target_os = "macos", target_os = "ios")))]
82 pub use super::metal::Api as Metal;
83 #[cfg(all(feature = "vulkan", not(target_arch = "wasm32")))]
84 pub use super::vulkan::Api as Vulkan;
85}
86
87use std::{
88 borrow::{Borrow, Cow},
89 fmt,
90 num::NonZeroU32,
91 ops::{Range, RangeInclusive},
92 ptr::NonNull,
93 sync::atomic::AtomicBool,
94};
95
96use bitflags::bitflags;
97use thiserror::Error;
98use wgt::{WasmNotSend, WasmNotSync};
99
100pub const MAX_ANISOTROPY: u8 = 16;
101pub const MAX_BIND_GROUPS: usize = 8;
102pub const MAX_VERTEX_BUFFERS: usize = 16;
103pub const MAX_COLOR_ATTACHMENTS: usize = 8;
104pub const MAX_MIP_LEVELS: u32 = 16;
105pub const QUERY_SIZE: wgt::BufferAddress = 8;
107
108pub type Label<'a> = Option<&'a str>;
109pub type MemoryRange = Range<wgt::BufferAddress>;
110pub type FenceValue = u64;
111
112pub type DropGuard = Box<dyn std::any::Any + Send + Sync>;
114
115#[derive(Clone, Debug, PartialEq, Eq, Error)]
116pub enum DeviceError {
117 #[error("Out of memory")]
118 OutOfMemory,
119 #[error("Device is lost")]
120 Lost,
121}
122
123#[derive(Clone, Debug, Eq, PartialEq, Error)]
124pub enum ShaderError {
125 #[error("Compilation failed: {0:?}")]
126 Compilation(String),
127 #[error(transparent)]
128 Device(#[from] DeviceError),
129}
130
131#[derive(Clone, Debug, Eq, PartialEq, Error)]
132pub enum PipelineError {
133 #[error("Linkage failed for stage {0:?}: {1}")]
134 Linkage(wgt::ShaderStages, String),
135 #[error("Entry point for stage {0:?} is invalid")]
136 EntryPoint(naga::ShaderStage),
137 #[error(transparent)]
138 Device(#[from] DeviceError),
139}
140
141#[derive(Clone, Debug, Eq, PartialEq, Error)]
142pub enum SurfaceError {
143 #[error("Surface is lost")]
144 Lost,
145 #[error("Surface is outdated, needs to be re-created")]
146 Outdated,
147 #[error(transparent)]
148 Device(#[from] DeviceError),
149 #[error("Other reason: {0}")]
150 Other(&'static str),
151}
152
153#[derive(Clone, Debug, Eq, PartialEq, Error)]
154#[error("Not supported")]
155pub struct InstanceError;
156
157pub trait Api: Clone + Sized {
158 type Instance: Instance<Self>;
159 type Surface: Surface<Self>;
160 type Adapter: Adapter<Self>;
161 type Device: Device<Self>;
162
163 type Queue: Queue<Self>;
164 type CommandEncoder: CommandEncoder<Self>;
165 type CommandBuffer: WasmNotSend + WasmNotSync + fmt::Debug;
166
167 type Buffer: fmt::Debug + WasmNotSend + WasmNotSync + 'static;
168 type Texture: fmt::Debug + WasmNotSend + WasmNotSync + 'static;
169 type SurfaceTexture: fmt::Debug + WasmNotSend + WasmNotSync + Borrow<Self::Texture>;
170 type TextureView: fmt::Debug + WasmNotSend + WasmNotSync;
171 type Sampler: fmt::Debug + WasmNotSend + WasmNotSync;
172 type QuerySet: fmt::Debug + WasmNotSend + WasmNotSync;
173 type Fence: fmt::Debug + WasmNotSend + WasmNotSync;
174
175 type BindGroupLayout: WasmNotSend + WasmNotSync;
176 type BindGroup: fmt::Debug + WasmNotSend + WasmNotSync;
177 type PipelineLayout: WasmNotSend + WasmNotSync;
178 type ShaderModule: fmt::Debug + WasmNotSend + WasmNotSync;
179 type RenderPipeline: WasmNotSend + WasmNotSync;
180 type ComputePipeline: WasmNotSend + WasmNotSync;
181}
182
183pub trait Instance<A: Api>: Sized + WasmNotSend + WasmNotSync {
184 unsafe fn init(desc: &InstanceDescriptor) -> Result<Self, InstanceError>;
185 unsafe fn create_surface(
186 &self,
187 display_handle: raw_window_handle::RawDisplayHandle,
188 window_handle: raw_window_handle::RawWindowHandle,
189 ) -> Result<A::Surface, InstanceError>;
190 unsafe fn destroy_surface(&self, surface: A::Surface);
191 unsafe fn enumerate_adapters(&self) -> Vec<ExposedAdapter<A>>;
192}
193
194pub trait Surface<A: Api>: WasmNotSend + WasmNotSync {
195 unsafe fn configure(
204 &mut self,
205 device: &A::Device,
206 config: &SurfaceConfiguration,
207 ) -> Result<(), SurfaceError>;
208
209 unsafe fn unconfigure(&mut self, device: &A::Device);
218
219 unsafe fn acquire_texture(
230 &mut self,
231 timeout: Option<std::time::Duration>,
232 ) -> Result<Option<AcquiredSurfaceTexture<A>>, SurfaceError>;
233 unsafe fn discard_texture(&mut self, texture: A::SurfaceTexture);
234}
235
236pub trait Adapter<A: Api>: WasmNotSend + WasmNotSync {
237 unsafe fn open(
238 &self,
239 features: wgt::Features,
240 limits: &wgt::Limits,
241 ) -> Result<OpenDevice<A>, DeviceError>;
242
243 unsafe fn texture_format_capabilities(
245 &self,
246 format: wgt::TextureFormat,
247 ) -> TextureFormatCapabilities;
248
249 unsafe fn surface_capabilities(&self, surface: &A::Surface) -> Option<SurfaceCapabilities>;
253
254 unsafe fn get_presentation_timestamp(&self) -> wgt::PresentationTimestamp;
258}
259
260pub trait Device<A: Api>: WasmNotSend + WasmNotSync {
261 unsafe fn exit(self, queue: A::Queue);
263 unsafe fn create_buffer(&self, desc: &BufferDescriptor) -> Result<A::Buffer, DeviceError>;
267 unsafe fn destroy_buffer(&self, buffer: A::Buffer);
268 unsafe fn map_buffer(
270 &self,
271 buffer: &A::Buffer,
272 range: MemoryRange,
273 ) -> Result<BufferMapping, DeviceError>;
274 unsafe fn unmap_buffer(&self, buffer: &A::Buffer) -> Result<(), DeviceError>;
275 unsafe fn flush_mapped_ranges<I>(&self, buffer: &A::Buffer, ranges: I)
276 where
277 I: Iterator<Item = MemoryRange>;
278 unsafe fn invalidate_mapped_ranges<I>(&self, buffer: &A::Buffer, ranges: I)
279 where
280 I: Iterator<Item = MemoryRange>;
281
282 unsafe fn create_texture(&self, desc: &TextureDescriptor) -> Result<A::Texture, DeviceError>;
286 unsafe fn destroy_texture(&self, texture: A::Texture);
287 unsafe fn create_texture_view(
288 &self,
289 texture: &A::Texture,
290 desc: &TextureViewDescriptor,
291 ) -> Result<A::TextureView, DeviceError>;
292 unsafe fn destroy_texture_view(&self, view: A::TextureView);
293 unsafe fn create_sampler(&self, desc: &SamplerDescriptor) -> Result<A::Sampler, DeviceError>;
294 unsafe fn destroy_sampler(&self, sampler: A::Sampler);
295
296 unsafe fn create_command_encoder(
297 &self,
298 desc: &CommandEncoderDescriptor<A>,
299 ) -> Result<A::CommandEncoder, DeviceError>;
300 unsafe fn destroy_command_encoder(&self, pool: A::CommandEncoder);
301
302 unsafe fn create_bind_group_layout(
304 &self,
305 desc: &BindGroupLayoutDescriptor,
306 ) -> Result<A::BindGroupLayout, DeviceError>;
307 unsafe fn destroy_bind_group_layout(&self, bg_layout: A::BindGroupLayout);
308 unsafe fn create_pipeline_layout(
309 &self,
310 desc: &PipelineLayoutDescriptor<A>,
311 ) -> Result<A::PipelineLayout, DeviceError>;
312 unsafe fn destroy_pipeline_layout(&self, pipeline_layout: A::PipelineLayout);
313 unsafe fn create_bind_group(
314 &self,
315 desc: &BindGroupDescriptor<A>,
316 ) -> Result<A::BindGroup, DeviceError>;
317 unsafe fn destroy_bind_group(&self, group: A::BindGroup);
318
319 unsafe fn create_shader_module(
320 &self,
321 desc: &ShaderModuleDescriptor,
322 shader: ShaderInput,
323 ) -> Result<A::ShaderModule, ShaderError>;
324 unsafe fn destroy_shader_module(&self, module: A::ShaderModule);
325 unsafe fn create_render_pipeline(
326 &self,
327 desc: &RenderPipelineDescriptor<A>,
328 ) -> Result<A::RenderPipeline, PipelineError>;
329 unsafe fn destroy_render_pipeline(&self, pipeline: A::RenderPipeline);
330 unsafe fn create_compute_pipeline(
331 &self,
332 desc: &ComputePipelineDescriptor<A>,
333 ) -> Result<A::ComputePipeline, PipelineError>;
334 unsafe fn destroy_compute_pipeline(&self, pipeline: A::ComputePipeline);
335
336 unsafe fn create_query_set(
337 &self,
338 desc: &wgt::QuerySetDescriptor<Label>,
339 ) -> Result<A::QuerySet, DeviceError>;
340 unsafe fn destroy_query_set(&self, set: A::QuerySet);
341 unsafe fn create_fence(&self) -> Result<A::Fence, DeviceError>;
342 unsafe fn destroy_fence(&self, fence: A::Fence);
343 unsafe fn get_fence_value(&self, fence: &A::Fence) -> Result<FenceValue, DeviceError>;
344 unsafe fn wait(
346 &self,
347 fence: &A::Fence,
348 value: FenceValue,
349 timeout_ms: u32,
350 ) -> Result<bool, DeviceError>;
351
352 unsafe fn start_capture(&self) -> bool;
353 unsafe fn stop_capture(&self);
354}
355
356pub trait Queue<A: Api>: WasmNotSend + WasmNotSync {
357 unsafe fn submit(
364 &mut self,
365 command_buffers: &[&A::CommandBuffer],
366 signal_fence: Option<(&mut A::Fence, FenceValue)>,
367 ) -> Result<(), DeviceError>;
368 unsafe fn present(
369 &mut self,
370 surface: &mut A::Surface,
371 texture: A::SurfaceTexture,
372 ) -> Result<(), SurfaceError>;
373 unsafe fn get_timestamp_period(&self) -> f32;
374}
375
376pub trait CommandEncoder<A: Api>: WasmNotSend + WasmNotSync + fmt::Debug {
381 unsafe fn begin_encoding(&mut self, label: Label) -> Result<(), DeviceError>;
383 unsafe fn discard_encoding(&mut self);
385 unsafe fn end_encoding(&mut self) -> Result<A::CommandBuffer, DeviceError>;
386 unsafe fn reset_all<I>(&mut self, command_buffers: I)
390 where
391 I: Iterator<Item = A::CommandBuffer>;
392
393 unsafe fn transition_buffers<'a, T>(&mut self, barriers: T)
394 where
395 T: Iterator<Item = BufferBarrier<'a, A>>;
396
397 unsafe fn transition_textures<'a, T>(&mut self, barriers: T)
398 where
399 T: Iterator<Item = TextureBarrier<'a, A>>;
400
401 unsafe fn clear_buffer(&mut self, buffer: &A::Buffer, range: MemoryRange);
404
405 unsafe fn copy_buffer_to_buffer<T>(&mut self, src: &A::Buffer, dst: &A::Buffer, regions: T)
406 where
407 T: Iterator<Item = BufferCopy>;
408
409 #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
414 unsafe fn copy_external_image_to_texture<T>(
415 &mut self,
416 src: &wgt::ImageCopyExternalImage,
417 dst: &A::Texture,
418 dst_premultiplication: bool,
419 regions: T,
420 ) where
421 T: Iterator<Item = TextureCopy>;
422
423 unsafe fn copy_texture_to_texture<T>(
428 &mut self,
429 src: &A::Texture,
430 src_usage: TextureUses,
431 dst: &A::Texture,
432 regions: T,
433 ) where
434 T: Iterator<Item = TextureCopy>;
435
436 unsafe fn copy_buffer_to_texture<T>(&mut self, src: &A::Buffer, dst: &A::Texture, regions: T)
441 where
442 T: Iterator<Item = BufferTextureCopy>;
443
444 unsafe fn copy_texture_to_buffer<T>(
448 &mut self,
449 src: &A::Texture,
450 src_usage: TextureUses,
451 dst: &A::Buffer,
452 regions: T,
453 ) where
454 T: Iterator<Item = BufferTextureCopy>;
455
456 unsafe fn set_bind_group(
461 &mut self,
462 layout: &A::PipelineLayout,
463 index: u32,
464 group: &A::BindGroup,
465 dynamic_offsets: &[wgt::DynamicOffset],
466 );
467
468 unsafe fn set_push_constants(
469 &mut self,
470 layout: &A::PipelineLayout,
471 stages: wgt::ShaderStages,
472 offset: u32,
473 data: &[u32],
474 );
475
476 unsafe fn insert_debug_marker(&mut self, label: &str);
477 unsafe fn begin_debug_marker(&mut self, group_label: &str);
478 unsafe fn end_debug_marker(&mut self);
479
480 unsafe fn begin_query(&mut self, set: &A::QuerySet, index: u32);
483 unsafe fn end_query(&mut self, set: &A::QuerySet, index: u32);
484 unsafe fn write_timestamp(&mut self, set: &A::QuerySet, index: u32);
485 unsafe fn reset_queries(&mut self, set: &A::QuerySet, range: Range<u32>);
486 unsafe fn copy_query_results(
487 &mut self,
488 set: &A::QuerySet,
489 range: Range<u32>,
490 buffer: &A::Buffer,
491 offset: wgt::BufferAddress,
492 stride: wgt::BufferSize,
493 );
494
495 unsafe fn begin_render_pass(&mut self, desc: &RenderPassDescriptor<A>);
499 unsafe fn end_render_pass(&mut self);
500
501 unsafe fn set_render_pipeline(&mut self, pipeline: &A::RenderPipeline);
502
503 unsafe fn set_index_buffer<'a>(
504 &mut self,
505 binding: BufferBinding<'a, A>,
506 format: wgt::IndexFormat,
507 );
508 unsafe fn set_vertex_buffer<'a>(&mut self, index: u32, binding: BufferBinding<'a, A>);
509 unsafe fn set_viewport(&mut self, rect: &Rect<f32>, depth_range: Range<f32>);
510 unsafe fn set_scissor_rect(&mut self, rect: &Rect<u32>);
511 unsafe fn set_stencil_reference(&mut self, value: u32);
512 unsafe fn set_blend_constants(&mut self, color: &[f32; 4]);
513
514 unsafe fn draw(
515 &mut self,
516 start_vertex: u32,
517 vertex_count: u32,
518 start_instance: u32,
519 instance_count: u32,
520 );
521 unsafe fn draw_indexed(
522 &mut self,
523 start_index: u32,
524 index_count: u32,
525 base_vertex: i32,
526 start_instance: u32,
527 instance_count: u32,
528 );
529 unsafe fn draw_indirect(
530 &mut self,
531 buffer: &A::Buffer,
532 offset: wgt::BufferAddress,
533 draw_count: u32,
534 );
535 unsafe fn draw_indexed_indirect(
536 &mut self,
537 buffer: &A::Buffer,
538 offset: wgt::BufferAddress,
539 draw_count: u32,
540 );
541 unsafe fn draw_indirect_count(
542 &mut self,
543 buffer: &A::Buffer,
544 offset: wgt::BufferAddress,
545 count_buffer: &A::Buffer,
546 count_offset: wgt::BufferAddress,
547 max_count: u32,
548 );
549 unsafe fn draw_indexed_indirect_count(
550 &mut self,
551 buffer: &A::Buffer,
552 offset: wgt::BufferAddress,
553 count_buffer: &A::Buffer,
554 count_offset: wgt::BufferAddress,
555 max_count: u32,
556 );
557
558 unsafe fn begin_compute_pass(&mut self, desc: &ComputePassDescriptor);
562 unsafe fn end_compute_pass(&mut self);
563
564 unsafe fn set_compute_pipeline(&mut self, pipeline: &A::ComputePipeline);
565
566 unsafe fn dispatch(&mut self, count: [u32; 3]);
567 unsafe fn dispatch_indirect(&mut self, buffer: &A::Buffer, offset: wgt::BufferAddress);
568}
569
570bitflags!(
571 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
573 pub struct InstanceFlags: u32 {
574 const DEBUG = 1 << 0;
576 const VALIDATION = 1 << 1;
578 }
579);
580
581bitflags!(
582 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
584 pub struct PipelineLayoutFlags: u32 {
585 const BASE_VERTEX_INSTANCE = 1 << 0;
587 const NUM_WORK_GROUPS = 1 << 1;
589 }
590);
591
592bitflags!(
593 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
595 pub struct BindGroupLayoutFlags: u32 {
596 const PARTIALLY_BOUND = 1 << 0;
598 }
599);
600
601bitflags!(
602 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
604 pub struct TextureFormatCapabilities: u32 {
605 const SAMPLED = 1 << 0;
607 const SAMPLED_LINEAR = 1 << 1;
609 const SAMPLED_MINMAX = 1 << 2;
611
612 const STORAGE = 1 << 3;
614 const STORAGE_READ_WRITE = 1 << 4;
616 const STORAGE_ATOMIC = 1 << 5;
618
619 const COLOR_ATTACHMENT = 1 << 6;
621 const COLOR_ATTACHMENT_BLEND = 1 << 7;
623 const DEPTH_STENCIL_ATTACHMENT = 1 << 8;
625
626 const MULTISAMPLE_X2 = 1 << 9;
628 const MULTISAMPLE_X4 = 1 << 10;
630 const MULTISAMPLE_X8 = 1 << 11;
632 const MULTISAMPLE_X16 = 1 << 12;
634
635 const MULTISAMPLE_RESOLVE = 1 << 13;
637
638 const COPY_SRC = 1 << 14;
640 const COPY_DST = 1 << 15;
642 }
643);
644
645bitflags!(
646 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
648 pub struct FormatAspects: u8 {
649 const COLOR = 1 << 0;
650 const DEPTH = 1 << 1;
651 const STENCIL = 1 << 2;
652 }
653);
654
655impl FormatAspects {
656 pub fn new(format: wgt::TextureFormat, aspect: wgt::TextureAspect) -> Self {
657 let aspect_mask = match aspect {
658 wgt::TextureAspect::All => Self::all(),
659 wgt::TextureAspect::DepthOnly => Self::DEPTH,
660 wgt::TextureAspect::StencilOnly => Self::STENCIL,
661 };
662 Self::from(format) & aspect_mask
663 }
664
665 pub fn is_one(&self) -> bool {
667 self.bits().count_ones() == 1
668 }
669
670 pub fn map(&self) -> wgt::TextureAspect {
671 match *self {
672 Self::COLOR => wgt::TextureAspect::All,
673 Self::DEPTH => wgt::TextureAspect::DepthOnly,
674 Self::STENCIL => wgt::TextureAspect::StencilOnly,
675 _ => unreachable!(),
676 }
677 }
678}
679
680impl From<wgt::TextureFormat> for FormatAspects {
681 fn from(format: wgt::TextureFormat) -> Self {
682 match format {
683 wgt::TextureFormat::Stencil8 => Self::STENCIL,
684 wgt::TextureFormat::Depth16Unorm
685 | wgt::TextureFormat::Depth32Float
686 | wgt::TextureFormat::Depth24Plus => Self::DEPTH,
687 wgt::TextureFormat::Depth32FloatStencil8 | wgt::TextureFormat::Depth24PlusStencil8 => {
688 Self::DEPTH | Self::STENCIL
689 }
690 _ => Self::COLOR,
691 }
692 }
693}
694
695bitflags!(
696 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
697 pub struct MemoryFlags: u32 {
698 const TRANSIENT = 1 << 0;
699 const PREFER_COHERENT = 1 << 1;
700 }
701);
702
703bitflags!(
706 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
707 pub struct AttachmentOps: u8 {
708 const LOAD = 1 << 0;
709 const STORE = 1 << 1;
710 }
711);
712
713bitflags::bitflags! {
714 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
716 pub struct BufferUses: u16 {
717 const MAP_READ = 1 << 0;
719 const MAP_WRITE = 1 << 1;
721 const COPY_SRC = 1 << 2;
723 const COPY_DST = 1 << 3;
725 const INDEX = 1 << 4;
727 const VERTEX = 1 << 5;
729 const UNIFORM = 1 << 6;
731 const STORAGE_READ = 1 << 7;
733 const STORAGE_READ_WRITE = 1 << 8;
735 const INDIRECT = 1 << 9;
737 const INCLUSIVE = Self::MAP_READ.bits() | Self::COPY_SRC.bits() |
739 Self::INDEX.bits() | Self::VERTEX.bits() | Self::UNIFORM.bits() |
740 Self::STORAGE_READ.bits() | Self::INDIRECT.bits();
741 const EXCLUSIVE = Self::MAP_WRITE.bits() | Self::COPY_DST.bits() | Self::STORAGE_READ_WRITE.bits();
743 const ORDERED = Self::INCLUSIVE.bits() | Self::MAP_WRITE.bits();
747 }
748}
749
750bitflags::bitflags! {
751 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
753 pub struct TextureUses: u16 {
754 const UNINITIALIZED = 1 << 0;
756 const PRESENT = 1 << 1;
758 const COPY_SRC = 1 << 2;
760 const COPY_DST = 1 << 3;
762 const RESOURCE = 1 << 4;
764 const COLOR_TARGET = 1 << 5;
766 const DEPTH_STENCIL_READ = 1 << 6;
768 const DEPTH_STENCIL_WRITE = 1 << 7;
770 const STORAGE_READ = 1 << 8;
772 const STORAGE_READ_WRITE = 1 << 9;
774 const INCLUSIVE = Self::COPY_SRC.bits() | Self::RESOURCE.bits() | Self::DEPTH_STENCIL_READ.bits();
776 const EXCLUSIVE = Self::COPY_DST.bits() | Self::COLOR_TARGET.bits() | Self::DEPTH_STENCIL_WRITE.bits() | Self::STORAGE_READ.bits() | Self::STORAGE_READ_WRITE.bits() | Self::PRESENT.bits();
778 const ORDERED = Self::INCLUSIVE.bits() | Self::COLOR_TARGET.bits() | Self::DEPTH_STENCIL_WRITE.bits() | Self::STORAGE_READ.bits();
782
783 const COMPLEX = 1 << 10;
785 const UNKNOWN = 1 << 11;
788 }
789}
790
791#[derive(Clone, Debug)]
792pub struct InstanceDescriptor<'a> {
793 pub name: &'a str,
794 pub flags: InstanceFlags,
795 pub dx12_shader_compiler: wgt::Dx12Compiler,
796}
797
798#[derive(Clone, Debug)]
799pub struct Alignments {
800 pub buffer_copy_offset: wgt::BufferSize,
802 pub buffer_copy_pitch: wgt::BufferSize,
805}
806
807#[derive(Clone, Debug)]
808pub struct Capabilities {
809 pub limits: wgt::Limits,
810 pub alignments: Alignments,
811 pub downlevel: wgt::DownlevelCapabilities,
812}
813
814#[derive(Debug)]
815pub struct ExposedAdapter<A: Api> {
816 pub adapter: A::Adapter,
817 pub info: wgt::AdapterInfo,
818 pub features: wgt::Features,
819 pub capabilities: Capabilities,
820}
821
822#[derive(Debug, Clone)]
825pub struct SurfaceCapabilities {
826 pub formats: Vec<wgt::TextureFormat>,
830
831 pub swap_chain_sizes: RangeInclusive<u32>,
836
837 pub current_extent: Option<wgt::Extent3d>,
839
840 pub extents: RangeInclusive<wgt::Extent3d>,
844
845 pub usage: TextureUses,
849
850 pub present_modes: Vec<wgt::PresentMode>,
854
855 pub composite_alpha_modes: Vec<wgt::CompositeAlphaMode>,
859}
860
861#[derive(Debug)]
862pub struct AcquiredSurfaceTexture<A: Api> {
863 pub texture: A::SurfaceTexture,
864 pub suboptimal: bool,
868}
869
870#[derive(Debug)]
871pub struct OpenDevice<A: Api> {
872 pub device: A::Device,
873 pub queue: A::Queue,
874}
875
876#[derive(Clone, Debug)]
877pub struct BufferMapping {
878 pub ptr: NonNull<u8>,
879 pub is_coherent: bool,
880}
881
882#[derive(Clone, Debug)]
883pub struct BufferDescriptor<'a> {
884 pub label: Label<'a>,
885 pub size: wgt::BufferAddress,
886 pub usage: BufferUses,
887 pub memory_flags: MemoryFlags,
888}
889
890#[derive(Clone, Debug)]
891pub struct TextureDescriptor<'a> {
892 pub label: Label<'a>,
893 pub size: wgt::Extent3d,
894 pub mip_level_count: u32,
895 pub sample_count: u32,
896 pub dimension: wgt::TextureDimension,
897 pub format: wgt::TextureFormat,
898 pub usage: TextureUses,
899 pub memory_flags: MemoryFlags,
900 pub view_formats: Vec<wgt::TextureFormat>,
903}
904
905impl TextureDescriptor<'_> {
906 pub fn copy_extent(&self) -> CopyExtent {
907 CopyExtent::map_extent_to_copy_size(&self.size, self.dimension)
908 }
909
910 pub fn is_cube_compatible(&self) -> bool {
911 self.dimension == wgt::TextureDimension::D2
912 && self.size.depth_or_array_layers % 6 == 0
913 && self.sample_count == 1
914 && self.size.width == self.size.height
915 }
916
917 pub fn array_layer_count(&self) -> u32 {
918 match self.dimension {
919 wgt::TextureDimension::D1 | wgt::TextureDimension::D3 => 1,
920 wgt::TextureDimension::D2 => self.size.depth_or_array_layers,
921 }
922 }
923}
924
925#[derive(Clone, Debug)]
933pub struct TextureViewDescriptor<'a> {
934 pub label: Label<'a>,
935 pub format: wgt::TextureFormat,
936 pub dimension: wgt::TextureViewDimension,
937 pub usage: TextureUses,
938 pub range: wgt::ImageSubresourceRange,
939}
940
941#[derive(Clone, Debug)]
942pub struct SamplerDescriptor<'a> {
943 pub label: Label<'a>,
944 pub address_modes: [wgt::AddressMode; 3],
945 pub mag_filter: wgt::FilterMode,
946 pub min_filter: wgt::FilterMode,
947 pub mipmap_filter: wgt::FilterMode,
948 pub lod_clamp: Range<f32>,
949 pub compare: Option<wgt::CompareFunction>,
950 pub anisotropy_clamp: u16,
954 pub border_color: Option<wgt::SamplerBorderColor>,
955}
956
957#[derive(Clone, Debug)]
962pub struct BindGroupLayoutDescriptor<'a> {
963 pub label: Label<'a>,
964 pub flags: BindGroupLayoutFlags,
965 pub entries: &'a [wgt::BindGroupLayoutEntry],
966}
967
968#[derive(Clone, Debug)]
969pub struct PipelineLayoutDescriptor<'a, A: Api> {
970 pub label: Label<'a>,
971 pub flags: PipelineLayoutFlags,
972 pub bind_group_layouts: &'a [&'a A::BindGroupLayout],
973 pub push_constant_ranges: &'a [wgt::PushConstantRange],
974}
975
976#[derive(Debug)]
977pub struct BufferBinding<'a, A: Api> {
978 pub buffer: &'a A::Buffer,
980
981 pub offset: wgt::BufferAddress,
993
994 pub size: Option<wgt::BufferSize>,
1000}
1001
1002impl<A: Api> Clone for BufferBinding<'_, A> {
1004 fn clone(&self) -> Self {
1005 Self {
1006 buffer: self.buffer,
1007 offset: self.offset,
1008 size: self.size,
1009 }
1010 }
1011}
1012
1013#[derive(Debug)]
1014pub struct TextureBinding<'a, A: Api> {
1015 pub view: &'a A::TextureView,
1016 pub usage: TextureUses,
1017}
1018
1019impl<A: Api> Clone for TextureBinding<'_, A> {
1021 fn clone(&self) -> Self {
1022 Self {
1023 view: self.view,
1024 usage: self.usage,
1025 }
1026 }
1027}
1028
1029#[derive(Clone, Debug)]
1030pub struct BindGroupEntry {
1031 pub binding: u32,
1032 pub resource_index: u32,
1033 pub count: u32,
1034}
1035
1036#[derive(Clone, Debug)]
1046pub struct BindGroupDescriptor<'a, A: Api> {
1047 pub label: Label<'a>,
1048 pub layout: &'a A::BindGroupLayout,
1049 pub buffers: &'a [BufferBinding<'a, A>],
1050 pub samplers: &'a [&'a A::Sampler],
1051 pub textures: &'a [TextureBinding<'a, A>],
1052 pub entries: &'a [BindGroupEntry],
1053}
1054
1055#[derive(Clone, Debug)]
1056pub struct CommandEncoderDescriptor<'a, A: Api> {
1057 pub label: Label<'a>,
1058 pub queue: &'a A::Queue,
1059}
1060
1061pub struct NagaShader {
1063 pub module: Cow<'static, naga::Module>,
1065 pub info: naga::valid::ModuleInfo,
1067}
1068
1069impl fmt::Debug for NagaShader {
1072 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1073 write!(formatter, "Naga shader")
1074 }
1075}
1076
1077#[allow(clippy::large_enum_variant)]
1079pub enum ShaderInput<'a> {
1080 Naga(NagaShader),
1081 SpirV(&'a [u32]),
1082}
1083
1084pub struct ShaderModuleDescriptor<'a> {
1085 pub label: Label<'a>,
1086 pub runtime_checks: bool,
1087}
1088
1089#[derive(Debug)]
1091pub struct ProgrammableStage<'a, A: Api> {
1092 pub module: &'a A::ShaderModule,
1094 pub entry_point: &'a str,
1097}
1098
1099impl<A: Api> Clone for ProgrammableStage<'_, A> {
1101 fn clone(&self) -> Self {
1102 Self {
1103 module: self.module,
1104 entry_point: self.entry_point,
1105 }
1106 }
1107}
1108
1109#[derive(Clone, Debug)]
1111pub struct ComputePipelineDescriptor<'a, A: Api> {
1112 pub label: Label<'a>,
1113 pub layout: &'a A::PipelineLayout,
1115 pub stage: ProgrammableStage<'a, A>,
1117}
1118
1119#[derive(Clone, Debug)]
1121pub struct VertexBufferLayout<'a> {
1122 pub array_stride: wgt::BufferAddress,
1124 pub step_mode: wgt::VertexStepMode,
1126 pub attributes: &'a [wgt::VertexAttribute],
1128}
1129
1130#[derive(Clone, Debug)]
1132pub struct RenderPipelineDescriptor<'a, A: Api> {
1133 pub label: Label<'a>,
1134 pub layout: &'a A::PipelineLayout,
1136 pub vertex_buffers: &'a [VertexBufferLayout<'a>],
1138 pub vertex_stage: ProgrammableStage<'a, A>,
1140 pub primitive: wgt::PrimitiveState,
1142 pub depth_stencil: Option<wgt::DepthStencilState>,
1144 pub multisample: wgt::MultisampleState,
1146 pub fragment_stage: Option<ProgrammableStage<'a, A>>,
1148 pub color_targets: &'a [Option<wgt::ColorTargetState>],
1150 pub multiview: Option<NonZeroU32>,
1153}
1154
1155#[derive(Debug, Clone)]
1156pub struct SurfaceConfiguration {
1157 pub swap_chain_size: u32,
1160 pub present_mode: wgt::PresentMode,
1162 pub composite_alpha_mode: wgt::CompositeAlphaMode,
1164 pub format: wgt::TextureFormat,
1166 pub extent: wgt::Extent3d,
1169 pub usage: TextureUses,
1171 pub view_formats: Vec<wgt::TextureFormat>,
1174}
1175
1176#[derive(Debug, Clone)]
1177pub struct Rect<T> {
1178 pub x: T,
1179 pub y: T,
1180 pub w: T,
1181 pub h: T,
1182}
1183
1184#[derive(Debug, Clone)]
1185pub struct BufferBarrier<'a, A: Api> {
1186 pub buffer: &'a A::Buffer,
1187 pub usage: Range<BufferUses>,
1188}
1189
1190#[derive(Debug, Clone)]
1191pub struct TextureBarrier<'a, A: Api> {
1192 pub texture: &'a A::Texture,
1193 pub range: wgt::ImageSubresourceRange,
1194 pub usage: Range<TextureUses>,
1195}
1196
1197#[derive(Clone, Copy, Debug)]
1198pub struct BufferCopy {
1199 pub src_offset: wgt::BufferAddress,
1200 pub dst_offset: wgt::BufferAddress,
1201 pub size: wgt::BufferSize,
1202}
1203
1204#[derive(Clone, Debug)]
1205pub struct TextureCopyBase {
1206 pub mip_level: u32,
1207 pub array_layer: u32,
1208 pub origin: wgt::Origin3d,
1211 pub aspect: FormatAspects,
1212}
1213
1214#[derive(Clone, Copy, Debug)]
1215pub struct CopyExtent {
1216 pub width: u32,
1217 pub height: u32,
1218 pub depth: u32,
1219}
1220
1221#[derive(Clone, Debug)]
1222pub struct TextureCopy {
1223 pub src_base: TextureCopyBase,
1224 pub dst_base: TextureCopyBase,
1225 pub size: CopyExtent,
1226}
1227
1228#[derive(Clone, Debug)]
1229pub struct BufferTextureCopy {
1230 pub buffer_layout: wgt::ImageDataLayout,
1231 pub texture_base: TextureCopyBase,
1232 pub size: CopyExtent,
1233}
1234
1235#[derive(Debug)]
1236pub struct Attachment<'a, A: Api> {
1237 pub view: &'a A::TextureView,
1238 pub usage: TextureUses,
1241}
1242
1243impl<A: Api> Clone for Attachment<'_, A> {
1245 fn clone(&self) -> Self {
1246 Self {
1247 view: self.view,
1248 usage: self.usage,
1249 }
1250 }
1251}
1252
1253#[derive(Debug)]
1254pub struct ColorAttachment<'a, A: Api> {
1255 pub target: Attachment<'a, A>,
1256 pub resolve_target: Option<Attachment<'a, A>>,
1257 pub ops: AttachmentOps,
1258 pub clear_value: wgt::Color,
1259}
1260
1261impl<A: Api> Clone for ColorAttachment<'_, A> {
1263 fn clone(&self) -> Self {
1264 Self {
1265 target: self.target.clone(),
1266 resolve_target: self.resolve_target.clone(),
1267 ops: self.ops,
1268 clear_value: self.clear_value,
1269 }
1270 }
1271}
1272
1273#[derive(Clone, Debug)]
1274pub struct DepthStencilAttachment<'a, A: Api> {
1275 pub target: Attachment<'a, A>,
1276 pub depth_ops: AttachmentOps,
1277 pub stencil_ops: AttachmentOps,
1278 pub clear_value: (f32, u32),
1279}
1280
1281#[derive(Clone, Debug)]
1282pub struct RenderPassDescriptor<'a, A: Api> {
1283 pub label: Label<'a>,
1284 pub extent: wgt::Extent3d,
1285 pub sample_count: u32,
1286 pub color_attachments: &'a [Option<ColorAttachment<'a, A>>],
1287 pub depth_stencil_attachment: Option<DepthStencilAttachment<'a, A>>,
1288 pub multiview: Option<NonZeroU32>,
1289}
1290
1291#[derive(Clone, Debug)]
1292pub struct ComputePassDescriptor<'a> {
1293 pub label: Label<'a>,
1294}
1295
1296pub static VALIDATION_CANARY: ValidationCanary = ValidationCanary {
1308 inner: AtomicBool::new(false),
1309};
1310
1311pub struct ValidationCanary {
1313 inner: AtomicBool,
1314}
1315
1316impl ValidationCanary {
1317 #[allow(dead_code)] fn set(&self) {
1319 self.inner.store(true, std::sync::atomic::Ordering::SeqCst);
1320 }
1321
1322 pub fn get_and_reset(&self) -> bool {
1325 self.inner.swap(false, std::sync::atomic::Ordering::SeqCst)
1326 }
1327}
1328
1329#[test]
1330fn test_default_limits() {
1331 let limits = wgt::Limits::default();
1332 assert!(limits.max_bind_groups <= MAX_BIND_GROUPS as u32);
1333}