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(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, Arc},
94};
95
96use bitflags::bitflags;
97use thiserror::Error;
98use wgt::{WasmNotSend, WasmNotSync};
99
100pub const MAX_ANISOTROPY: u8 = 16;
101pub const MAX_BIND_GROUPS: usize = 8;
102pub const MAX_VERTEX_BUFFERS: usize = 16;
103pub const MAX_COLOR_ATTACHMENTS: usize = 8;
104pub const MAX_MIP_LEVELS: u32 = 16;
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 #[error("Creation of a resource failed for a reason other than running out of memory.")]
122 ResourceCreationFailed,
123}
124
125#[derive(Clone, Debug, Eq, PartialEq, Error)]
126pub enum ShaderError {
127 #[error("Compilation failed: {0:?}")]
128 Compilation(String),
129 #[error(transparent)]
130 Device(#[from] DeviceError),
131}
132
133#[derive(Clone, Debug, Eq, PartialEq, Error)]
134pub enum PipelineError {
135 #[error("Linkage failed for stage {0:?}: {1}")]
136 Linkage(wgt::ShaderStages, String),
137 #[error("Entry point for stage {0:?} is invalid")]
138 EntryPoint(naga::ShaderStage),
139 #[error(transparent)]
140 Device(#[from] DeviceError),
141}
142
143#[derive(Clone, Debug, Eq, PartialEq, Error)]
144pub enum SurfaceError {
145 #[error("Surface is lost")]
146 Lost,
147 #[error("Surface is outdated, needs to be re-created")]
148 Outdated,
149 #[error(transparent)]
150 Device(#[from] DeviceError),
151 #[error("Other reason: {0}")]
152 Other(&'static str),
153}
154
155#[derive(Clone, Debug, Error)]
158#[error("{message}")]
159pub struct InstanceError {
160 message: String,
166
167 #[source]
169 source: Option<Arc<dyn std::error::Error + Send + Sync + 'static>>,
170}
171
172impl InstanceError {
173 #[allow(dead_code)] pub(crate) fn new(message: String) -> Self {
175 Self {
176 message,
177 source: None,
178 }
179 }
180 #[allow(dead_code)] pub(crate) fn with_source(
182 message: String,
183 source: impl std::error::Error + Send + Sync + 'static,
184 ) -> Self {
185 Self {
186 message,
187 source: Some(Arc::new(source)),
188 }
189 }
190}
191
192pub trait Api: Clone + fmt::Debug + Sized {
193 type Instance: Instance<Self>;
194 type Surface: Surface<Self>;
195 type Adapter: Adapter<Self>;
196 type Device: Device<Self>;
197
198 type Queue: Queue<Self>;
199 type CommandEncoder: CommandEncoder<Self>;
200 type CommandBuffer: WasmNotSend + WasmNotSync + fmt::Debug;
201
202 type Buffer: fmt::Debug + WasmNotSend + WasmNotSync + 'static;
203 type Texture: fmt::Debug + WasmNotSend + WasmNotSync + 'static;
204 type SurfaceTexture: fmt::Debug + WasmNotSend + WasmNotSync + Borrow<Self::Texture>;
205 type TextureView: fmt::Debug + WasmNotSend + WasmNotSync;
206 type Sampler: fmt::Debug + WasmNotSend + WasmNotSync;
207 type QuerySet: fmt::Debug + WasmNotSend + WasmNotSync;
208 type Fence: fmt::Debug + WasmNotSend + WasmNotSync;
209
210 type BindGroupLayout: fmt::Debug + WasmNotSend + WasmNotSync;
211 type BindGroup: fmt::Debug + WasmNotSend + WasmNotSync;
212 type PipelineLayout: WasmNotSend + WasmNotSync;
213 type ShaderModule: fmt::Debug + WasmNotSend + WasmNotSync;
214 type RenderPipeline: WasmNotSend + WasmNotSync;
215 type ComputePipeline: WasmNotSend + WasmNotSync;
216}
217
218pub trait Instance<A: Api>: Sized + WasmNotSend + WasmNotSync {
219 unsafe fn init(desc: &InstanceDescriptor) -> Result<Self, InstanceError>;
220 unsafe fn create_surface(
221 &self,
222 display_handle: raw_window_handle::RawDisplayHandle,
223 window_handle: raw_window_handle::RawWindowHandle,
224 ) -> Result<A::Surface, InstanceError>;
225 unsafe fn destroy_surface(&self, surface: A::Surface);
226 unsafe fn enumerate_adapters(&self) -> Vec<ExposedAdapter<A>>;
227}
228
229pub trait Surface<A: Api>: WasmNotSend + WasmNotSync {
230 unsafe fn configure(
239 &mut self,
240 device: &A::Device,
241 config: &SurfaceConfiguration,
242 ) -> Result<(), SurfaceError>;
243
244 unsafe fn unconfigure(&mut self, device: &A::Device);
253
254 unsafe fn acquire_texture(
265 &mut self,
266 timeout: Option<std::time::Duration>,
267 ) -> Result<Option<AcquiredSurfaceTexture<A>>, SurfaceError>;
268 unsafe fn discard_texture(&mut self, texture: A::SurfaceTexture);
269}
270
271pub trait Adapter<A: Api>: WasmNotSend + WasmNotSync {
272 unsafe fn open(
273 &self,
274 features: wgt::Features,
275 limits: &wgt::Limits,
276 ) -> Result<OpenDevice<A>, DeviceError>;
277
278 unsafe fn texture_format_capabilities(
280 &self,
281 format: wgt::TextureFormat,
282 ) -> TextureFormatCapabilities;
283
284 unsafe fn surface_capabilities(&self, surface: &A::Surface) -> Option<SurfaceCapabilities>;
288
289 unsafe fn get_presentation_timestamp(&self) -> wgt::PresentationTimestamp;
293}
294
295pub trait Device<A: Api>: WasmNotSend + WasmNotSync {
296 unsafe fn exit(self, queue: A::Queue);
298 unsafe fn create_buffer(&self, desc: &BufferDescriptor) -> Result<A::Buffer, DeviceError>;
302 unsafe fn destroy_buffer(&self, buffer: A::Buffer);
303 unsafe fn map_buffer(
305 &self,
306 buffer: &A::Buffer,
307 range: MemoryRange,
308 ) -> Result<BufferMapping, DeviceError>;
309 unsafe fn unmap_buffer(&self, buffer: &A::Buffer) -> Result<(), DeviceError>;
310 unsafe fn flush_mapped_ranges<I>(&self, buffer: &A::Buffer, ranges: I)
311 where
312 I: Iterator<Item = MemoryRange>;
313 unsafe fn invalidate_mapped_ranges<I>(&self, buffer: &A::Buffer, ranges: I)
314 where
315 I: Iterator<Item = MemoryRange>;
316
317 unsafe fn create_texture(&self, desc: &TextureDescriptor) -> Result<A::Texture, DeviceError>;
321 unsafe fn destroy_texture(&self, texture: A::Texture);
322 unsafe fn create_texture_view(
323 &self,
324 texture: &A::Texture,
325 desc: &TextureViewDescriptor,
326 ) -> Result<A::TextureView, DeviceError>;
327 unsafe fn destroy_texture_view(&self, view: A::TextureView);
328 unsafe fn create_sampler(&self, desc: &SamplerDescriptor) -> Result<A::Sampler, DeviceError>;
329 unsafe fn destroy_sampler(&self, sampler: A::Sampler);
330
331 unsafe fn create_command_encoder(
332 &self,
333 desc: &CommandEncoderDescriptor<A>,
334 ) -> Result<A::CommandEncoder, DeviceError>;
335 unsafe fn destroy_command_encoder(&self, pool: A::CommandEncoder);
336
337 unsafe fn create_bind_group_layout(
339 &self,
340 desc: &BindGroupLayoutDescriptor,
341 ) -> Result<A::BindGroupLayout, DeviceError>;
342 unsafe fn destroy_bind_group_layout(&self, bg_layout: A::BindGroupLayout);
343 unsafe fn create_pipeline_layout(
344 &self,
345 desc: &PipelineLayoutDescriptor<A>,
346 ) -> Result<A::PipelineLayout, DeviceError>;
347 unsafe fn destroy_pipeline_layout(&self, pipeline_layout: A::PipelineLayout);
348 unsafe fn create_bind_group(
349 &self,
350 desc: &BindGroupDescriptor<A>,
351 ) -> Result<A::BindGroup, DeviceError>;
352 unsafe fn destroy_bind_group(&self, group: A::BindGroup);
353
354 unsafe fn create_shader_module(
355 &self,
356 desc: &ShaderModuleDescriptor,
357 shader: ShaderInput,
358 ) -> Result<A::ShaderModule, ShaderError>;
359 unsafe fn destroy_shader_module(&self, module: A::ShaderModule);
360 unsafe fn create_render_pipeline(
361 &self,
362 desc: &RenderPipelineDescriptor<A>,
363 ) -> Result<A::RenderPipeline, PipelineError>;
364 unsafe fn destroy_render_pipeline(&self, pipeline: A::RenderPipeline);
365 unsafe fn create_compute_pipeline(
366 &self,
367 desc: &ComputePipelineDescriptor<A>,
368 ) -> Result<A::ComputePipeline, PipelineError>;
369 unsafe fn destroy_compute_pipeline(&self, pipeline: A::ComputePipeline);
370
371 unsafe fn create_query_set(
372 &self,
373 desc: &wgt::QuerySetDescriptor<Label>,
374 ) -> Result<A::QuerySet, DeviceError>;
375 unsafe fn destroy_query_set(&self, set: A::QuerySet);
376 unsafe fn create_fence(&self) -> Result<A::Fence, DeviceError>;
377 unsafe fn destroy_fence(&self, fence: A::Fence);
378 unsafe fn get_fence_value(&self, fence: &A::Fence) -> Result<FenceValue, DeviceError>;
379 unsafe fn wait(
381 &self,
382 fence: &A::Fence,
383 value: FenceValue,
384 timeout_ms: u32,
385 ) -> Result<bool, DeviceError>;
386
387 unsafe fn start_capture(&self) -> bool;
388 unsafe fn stop_capture(&self);
389}
390
391pub trait Queue<A: Api>: WasmNotSend + WasmNotSync {
392 unsafe fn submit(
399 &mut self,
400 command_buffers: &[&A::CommandBuffer],
401 signal_fence: Option<(&mut A::Fence, FenceValue)>,
402 ) -> Result<(), DeviceError>;
403 unsafe fn present(
404 &mut self,
405 surface: &mut A::Surface,
406 texture: A::SurfaceTexture,
407 ) -> Result<(), SurfaceError>;
408 unsafe fn get_timestamp_period(&self) -> f32;
409}
410
411pub trait CommandEncoder<A: Api>: WasmNotSend + WasmNotSync + fmt::Debug {
416 unsafe fn begin_encoding(&mut self, label: Label) -> Result<(), DeviceError>;
418 unsafe fn discard_encoding(&mut self);
420 unsafe fn end_encoding(&mut self) -> Result<A::CommandBuffer, DeviceError>;
421 unsafe fn reset_all<I>(&mut self, command_buffers: I)
425 where
426 I: Iterator<Item = A::CommandBuffer>;
427
428 unsafe fn transition_buffers<'a, T>(&mut self, barriers: T)
429 where
430 T: Iterator<Item = BufferBarrier<'a, A>>;
431
432 unsafe fn transition_textures<'a, T>(&mut self, barriers: T)
433 where
434 T: Iterator<Item = TextureBarrier<'a, A>>;
435
436 unsafe fn clear_buffer(&mut self, buffer: &A::Buffer, range: MemoryRange);
439
440 unsafe fn copy_buffer_to_buffer<T>(&mut self, src: &A::Buffer, dst: &A::Buffer, regions: T)
441 where
442 T: Iterator<Item = BufferCopy>;
443
444 #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
449 unsafe fn copy_external_image_to_texture<T>(
450 &mut self,
451 src: &wgt::ImageCopyExternalImage,
452 dst: &A::Texture,
453 dst_premultiplication: bool,
454 regions: T,
455 ) where
456 T: Iterator<Item = TextureCopy>;
457
458 unsafe fn copy_texture_to_texture<T>(
463 &mut self,
464 src: &A::Texture,
465 src_usage: TextureUses,
466 dst: &A::Texture,
467 regions: T,
468 ) where
469 T: Iterator<Item = TextureCopy>;
470
471 unsafe fn copy_buffer_to_texture<T>(&mut self, src: &A::Buffer, dst: &A::Texture, regions: T)
476 where
477 T: Iterator<Item = BufferTextureCopy>;
478
479 unsafe fn copy_texture_to_buffer<T>(
483 &mut self,
484 src: &A::Texture,
485 src_usage: TextureUses,
486 dst: &A::Buffer,
487 regions: T,
488 ) where
489 T: Iterator<Item = BufferTextureCopy>;
490
491 unsafe fn set_bind_group(
496 &mut self,
497 layout: &A::PipelineLayout,
498 index: u32,
499 group: &A::BindGroup,
500 dynamic_offsets: &[wgt::DynamicOffset],
501 );
502
503 unsafe fn set_push_constants(
504 &mut self,
505 layout: &A::PipelineLayout,
506 stages: wgt::ShaderStages,
507 offset: u32,
508 data: &[u32],
509 );
510
511 unsafe fn insert_debug_marker(&mut self, label: &str);
512 unsafe fn begin_debug_marker(&mut self, group_label: &str);
513 unsafe fn end_debug_marker(&mut self);
514
515 unsafe fn begin_query(&mut self, set: &A::QuerySet, index: u32);
521 unsafe fn end_query(&mut self, set: &A::QuerySet, index: u32);
525 unsafe fn write_timestamp(&mut self, set: &A::QuerySet, index: u32);
526 unsafe fn reset_queries(&mut self, set: &A::QuerySet, range: Range<u32>);
527 unsafe fn copy_query_results(
528 &mut self,
529 set: &A::QuerySet,
530 range: Range<u32>,
531 buffer: &A::Buffer,
532 offset: wgt::BufferAddress,
533 stride: wgt::BufferSize,
534 );
535
536 unsafe fn begin_render_pass(&mut self, desc: &RenderPassDescriptor<A>);
540 unsafe fn end_render_pass(&mut self);
541
542 unsafe fn set_render_pipeline(&mut self, pipeline: &A::RenderPipeline);
543
544 unsafe fn set_index_buffer<'a>(
545 &mut self,
546 binding: BufferBinding<'a, A>,
547 format: wgt::IndexFormat,
548 );
549 unsafe fn set_vertex_buffer<'a>(&mut self, index: u32, binding: BufferBinding<'a, A>);
550 unsafe fn set_viewport(&mut self, rect: &Rect<f32>, depth_range: Range<f32>);
551 unsafe fn set_scissor_rect(&mut self, rect: &Rect<u32>);
552 unsafe fn set_stencil_reference(&mut self, value: u32);
553 unsafe fn set_blend_constants(&mut self, color: &[f32; 4]);
554
555 unsafe fn draw(
556 &mut self,
557 start_vertex: u32,
558 vertex_count: u32,
559 start_instance: u32,
560 instance_count: u32,
561 );
562 unsafe fn draw_indexed(
563 &mut self,
564 start_index: u32,
565 index_count: u32,
566 base_vertex: i32,
567 start_instance: u32,
568 instance_count: u32,
569 );
570 unsafe fn draw_indirect(
571 &mut self,
572 buffer: &A::Buffer,
573 offset: wgt::BufferAddress,
574 draw_count: u32,
575 );
576 unsafe fn draw_indexed_indirect(
577 &mut self,
578 buffer: &A::Buffer,
579 offset: wgt::BufferAddress,
580 draw_count: u32,
581 );
582 unsafe fn draw_indirect_count(
583 &mut self,
584 buffer: &A::Buffer,
585 offset: wgt::BufferAddress,
586 count_buffer: &A::Buffer,
587 count_offset: wgt::BufferAddress,
588 max_count: u32,
589 );
590 unsafe fn draw_indexed_indirect_count(
591 &mut self,
592 buffer: &A::Buffer,
593 offset: wgt::BufferAddress,
594 count_buffer: &A::Buffer,
595 count_offset: wgt::BufferAddress,
596 max_count: u32,
597 );
598
599 unsafe fn begin_compute_pass(&mut self, desc: &ComputePassDescriptor<A>);
603 unsafe fn end_compute_pass(&mut self);
604
605 unsafe fn set_compute_pipeline(&mut self, pipeline: &A::ComputePipeline);
606
607 unsafe fn dispatch(&mut self, count: [u32; 3]);
608 unsafe fn dispatch_indirect(&mut self, buffer: &A::Buffer, offset: wgt::BufferAddress);
609}
610
611bitflags!(
612 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
614 pub struct PipelineLayoutFlags: u32 {
615 const BASE_VERTEX_INSTANCE = 1 << 0;
617 const NUM_WORK_GROUPS = 1 << 1;
619 }
620);
621
622bitflags!(
623 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
625 pub struct BindGroupLayoutFlags: u32 {
626 const PARTIALLY_BOUND = 1 << 0;
628 }
629);
630
631bitflags!(
632 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
634 pub struct TextureFormatCapabilities: u32 {
635 const SAMPLED = 1 << 0;
637 const SAMPLED_LINEAR = 1 << 1;
639 const SAMPLED_MINMAX = 1 << 2;
641
642 const STORAGE = 1 << 3;
644 const STORAGE_READ_WRITE = 1 << 4;
646 const STORAGE_ATOMIC = 1 << 5;
648
649 const COLOR_ATTACHMENT = 1 << 6;
651 const COLOR_ATTACHMENT_BLEND = 1 << 7;
653 const DEPTH_STENCIL_ATTACHMENT = 1 << 8;
655
656 const MULTISAMPLE_X2 = 1 << 9;
658 const MULTISAMPLE_X4 = 1 << 10;
660 const MULTISAMPLE_X8 = 1 << 11;
662 const MULTISAMPLE_X16 = 1 << 12;
664
665 const MULTISAMPLE_RESOLVE = 1 << 13;
667
668 const COPY_SRC = 1 << 14;
670 const COPY_DST = 1 << 15;
672 }
673);
674
675bitflags!(
676 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
678 pub struct FormatAspects: u8 {
679 const COLOR = 1 << 0;
680 const DEPTH = 1 << 1;
681 const STENCIL = 1 << 2;
682 }
683);
684
685impl FormatAspects {
686 pub fn new(format: wgt::TextureFormat, aspect: wgt::TextureAspect) -> Self {
687 let aspect_mask = match aspect {
688 wgt::TextureAspect::All => Self::all(),
689 wgt::TextureAspect::DepthOnly => Self::DEPTH,
690 wgt::TextureAspect::StencilOnly => Self::STENCIL,
691 };
692 Self::from(format) & aspect_mask
693 }
694
695 pub fn is_one(&self) -> bool {
697 self.bits().count_ones() == 1
698 }
699
700 pub fn map(&self) -> wgt::TextureAspect {
701 match *self {
702 Self::COLOR => wgt::TextureAspect::All,
703 Self::DEPTH => wgt::TextureAspect::DepthOnly,
704 Self::STENCIL => wgt::TextureAspect::StencilOnly,
705 _ => unreachable!(),
706 }
707 }
708}
709
710impl From<wgt::TextureFormat> for FormatAspects {
711 fn from(format: wgt::TextureFormat) -> Self {
712 match format {
713 wgt::TextureFormat::Stencil8 => Self::STENCIL,
714 wgt::TextureFormat::Depth16Unorm
715 | wgt::TextureFormat::Depth32Float
716 | wgt::TextureFormat::Depth24Plus => Self::DEPTH,
717 wgt::TextureFormat::Depth32FloatStencil8 | wgt::TextureFormat::Depth24PlusStencil8 => {
718 Self::DEPTH | Self::STENCIL
719 }
720 _ => Self::COLOR,
721 }
722 }
723}
724
725bitflags!(
726 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
727 pub struct MemoryFlags: u32 {
728 const TRANSIENT = 1 << 0;
729 const PREFER_COHERENT = 1 << 1;
730 }
731);
732
733bitflags!(
736 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
737 pub struct AttachmentOps: u8 {
738 const LOAD = 1 << 0;
739 const STORE = 1 << 1;
740 }
741);
742
743bitflags::bitflags! {
744 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
746 pub struct BufferUses: u16 {
747 const MAP_READ = 1 << 0;
749 const MAP_WRITE = 1 << 1;
751 const COPY_SRC = 1 << 2;
753 const COPY_DST = 1 << 3;
755 const INDEX = 1 << 4;
757 const VERTEX = 1 << 5;
759 const UNIFORM = 1 << 6;
761 const STORAGE_READ = 1 << 7;
763 const STORAGE_READ_WRITE = 1 << 8;
765 const INDIRECT = 1 << 9;
767 const QUERY_RESOLVE = 1 << 10;
769 const INCLUSIVE = Self::MAP_READ.bits() | Self::COPY_SRC.bits() |
771 Self::INDEX.bits() | Self::VERTEX.bits() | Self::UNIFORM.bits() |
772 Self::STORAGE_READ.bits() | Self::INDIRECT.bits();
773 const EXCLUSIVE = Self::MAP_WRITE.bits() | Self::COPY_DST.bits() | Self::STORAGE_READ_WRITE.bits();
775 const ORDERED = Self::INCLUSIVE.bits() | Self::MAP_WRITE.bits();
779 }
780}
781
782bitflags::bitflags! {
783 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
785 pub struct TextureUses: u16 {
786 const UNINITIALIZED = 1 << 0;
788 const PRESENT = 1 << 1;
790 const COPY_SRC = 1 << 2;
792 const COPY_DST = 1 << 3;
794 const RESOURCE = 1 << 4;
796 const COLOR_TARGET = 1 << 5;
798 const DEPTH_STENCIL_READ = 1 << 6;
800 const DEPTH_STENCIL_WRITE = 1 << 7;
802 const STORAGE_READ = 1 << 8;
804 const STORAGE_READ_WRITE = 1 << 9;
806 const INCLUSIVE = Self::COPY_SRC.bits() | Self::RESOURCE.bits() | Self::DEPTH_STENCIL_READ.bits();
808 const EXCLUSIVE = Self::COPY_DST.bits() | Self::COLOR_TARGET.bits() | Self::DEPTH_STENCIL_WRITE.bits() | Self::STORAGE_READ.bits() | Self::STORAGE_READ_WRITE.bits() | Self::PRESENT.bits();
810 const ORDERED = Self::INCLUSIVE.bits() | Self::COLOR_TARGET.bits() | Self::DEPTH_STENCIL_WRITE.bits() | Self::STORAGE_READ.bits();
814
815 const COMPLEX = 1 << 10;
817 const UNKNOWN = 1 << 11;
820 }
821}
822
823#[derive(Clone, Debug)]
824pub struct InstanceDescriptor<'a> {
825 pub name: &'a str,
826 pub flags: wgt::InstanceFlags,
827 pub dx12_shader_compiler: wgt::Dx12Compiler,
828 pub gles_minor_version: wgt::Gles3MinorVersion,
829}
830
831#[derive(Clone, Debug)]
832pub struct Alignments {
833 pub buffer_copy_offset: wgt::BufferSize,
835 pub buffer_copy_pitch: wgt::BufferSize,
838}
839
840#[derive(Clone, Debug)]
841pub struct Capabilities {
842 pub limits: wgt::Limits,
843 pub alignments: Alignments,
844 pub downlevel: wgt::DownlevelCapabilities,
845}
846
847#[derive(Debug)]
848pub struct ExposedAdapter<A: Api> {
849 pub adapter: A::Adapter,
850 pub info: wgt::AdapterInfo,
851 pub features: wgt::Features,
852 pub capabilities: Capabilities,
853}
854
855#[derive(Debug, Clone)]
858pub struct SurfaceCapabilities {
859 pub formats: Vec<wgt::TextureFormat>,
863
864 pub swap_chain_sizes: RangeInclusive<u32>,
869
870 pub current_extent: Option<wgt::Extent3d>,
872
873 pub extents: RangeInclusive<wgt::Extent3d>,
877
878 pub usage: TextureUses,
882
883 pub present_modes: Vec<wgt::PresentMode>,
887
888 pub composite_alpha_modes: Vec<wgt::CompositeAlphaMode>,
892}
893
894#[derive(Debug)]
895pub struct AcquiredSurfaceTexture<A: Api> {
896 pub texture: A::SurfaceTexture,
897 pub suboptimal: bool,
901}
902
903#[derive(Debug)]
904pub struct OpenDevice<A: Api> {
905 pub device: A::Device,
906 pub queue: A::Queue,
907}
908
909#[derive(Clone, Debug)]
910pub struct BufferMapping {
911 pub ptr: NonNull<u8>,
912 pub is_coherent: bool,
913}
914
915#[derive(Clone, Debug)]
916pub struct BufferDescriptor<'a> {
917 pub label: Label<'a>,
918 pub size: wgt::BufferAddress,
919 pub usage: BufferUses,
920 pub memory_flags: MemoryFlags,
921}
922
923#[derive(Clone, Debug)]
924pub struct TextureDescriptor<'a> {
925 pub label: Label<'a>,
926 pub size: wgt::Extent3d,
927 pub mip_level_count: u32,
928 pub sample_count: u32,
929 pub dimension: wgt::TextureDimension,
930 pub format: wgt::TextureFormat,
931 pub usage: TextureUses,
932 pub memory_flags: MemoryFlags,
933 pub view_formats: Vec<wgt::TextureFormat>,
936}
937
938impl TextureDescriptor<'_> {
939 pub fn copy_extent(&self) -> CopyExtent {
940 CopyExtent::map_extent_to_copy_size(&self.size, self.dimension)
941 }
942
943 pub fn is_cube_compatible(&self) -> bool {
944 self.dimension == wgt::TextureDimension::D2
945 && self.size.depth_or_array_layers % 6 == 0
946 && self.sample_count == 1
947 && self.size.width == self.size.height
948 }
949
950 pub fn array_layer_count(&self) -> u32 {
951 match self.dimension {
952 wgt::TextureDimension::D1 | wgt::TextureDimension::D3 => 1,
953 wgt::TextureDimension::D2 => self.size.depth_or_array_layers,
954 }
955 }
956}
957
958#[derive(Clone, Debug)]
966pub struct TextureViewDescriptor<'a> {
967 pub label: Label<'a>,
968 pub format: wgt::TextureFormat,
969 pub dimension: wgt::TextureViewDimension,
970 pub usage: TextureUses,
971 pub range: wgt::ImageSubresourceRange,
972}
973
974#[derive(Clone, Debug)]
975pub struct SamplerDescriptor<'a> {
976 pub label: Label<'a>,
977 pub address_modes: [wgt::AddressMode; 3],
978 pub mag_filter: wgt::FilterMode,
979 pub min_filter: wgt::FilterMode,
980 pub mipmap_filter: wgt::FilterMode,
981 pub lod_clamp: Range<f32>,
982 pub compare: Option<wgt::CompareFunction>,
983 pub anisotropy_clamp: u16,
987 pub border_color: Option<wgt::SamplerBorderColor>,
988}
989
990#[derive(Clone, Debug)]
995pub struct BindGroupLayoutDescriptor<'a> {
996 pub label: Label<'a>,
997 pub flags: BindGroupLayoutFlags,
998 pub entries: &'a [wgt::BindGroupLayoutEntry],
999}
1000
1001#[derive(Clone, Debug)]
1002pub struct PipelineLayoutDescriptor<'a, A: Api> {
1003 pub label: Label<'a>,
1004 pub flags: PipelineLayoutFlags,
1005 pub bind_group_layouts: &'a [&'a A::BindGroupLayout],
1006 pub push_constant_ranges: &'a [wgt::PushConstantRange],
1007}
1008
1009#[derive(Debug)]
1010pub struct BufferBinding<'a, A: Api> {
1011 pub buffer: &'a A::Buffer,
1013
1014 pub offset: wgt::BufferAddress,
1026
1027 pub size: Option<wgt::BufferSize>,
1033}
1034
1035impl<A: Api> Clone for BufferBinding<'_, A> {
1037 fn clone(&self) -> Self {
1038 Self {
1039 buffer: self.buffer,
1040 offset: self.offset,
1041 size: self.size,
1042 }
1043 }
1044}
1045
1046#[derive(Debug)]
1047pub struct TextureBinding<'a, A: Api> {
1048 pub view: &'a A::TextureView,
1049 pub usage: TextureUses,
1050}
1051
1052impl<A: Api> Clone for TextureBinding<'_, A> {
1054 fn clone(&self) -> Self {
1055 Self {
1056 view: self.view,
1057 usage: self.usage,
1058 }
1059 }
1060}
1061
1062#[derive(Clone, Debug)]
1063pub struct BindGroupEntry {
1064 pub binding: u32,
1065 pub resource_index: u32,
1066 pub count: u32,
1067}
1068
1069#[derive(Clone, Debug)]
1079pub struct BindGroupDescriptor<'a, A: Api> {
1080 pub label: Label<'a>,
1081 pub layout: &'a A::BindGroupLayout,
1082 pub buffers: &'a [BufferBinding<'a, A>],
1083 pub samplers: &'a [&'a A::Sampler],
1084 pub textures: &'a [TextureBinding<'a, A>],
1085 pub entries: &'a [BindGroupEntry],
1086}
1087
1088#[derive(Clone, Debug)]
1089pub struct CommandEncoderDescriptor<'a, A: Api> {
1090 pub label: Label<'a>,
1091 pub queue: &'a A::Queue,
1092}
1093
1094pub struct NagaShader {
1096 pub module: Cow<'static, naga::Module>,
1098 pub info: naga::valid::ModuleInfo,
1100 pub debug_source: Option<DebugSource>,
1102}
1103
1104impl fmt::Debug for NagaShader {
1107 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1108 write!(formatter, "Naga shader")
1109 }
1110}
1111
1112#[allow(clippy::large_enum_variant)]
1114pub enum ShaderInput<'a> {
1115 Naga(NagaShader),
1116 SpirV(&'a [u32]),
1117}
1118
1119pub struct ShaderModuleDescriptor<'a> {
1120 pub label: Label<'a>,
1121 pub runtime_checks: bool,
1122}
1123
1124#[derive(Debug, Clone)]
1125pub struct DebugSource {
1126 pub file_name: Cow<'static, str>,
1127 pub source_code: Cow<'static, str>,
1128}
1129
1130#[derive(Debug)]
1132pub struct ProgrammableStage<'a, A: Api> {
1133 pub module: &'a A::ShaderModule,
1135 pub entry_point: &'a str,
1138}
1139
1140impl<A: Api> Clone for ProgrammableStage<'_, A> {
1142 fn clone(&self) -> Self {
1143 Self {
1144 module: self.module,
1145 entry_point: self.entry_point,
1146 }
1147 }
1148}
1149
1150#[derive(Clone, Debug)]
1152pub struct ComputePipelineDescriptor<'a, A: Api> {
1153 pub label: Label<'a>,
1154 pub layout: &'a A::PipelineLayout,
1156 pub stage: ProgrammableStage<'a, A>,
1158}
1159
1160#[derive(Clone, Debug)]
1162pub struct VertexBufferLayout<'a> {
1163 pub array_stride: wgt::BufferAddress,
1165 pub step_mode: wgt::VertexStepMode,
1167 pub attributes: &'a [wgt::VertexAttribute],
1169}
1170
1171#[derive(Clone, Debug)]
1173pub struct RenderPipelineDescriptor<'a, A: Api> {
1174 pub label: Label<'a>,
1175 pub layout: &'a A::PipelineLayout,
1177 pub vertex_buffers: &'a [VertexBufferLayout<'a>],
1179 pub vertex_stage: ProgrammableStage<'a, A>,
1181 pub primitive: wgt::PrimitiveState,
1183 pub depth_stencil: Option<wgt::DepthStencilState>,
1185 pub multisample: wgt::MultisampleState,
1187 pub fragment_stage: Option<ProgrammableStage<'a, A>>,
1189 pub color_targets: &'a [Option<wgt::ColorTargetState>],
1191 pub multiview: Option<NonZeroU32>,
1194}
1195
1196#[derive(Debug, Clone)]
1197pub struct SurfaceConfiguration {
1198 pub swap_chain_size: u32,
1201 pub present_mode: wgt::PresentMode,
1203 pub composite_alpha_mode: wgt::CompositeAlphaMode,
1205 pub format: wgt::TextureFormat,
1207 pub extent: wgt::Extent3d,
1210 pub usage: TextureUses,
1212 pub view_formats: Vec<wgt::TextureFormat>,
1215}
1216
1217#[derive(Debug, Clone)]
1218pub struct Rect<T> {
1219 pub x: T,
1220 pub y: T,
1221 pub w: T,
1222 pub h: T,
1223}
1224
1225#[derive(Debug, Clone)]
1226pub struct BufferBarrier<'a, A: Api> {
1227 pub buffer: &'a A::Buffer,
1228 pub usage: Range<BufferUses>,
1229}
1230
1231#[derive(Debug, Clone)]
1232pub struct TextureBarrier<'a, A: Api> {
1233 pub texture: &'a A::Texture,
1234 pub range: wgt::ImageSubresourceRange,
1235 pub usage: Range<TextureUses>,
1236}
1237
1238#[derive(Clone, Copy, Debug)]
1239pub struct BufferCopy {
1240 pub src_offset: wgt::BufferAddress,
1241 pub dst_offset: wgt::BufferAddress,
1242 pub size: wgt::BufferSize,
1243}
1244
1245#[derive(Clone, Debug)]
1246pub struct TextureCopyBase {
1247 pub mip_level: u32,
1248 pub array_layer: u32,
1249 pub origin: wgt::Origin3d,
1252 pub aspect: FormatAspects,
1253}
1254
1255#[derive(Clone, Copy, Debug)]
1256pub struct CopyExtent {
1257 pub width: u32,
1258 pub height: u32,
1259 pub depth: u32,
1260}
1261
1262#[derive(Clone, Debug)]
1263pub struct TextureCopy {
1264 pub src_base: TextureCopyBase,
1265 pub dst_base: TextureCopyBase,
1266 pub size: CopyExtent,
1267}
1268
1269#[derive(Clone, Debug)]
1270pub struct BufferTextureCopy {
1271 pub buffer_layout: wgt::ImageDataLayout,
1272 pub texture_base: TextureCopyBase,
1273 pub size: CopyExtent,
1274}
1275
1276#[derive(Debug)]
1277pub struct Attachment<'a, A: Api> {
1278 pub view: &'a A::TextureView,
1279 pub usage: TextureUses,
1282}
1283
1284impl<A: Api> Clone for Attachment<'_, A> {
1286 fn clone(&self) -> Self {
1287 Self {
1288 view: self.view,
1289 usage: self.usage,
1290 }
1291 }
1292}
1293
1294#[derive(Debug)]
1295pub struct ColorAttachment<'a, A: Api> {
1296 pub target: Attachment<'a, A>,
1297 pub resolve_target: Option<Attachment<'a, A>>,
1298 pub ops: AttachmentOps,
1299 pub clear_value: wgt::Color,
1300}
1301
1302impl<A: Api> Clone for ColorAttachment<'_, A> {
1304 fn clone(&self) -> Self {
1305 Self {
1306 target: self.target.clone(),
1307 resolve_target: self.resolve_target.clone(),
1308 ops: self.ops,
1309 clear_value: self.clear_value,
1310 }
1311 }
1312}
1313
1314#[derive(Clone, Debug)]
1315pub struct DepthStencilAttachment<'a, A: Api> {
1316 pub target: Attachment<'a, A>,
1317 pub depth_ops: AttachmentOps,
1318 pub stencil_ops: AttachmentOps,
1319 pub clear_value: (f32, u32),
1320}
1321
1322#[derive(Debug)]
1323pub struct RenderPassTimestampWrites<'a, A: Api> {
1324 pub query_set: &'a A::QuerySet,
1325 pub beginning_of_pass_write_index: Option<u32>,
1326 pub end_of_pass_write_index: Option<u32>,
1327}
1328
1329impl<A: Api> Clone for RenderPassTimestampWrites<'_, A> {
1331 fn clone(&self) -> Self {
1332 Self {
1333 query_set: self.query_set,
1334 beginning_of_pass_write_index: self.beginning_of_pass_write_index,
1335 end_of_pass_write_index: self.end_of_pass_write_index,
1336 }
1337 }
1338}
1339
1340#[derive(Clone, Debug)]
1341pub struct RenderPassDescriptor<'a, A: Api> {
1342 pub label: Label<'a>,
1343 pub extent: wgt::Extent3d,
1344 pub sample_count: u32,
1345 pub color_attachments: &'a [Option<ColorAttachment<'a, A>>],
1346 pub depth_stencil_attachment: Option<DepthStencilAttachment<'a, A>>,
1347 pub multiview: Option<NonZeroU32>,
1348 pub timestamp_writes: Option<RenderPassTimestampWrites<'a, A>>,
1349 pub occlusion_query_set: Option<&'a A::QuerySet>,
1350}
1351
1352#[derive(Debug)]
1353pub struct ComputePassTimestampWrites<'a, A: Api> {
1354 pub query_set: &'a A::QuerySet,
1355 pub beginning_of_pass_write_index: Option<u32>,
1356 pub end_of_pass_write_index: Option<u32>,
1357}
1358
1359impl<A: Api> Clone for ComputePassTimestampWrites<'_, A> {
1361 fn clone(&self) -> Self {
1362 Self {
1363 query_set: self.query_set,
1364 beginning_of_pass_write_index: self.beginning_of_pass_write_index,
1365 end_of_pass_write_index: self.end_of_pass_write_index,
1366 }
1367 }
1368}
1369
1370#[derive(Clone, Debug)]
1371pub struct ComputePassDescriptor<'a, A: Api> {
1372 pub label: Label<'a>,
1373 pub timestamp_writes: Option<ComputePassTimestampWrites<'a, A>>,
1374}
1375
1376pub static VALIDATION_CANARY: ValidationCanary = ValidationCanary {
1388 inner: AtomicBool::new(false),
1389};
1390
1391pub struct ValidationCanary {
1393 inner: AtomicBool,
1394}
1395
1396impl ValidationCanary {
1397 #[allow(dead_code)] fn set(&self) {
1399 self.inner.store(true, std::sync::atomic::Ordering::SeqCst);
1400 }
1401
1402 pub fn get_and_reset(&self) -> bool {
1405 self.inner.swap(false, std::sync::atomic::Ordering::SeqCst)
1406 }
1407}
1408
1409#[test]
1410fn test_default_limits() {
1411 let limits = wgt::Limits::default();
1412 assert!(limits.max_bind_groups <= MAX_BIND_GROUPS as u32);
1413}