wgpu/
lib.rs

1//! A cross-platform graphics and compute library based on [WebGPU](https://gpuweb.github.io/gpuweb/).
2//!
3//! To start using the API, create an [`Instance`].
4
5#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
6#![doc(html_logo_url = "https://raw.githubusercontent.com/gfx-rs/wgpu/master/logo.png")]
7#![warn(missing_docs, unsafe_op_in_unsafe_fn)]
8
9mod backend;
10mod context;
11pub mod util;
12#[macro_use]
13mod macros;
14
15use std::{
16    any::Any,
17    borrow::Cow,
18    error,
19    fmt::{Debug, Display},
20    future::Future,
21    marker::PhantomData,
22    num::NonZeroU32,
23    ops::{Bound, Deref, DerefMut, Range, RangeBounds},
24    sync::Arc,
25    thread,
26};
27
28use context::{Context, DeviceRequest, DynContext, ObjectId};
29use parking_lot::Mutex;
30
31pub use wgt::{
32    AdapterInfo, AddressMode, AstcBlock, AstcChannel, Backend, Backends, BindGroupLayoutEntry,
33    BindingType, BlendComponent, BlendFactor, BlendOperation, BlendState, BufferAddress,
34    BufferBindingType, BufferSize, BufferUsages, Color, ColorTargetState, ColorWrites,
35    CommandBufferDescriptor, CompareFunction, CompositeAlphaMode, DepthBiasState,
36    DepthStencilState, DeviceType, DownlevelCapabilities, DownlevelFlags, Dx12Compiler,
37    DynamicOffset, Extent3d, Face, Features, FilterMode, FrontFace, ImageDataLayout,
38    ImageSubresourceRange, IndexFormat, InstanceDescriptor, Limits, MultisampleState, Origin2d,
39    Origin3d, PipelineStatisticsTypes, PolygonMode, PowerPreference, PredefinedColorSpace,
40    PresentMode, PresentationTimestamp, PrimitiveState, PrimitiveTopology, PushConstantRange,
41    QueryType, RenderBundleDepthStencil, SamplerBindingType, SamplerBorderColor, ShaderLocation,
42    ShaderModel, ShaderStages, StencilFaceState, StencilOperation, StencilState,
43    StorageTextureAccess, SurfaceCapabilities, SurfaceStatus, TextureAspect, TextureDimension,
44    TextureFormat, TextureFormatFeatureFlags, TextureFormatFeatures, TextureSampleType,
45    TextureUsages, TextureViewDimension, VertexAttribute, VertexFormat, VertexStepMode,
46    WasmNotSend, WasmNotSync, COPY_BUFFER_ALIGNMENT, COPY_BYTES_PER_ROW_ALIGNMENT, MAP_ALIGNMENT,
47    PUSH_CONSTANT_ALIGNMENT, QUERY_RESOLVE_BUFFER_ALIGNMENT, QUERY_SET_MAX_QUERIES, QUERY_SIZE,
48    VERTEX_STRIDE_ALIGNMENT,
49};
50
51#[cfg(any(
52    not(target_arch = "wasm32"),
53    feature = "webgl",
54    target_os = "emscripten"
55))]
56#[doc(hidden)]
57pub use ::hal;
58#[cfg(any(
59    not(target_arch = "wasm32"),
60    feature = "webgl",
61    target_os = "emscripten"
62))]
63#[doc(hidden)]
64pub use ::wgc as core;
65
66// wasm-only types, we try to keep as many types non-platform
67// specific, but these need to depend on web-sys.
68#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
69pub use wgt::{ExternalImageSource, ImageCopyExternalImage};
70
71/// Filter for error scopes.
72#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd)]
73pub enum ErrorFilter {
74    /// Catch only out-of-memory errors.
75    OutOfMemory,
76    /// Catch only validation errors.
77    Validation,
78}
79static_assertions::assert_impl_all!(ErrorFilter: Send, Sync);
80
81type C = dyn DynContext;
82#[cfg(any(
83    not(target_arch = "wasm32"),
84    all(
85        feature = "fragile-send-sync-non-atomic-wasm",
86        not(target_feature = "atomics")
87    )
88))]
89type Data = dyn Any + Send + Sync;
90#[cfg(not(any(
91    not(target_arch = "wasm32"),
92    all(
93        feature = "fragile-send-sync-non-atomic-wasm",
94        not(target_feature = "atomics")
95    )
96)))]
97type Data = dyn Any;
98
99/// Context for all other wgpu objects. Instance of wgpu.
100///
101/// This is the first thing you create when using wgpu.
102/// Its primary use is to create [`Adapter`]s and [`Surface`]s.
103///
104/// Does not have to be kept alive.
105///
106/// Corresponds to [WebGPU `GPU`](https://gpuweb.github.io/gpuweb/#gpu-interface).
107#[derive(Debug)]
108pub struct Instance {
109    context: Arc<C>,
110}
111#[cfg(any(
112    not(target_arch = "wasm32"),
113    all(
114        feature = "fragile-send-sync-non-atomic-wasm",
115        not(target_feature = "atomics")
116    )
117))]
118static_assertions::assert_impl_all!(Instance: Send, Sync);
119
120/// Handle to a physical graphics and/or compute device.
121///
122/// Adapters can be used to open a connection to the corresponding [`Device`]
123/// on the host system by using [`Adapter::request_device`].
124///
125/// Does not have to be kept alive.
126///
127/// Corresponds to [WebGPU `GPUAdapter`](https://gpuweb.github.io/gpuweb/#gpu-adapter).
128#[derive(Debug)]
129pub struct Adapter {
130    context: Arc<C>,
131    id: ObjectId,
132    data: Box<Data>,
133}
134#[cfg(any(
135    not(target_arch = "wasm32"),
136    all(
137        feature = "fragile-send-sync-non-atomic-wasm",
138        not(target_feature = "atomics")
139    )
140))]
141static_assertions::assert_impl_all!(Adapter: Send, Sync);
142
143impl Drop for Adapter {
144    fn drop(&mut self) {
145        if !thread::panicking() {
146            self.context.adapter_drop(&self.id, self.data.as_ref())
147        }
148    }
149}
150
151/// Open connection to a graphics and/or compute device.
152///
153/// Responsible for the creation of most rendering and compute resources.
154/// These are then used in commands, which are submitted to a [`Queue`].
155///
156/// A device may be requested from an adapter with [`Adapter::request_device`].
157///
158/// Corresponds to [WebGPU `GPUDevice`](https://gpuweb.github.io/gpuweb/#gpu-device).
159#[derive(Debug)]
160pub struct Device {
161    context: Arc<C>,
162    id: ObjectId,
163    data: Box<Data>,
164}
165#[cfg(any(
166    not(target_arch = "wasm32"),
167    all(
168        feature = "fragile-send-sync-non-atomic-wasm",
169        not(target_feature = "atomics")
170    )
171))]
172static_assertions::assert_impl_all!(Device: Send, Sync);
173
174/// Identifier for a particular call to [`Queue::submit`]. Can be used
175/// as part of an argument to [`Device::poll`] to block for a particular
176/// submission to finish.
177///
178/// This type is unique to the Rust API of `wgpu`.
179/// There is no analogue in the WebGPU specification.
180#[derive(Debug, Clone)]
181pub struct SubmissionIndex(ObjectId, Arc<crate::Data>);
182#[cfg(any(
183    not(target_arch = "wasm32"),
184    all(
185        feature = "fragile-send-sync-non-atomic-wasm",
186        not(target_feature = "atomics")
187    )
188))]
189static_assertions::assert_impl_all!(SubmissionIndex: Send, Sync);
190
191/// The main purpose of this struct is to resolve mapped ranges (convert sizes
192/// to end points), and to ensure that the sub-ranges don't intersect.
193#[derive(Debug)]
194struct MapContext {
195    total_size: BufferAddress,
196    initial_range: Range<BufferAddress>,
197    sub_ranges: Vec<Range<BufferAddress>>,
198}
199
200impl MapContext {
201    fn new(total_size: BufferAddress) -> Self {
202        Self {
203            total_size,
204            initial_range: 0..0,
205            sub_ranges: Vec::new(),
206        }
207    }
208
209    fn reset(&mut self) {
210        self.initial_range = 0..0;
211
212        assert!(
213            self.sub_ranges.is_empty(),
214            "You cannot unmap a buffer that still has accessible mapped views"
215        );
216    }
217
218    fn add(&mut self, offset: BufferAddress, size: Option<BufferSize>) -> BufferAddress {
219        let end = match size {
220            Some(s) => offset + s.get(),
221            None => self.initial_range.end,
222        };
223        assert!(self.initial_range.start <= offset && end <= self.initial_range.end);
224        for sub in self.sub_ranges.iter() {
225            assert!(
226                end <= sub.start || offset >= sub.end,
227                "Intersecting map range with {sub:?}"
228            );
229        }
230        self.sub_ranges.push(offset..end);
231        end
232    }
233
234    fn remove(&mut self, offset: BufferAddress, size: Option<BufferSize>) {
235        let end = match size {
236            Some(s) => offset + s.get(),
237            None => self.initial_range.end,
238        };
239
240        let index = self
241            .sub_ranges
242            .iter()
243            .position(|r| *r == (offset..end))
244            .expect("unable to remove range from map context");
245        self.sub_ranges.swap_remove(index);
246    }
247}
248
249/// Handle to a GPU-accessible buffer.
250///
251/// Created with [`Device::create_buffer`] or
252/// [`DeviceExt::create_buffer_init`](util::DeviceExt::create_buffer_init).
253///
254/// Corresponds to [WebGPU `GPUBuffer`](https://gpuweb.github.io/gpuweb/#buffer-interface).
255#[derive(Debug)]
256pub struct Buffer {
257    context: Arc<C>,
258    id: ObjectId,
259    data: Box<Data>,
260    map_context: Mutex<MapContext>,
261    size: wgt::BufferAddress,
262    usage: BufferUsages,
263    // Todo: missing map_state https://www.w3.org/TR/webgpu/#dom-gpubuffer-mapstate
264}
265#[cfg(any(
266    not(target_arch = "wasm32"),
267    all(
268        feature = "fragile-send-sync-non-atomic-wasm",
269        not(target_feature = "atomics")
270    )
271))]
272static_assertions::assert_impl_all!(Buffer: Send, Sync);
273
274/// Slice into a [`Buffer`].
275///
276/// It can be created with [`Buffer::slice`]. To use the whole buffer, call with unbounded slice:
277///
278/// `buffer.slice(..)`
279///
280/// This type is unique to the Rust API of `wgpu`. In the WebGPU specification,
281/// an offset and size are specified as arguments to each call working with the [`Buffer`], instead.
282#[derive(Copy, Clone, Debug)]
283pub struct BufferSlice<'a> {
284    buffer: &'a Buffer,
285    offset: BufferAddress,
286    size: Option<BufferSize>,
287}
288#[cfg(any(
289    not(target_arch = "wasm32"),
290    all(
291        feature = "fragile-send-sync-non-atomic-wasm",
292        not(target_feature = "atomics")
293    )
294))]
295static_assertions::assert_impl_all!(BufferSlice: Send, Sync);
296
297/// Handle to a texture on the GPU.
298///
299/// It can be created with [`Device::create_texture`].
300///
301/// Corresponds to [WebGPU `GPUTexture`](https://gpuweb.github.io/gpuweb/#texture-interface).
302#[derive(Debug)]
303pub struct Texture {
304    context: Arc<C>,
305    id: ObjectId,
306    data: Box<Data>,
307    owned: bool,
308    descriptor: TextureDescriptor<'static>,
309}
310#[cfg(any(
311    not(target_arch = "wasm32"),
312    all(
313        feature = "fragile-send-sync-non-atomic-wasm",
314        not(target_feature = "atomics")
315    )
316))]
317static_assertions::assert_impl_all!(Texture: Send, Sync);
318
319/// Handle to a texture view.
320///
321/// A `TextureView` object describes a texture and associated metadata needed by a
322/// [`RenderPipeline`] or [`BindGroup`].
323///
324/// Corresponds to [WebGPU `GPUTextureView`](https://gpuweb.github.io/gpuweb/#gputextureview).
325#[derive(Debug)]
326pub struct TextureView {
327    context: Arc<C>,
328    id: ObjectId,
329    data: Box<Data>,
330}
331#[cfg(any(
332    not(target_arch = "wasm32"),
333    all(
334        feature = "fragile-send-sync-non-atomic-wasm",
335        not(target_feature = "atomics")
336    )
337))]
338static_assertions::assert_impl_all!(TextureView: Send, Sync);
339
340/// Handle to a sampler.
341///
342/// A `Sampler` object defines how a pipeline will sample from a [`TextureView`]. Samplers define
343/// image filters (including anisotropy) and address (wrapping) modes, among other things. See
344/// the documentation for [`SamplerDescriptor`] for more information.
345///
346/// It can be created with [`Device::create_sampler`].
347///
348/// Corresponds to [WebGPU `GPUSampler`](https://gpuweb.github.io/gpuweb/#sampler-interface).
349#[derive(Debug)]
350pub struct Sampler {
351    context: Arc<C>,
352    id: ObjectId,
353    data: Box<Data>,
354}
355#[cfg(any(
356    not(target_arch = "wasm32"),
357    all(
358        feature = "fragile-send-sync-non-atomic-wasm",
359        not(target_feature = "atomics")
360    )
361))]
362static_assertions::assert_impl_all!(Sampler: Send, Sync);
363
364impl Drop for Sampler {
365    fn drop(&mut self) {
366        if !thread::panicking() {
367            self.context.sampler_drop(&self.id, self.data.as_ref());
368        }
369    }
370}
371
372/// Describes a [`Surface`].
373///
374/// For use with [`Surface::configure`].
375///
376/// Corresponds to [WebGPU `GPUCanvasConfiguration`](
377/// https://gpuweb.github.io/gpuweb/#canvas-configuration).
378pub type SurfaceConfiguration = wgt::SurfaceConfiguration<Vec<TextureFormat>>;
379static_assertions::assert_impl_all!(SurfaceConfiguration: Send, Sync);
380
381/// Handle to a presentable surface.
382///
383/// A `Surface` represents a platform-specific surface (e.g. a window) onto which rendered images may
384/// be presented. A `Surface` may be created with the unsafe function [`Instance::create_surface`].
385///
386/// This type is unique to the Rust API of `wgpu`. In the WebGPU specification,
387/// [`GPUCanvasContext`](https://gpuweb.github.io/gpuweb/#canvas-context)
388/// serves a similar role.
389#[derive(Debug)]
390pub struct Surface {
391    context: Arc<C>,
392    id: ObjectId,
393    data: Box<Data>,
394    // Stores the latest `SurfaceConfiguration` that was set using `Surface::configure`.
395    // It is required to set the attributes of the `SurfaceTexture` in the
396    // `Surface::get_current_texture` method.
397    // Because the `Surface::configure` method operates on an immutable reference this type has to
398    // be wrapped in a mutex and since the configuration is only supplied after the surface has
399    // been created is is additionally wrapped in an option.
400    config: Mutex<Option<SurfaceConfiguration>>,
401}
402#[cfg(any(
403    not(target_arch = "wasm32"),
404    all(
405        feature = "fragile-send-sync-non-atomic-wasm",
406        not(target_feature = "atomics")
407    )
408))]
409static_assertions::assert_impl_all!(Surface: Send, Sync);
410
411impl Drop for Surface {
412    fn drop(&mut self) {
413        if !thread::panicking() {
414            self.context.surface_drop(&self.id, self.data.as_ref())
415        }
416    }
417}
418
419/// Handle to a binding group layout.
420///
421/// A `BindGroupLayout` is a handle to the GPU-side layout of a binding group. It can be used to
422/// create a [`BindGroupDescriptor`] object, which in turn can be used to create a [`BindGroup`]
423/// object with [`Device::create_bind_group`]. A series of `BindGroupLayout`s can also be used to
424/// create a [`PipelineLayoutDescriptor`], which can be used to create a [`PipelineLayout`].
425///
426/// It can be created with [`Device::create_bind_group_layout`].
427///
428/// Corresponds to [WebGPU `GPUBindGroupLayout`](
429/// https://gpuweb.github.io/gpuweb/#gpubindgrouplayout).
430#[derive(Debug)]
431pub struct BindGroupLayout {
432    context: Arc<C>,
433    id: ObjectId,
434    data: Box<Data>,
435}
436#[cfg(any(
437    not(target_arch = "wasm32"),
438    all(
439        feature = "fragile-send-sync-non-atomic-wasm",
440        not(target_feature = "atomics")
441    )
442))]
443static_assertions::assert_impl_all!(BindGroupLayout: Send, Sync);
444
445impl Drop for BindGroupLayout {
446    fn drop(&mut self) {
447        if !thread::panicking() {
448            self.context
449                .bind_group_layout_drop(&self.id, self.data.as_ref());
450        }
451    }
452}
453
454/// Handle to a binding group.
455///
456/// A `BindGroup` represents the set of resources bound to the bindings described by a
457/// [`BindGroupLayout`]. It can be created with [`Device::create_bind_group`]. A `BindGroup` can
458/// be bound to a particular [`RenderPass`] with [`RenderPass::set_bind_group`], or to a
459/// [`ComputePass`] with [`ComputePass::set_bind_group`].
460///
461/// Corresponds to [WebGPU `GPUBindGroup`](https://gpuweb.github.io/gpuweb/#gpubindgroup).
462#[derive(Debug)]
463pub struct BindGroup {
464    context: Arc<C>,
465    id: ObjectId,
466    data: Box<Data>,
467}
468#[cfg(any(
469    not(target_arch = "wasm32"),
470    all(
471        feature = "fragile-send-sync-non-atomic-wasm",
472        not(target_feature = "atomics")
473    )
474))]
475static_assertions::assert_impl_all!(BindGroup: Send, Sync);
476
477impl Drop for BindGroup {
478    fn drop(&mut self) {
479        if !thread::panicking() {
480            self.context.bind_group_drop(&self.id, self.data.as_ref());
481        }
482    }
483}
484
485/// Handle to a compiled shader module.
486///
487/// A `ShaderModule` represents a compiled shader module on the GPU. It can be created by passing
488/// source code to [`Device::create_shader_module`] or valid SPIR-V binary to
489/// [`Device::create_shader_module_spirv`]. Shader modules are used to define programmable stages
490/// of a pipeline.
491///
492/// Corresponds to [WebGPU `GPUShaderModule`](https://gpuweb.github.io/gpuweb/#shader-module).
493#[derive(Debug)]
494pub struct ShaderModule {
495    context: Arc<C>,
496    id: ObjectId,
497    data: Box<Data>,
498}
499#[cfg(any(
500    not(target_arch = "wasm32"),
501    all(
502        feature = "fragile-send-sync-non-atomic-wasm",
503        not(target_feature = "atomics")
504    )
505))]
506static_assertions::assert_impl_all!(ShaderModule: Send, Sync);
507
508impl Drop for ShaderModule {
509    fn drop(&mut self) {
510        if !thread::panicking() {
511            self.context
512                .shader_module_drop(&self.id, self.data.as_ref());
513        }
514    }
515}
516
517/// Source of a shader module.
518///
519/// The source will be parsed and validated.
520///
521/// Any necessary shader translation (e.g. from WGSL to SPIR-V or vice versa)
522/// will be done internally by wgpu.
523///
524/// This type is unique to the Rust API of `wgpu`. In the WebGPU specification,
525/// only WGSL source code strings are accepted.
526#[cfg_attr(feature = "naga", allow(clippy::large_enum_variant))]
527#[derive(Clone)]
528#[non_exhaustive]
529pub enum ShaderSource<'a> {
530    /// SPIR-V module represented as a slice of words.
531    ///
532    /// See also: [`util::make_spirv`], [`include_spirv`]
533    #[cfg(feature = "spirv")]
534    SpirV(Cow<'a, [u32]>),
535    /// GLSL module as a string slice.
536    ///
537    /// Note: GLSL is not yet fully supported and must be a specific ShaderStage.
538    #[cfg(feature = "glsl")]
539    Glsl {
540        /// The source code of the shader.
541        shader: Cow<'a, str>,
542        /// The shader stage that the shader targets. For example, `naga::ShaderStage::Vertex`
543        stage: naga::ShaderStage,
544        /// Defines to unlock configured shader features.
545        defines: naga::FastHashMap<String, String>,
546    },
547    /// WGSL module as a string slice.
548    #[cfg(feature = "wgsl")]
549    Wgsl(Cow<'a, str>),
550    /// Naga module.
551    #[cfg(feature = "naga")]
552    Naga(Cow<'static, naga::Module>),
553    /// Dummy variant because `Naga` doesn't have a lifetime and without enough active features it
554    /// could be the last one active.
555    #[doc(hidden)]
556    Dummy(PhantomData<&'a ()>),
557}
558static_assertions::assert_impl_all!(ShaderSource: Send, Sync);
559
560/// Descriptor for use with [`Device::create_shader_module`].
561///
562/// Corresponds to [WebGPU `GPUShaderModuleDescriptor`](
563/// https://gpuweb.github.io/gpuweb/#dictdef-gpushadermoduledescriptor).
564#[derive(Clone)]
565pub struct ShaderModuleDescriptor<'a> {
566    /// Debug label of the shader module. This will show up in graphics debuggers for easy identification.
567    pub label: Label<'a>,
568    /// Source code for the shader.
569    pub source: ShaderSource<'a>,
570}
571static_assertions::assert_impl_all!(ShaderModuleDescriptor: Send, Sync);
572
573/// Descriptor for a shader module given by SPIR-V binary, for use with
574/// [`Device::create_shader_module_spirv`].
575///
576/// This type is unique to the Rust API of `wgpu`. In the WebGPU specification,
577/// only WGSL source code strings are accepted.
578pub struct ShaderModuleDescriptorSpirV<'a> {
579    /// Debug label of the shader module. This will show up in graphics debuggers for easy identification.
580    pub label: Label<'a>,
581    /// Binary SPIR-V data, in 4-byte words.
582    pub source: Cow<'a, [u32]>,
583}
584static_assertions::assert_impl_all!(ShaderModuleDescriptorSpirV: Send, Sync);
585
586/// Handle to a pipeline layout.
587///
588/// A `PipelineLayout` object describes the available binding groups of a pipeline.
589/// It can be created with [`Device::create_pipeline_layout`].
590///
591/// Corresponds to [WebGPU `GPUPipelineLayout`](https://gpuweb.github.io/gpuweb/#gpupipelinelayout).
592#[derive(Debug)]
593pub struct PipelineLayout {
594    context: Arc<C>,
595    id: ObjectId,
596    data: Box<Data>,
597}
598#[cfg(any(
599    not(target_arch = "wasm32"),
600    all(
601        feature = "fragile-send-sync-non-atomic-wasm",
602        not(target_feature = "atomics")
603    )
604))]
605static_assertions::assert_impl_all!(PipelineLayout: Send, Sync);
606
607impl Drop for PipelineLayout {
608    fn drop(&mut self) {
609        if !thread::panicking() {
610            self.context
611                .pipeline_layout_drop(&self.id, self.data.as_ref());
612        }
613    }
614}
615
616/// Handle to a rendering (graphics) pipeline.
617///
618/// A `RenderPipeline` object represents a graphics pipeline and its stages, bindings, vertex
619/// buffers and targets. It can be created with [`Device::create_render_pipeline`].
620///
621/// Corresponds to [WebGPU `GPURenderPipeline`](https://gpuweb.github.io/gpuweb/#render-pipeline).
622#[derive(Debug)]
623pub struct RenderPipeline {
624    context: Arc<C>,
625    id: ObjectId,
626    data: Box<Data>,
627}
628#[cfg(any(
629    not(target_arch = "wasm32"),
630    all(
631        feature = "fragile-send-sync-non-atomic-wasm",
632        not(target_feature = "atomics")
633    )
634))]
635static_assertions::assert_impl_all!(RenderPipeline: Send, Sync);
636
637impl Drop for RenderPipeline {
638    fn drop(&mut self) {
639        if !thread::panicking() {
640            self.context
641                .render_pipeline_drop(&self.id, self.data.as_ref());
642        }
643    }
644}
645
646impl RenderPipeline {
647    /// Get an object representing the bind group layout at a given index.
648    pub fn get_bind_group_layout(&self, index: u32) -> BindGroupLayout {
649        let context = Arc::clone(&self.context);
650        let (id, data) =
651            self.context
652                .render_pipeline_get_bind_group_layout(&self.id, self.data.as_ref(), index);
653        BindGroupLayout { context, id, data }
654    }
655}
656
657/// Handle to a compute pipeline.
658///
659/// A `ComputePipeline` object represents a compute pipeline and its single shader stage.
660/// It can be created with [`Device::create_compute_pipeline`].
661///
662/// Corresponds to [WebGPU `GPUComputePipeline`](https://gpuweb.github.io/gpuweb/#compute-pipeline).
663#[derive(Debug)]
664pub struct ComputePipeline {
665    context: Arc<C>,
666    id: ObjectId,
667    data: Box<Data>,
668}
669#[cfg(any(
670    not(target_arch = "wasm32"),
671    all(
672        feature = "fragile-send-sync-non-atomic-wasm",
673        not(target_feature = "atomics")
674    )
675))]
676static_assertions::assert_impl_all!(ComputePipeline: Send, Sync);
677
678impl Drop for ComputePipeline {
679    fn drop(&mut self) {
680        if !thread::panicking() {
681            self.context
682                .compute_pipeline_drop(&self.id, self.data.as_ref());
683        }
684    }
685}
686
687impl ComputePipeline {
688    /// Get an object representing the bind group layout at a given index.
689    pub fn get_bind_group_layout(&self, index: u32) -> BindGroupLayout {
690        let context = Arc::clone(&self.context);
691        let (id, data) = self.context.compute_pipeline_get_bind_group_layout(
692            &self.id,
693            self.data.as_ref(),
694            index,
695        );
696        BindGroupLayout { context, id, data }
697    }
698}
699
700/// Handle to a command buffer on the GPU.
701///
702/// A `CommandBuffer` represents a complete sequence of commands that may be submitted to a command
703/// queue with [`Queue::submit`]. A `CommandBuffer` is obtained by recording a series of commands to
704/// a [`CommandEncoder`] and then calling [`CommandEncoder::finish`].
705///
706/// Corresponds to [WebGPU `GPUCommandBuffer`](https://gpuweb.github.io/gpuweb/#command-buffer).
707#[derive(Debug)]
708pub struct CommandBuffer {
709    context: Arc<C>,
710    id: Option<ObjectId>,
711    data: Option<Box<Data>>,
712}
713#[cfg(any(
714    not(target_arch = "wasm32"),
715    all(
716        feature = "fragile-send-sync-non-atomic-wasm",
717        not(target_feature = "atomics")
718    )
719))]
720static_assertions::assert_impl_all!(CommandBuffer: Send, Sync);
721
722impl Drop for CommandBuffer {
723    fn drop(&mut self) {
724        if !thread::panicking() {
725            if let Some(id) = self.id.take() {
726                self.context
727                    .command_buffer_drop(&id, self.data.take().unwrap().as_ref());
728            }
729        }
730    }
731}
732
733/// Encodes a series of GPU operations.
734///
735/// A command encoder can record [`RenderPass`]es, [`ComputePass`]es,
736/// and transfer operations between driver-managed resources like [`Buffer`]s and [`Texture`]s.
737///
738/// When finished recording, call [`CommandEncoder::finish`] to obtain a [`CommandBuffer`] which may
739/// be submitted for execution.
740///
741/// Corresponds to [WebGPU `GPUCommandEncoder`](https://gpuweb.github.io/gpuweb/#command-encoder).
742#[derive(Debug)]
743pub struct CommandEncoder {
744    context: Arc<C>,
745    id: Option<ObjectId>,
746    data: Box<Data>,
747}
748#[cfg(any(
749    not(target_arch = "wasm32"),
750    all(
751        feature = "fragile-send-sync-non-atomic-wasm",
752        not(target_feature = "atomics")
753    )
754))]
755static_assertions::assert_impl_all!(CommandEncoder: Send, Sync);
756
757impl Drop for CommandEncoder {
758    fn drop(&mut self) {
759        if !thread::panicking() {
760            if let Some(id) = self.id.take() {
761                self.context.command_encoder_drop(&id, self.data.as_ref());
762            }
763        }
764    }
765}
766
767/// In-progress recording of a render pass.
768///
769/// It can be created with [`CommandEncoder::begin_render_pass`].
770///
771/// Corresponds to [WebGPU `GPURenderPassEncoder`](
772/// https://gpuweb.github.io/gpuweb/#render-pass-encoder).
773#[derive(Debug)]
774pub struct RenderPass<'a> {
775    id: ObjectId,
776    data: Box<Data>,
777    parent: &'a mut CommandEncoder,
778}
779
780/// In-progress recording of a compute pass.
781///
782/// It can be created with [`CommandEncoder::begin_compute_pass`].
783///
784/// Corresponds to [WebGPU `GPUComputePassEncoder`](
785/// https://gpuweb.github.io/gpuweb/#compute-pass-encoder).
786#[derive(Debug)]
787pub struct ComputePass<'a> {
788    id: ObjectId,
789    data: Box<Data>,
790    parent: &'a mut CommandEncoder,
791}
792
793/// Encodes a series of GPU operations into a reusable "render bundle".
794///
795/// It only supports a handful of render commands, but it makes them reusable.
796/// It can be created with [`Device::create_render_bundle_encoder`].
797/// It can be executed onto a [`CommandEncoder`] using [`RenderPass::execute_bundles`].
798///
799/// Executing a [`RenderBundle`] is often more efficient than issuing the underlying commands
800/// manually.
801///
802/// Corresponds to [WebGPU `GPURenderBundleEncoder`](
803/// https://gpuweb.github.io/gpuweb/#gpurenderbundleencoder).
804#[derive(Debug)]
805pub struct RenderBundleEncoder<'a> {
806    context: Arc<C>,
807    id: ObjectId,
808    data: Box<Data>,
809    parent: &'a Device,
810    /// This type should be !Send !Sync, because it represents an allocation on this thread's
811    /// command buffer.
812    _p: PhantomData<*const u8>,
813}
814static_assertions::assert_not_impl_any!(RenderBundleEncoder<'_>: Send, Sync);
815
816/// Pre-prepared reusable bundle of GPU operations.
817///
818/// It only supports a handful of render commands, but it makes them reusable. Executing a
819/// [`RenderBundle`] is often more efficient than issuing the underlying commands manually.
820///
821/// It can be created by use of a [`RenderBundleEncoder`], and executed onto a [`CommandEncoder`]
822/// using [`RenderPass::execute_bundles`].
823///
824/// Corresponds to [WebGPU `GPURenderBundle`](https://gpuweb.github.io/gpuweb/#render-bundle).
825#[derive(Debug)]
826pub struct RenderBundle {
827    context: Arc<C>,
828    id: ObjectId,
829    data: Box<Data>,
830}
831#[cfg(any(
832    not(target_arch = "wasm32"),
833    all(
834        feature = "fragile-send-sync-non-atomic-wasm",
835        not(target_feature = "atomics")
836    )
837))]
838static_assertions::assert_impl_all!(RenderBundle: Send, Sync);
839
840impl Drop for RenderBundle {
841    fn drop(&mut self) {
842        if !thread::panicking() {
843            self.context
844                .render_bundle_drop(&self.id, self.data.as_ref());
845        }
846    }
847}
848
849/// Handle to a query set.
850///
851/// It can be created with [`Device::create_query_set`].
852///
853/// Corresponds to [WebGPU `GPUQuerySet`](https://gpuweb.github.io/gpuweb/#queryset).
854pub struct QuerySet {
855    context: Arc<C>,
856    id: ObjectId,
857    data: Box<Data>,
858}
859#[cfg(any(
860    not(target_arch = "wasm32"),
861    all(
862        feature = "fragile-send-sync-non-atomic-wasm",
863        not(target_feature = "atomics")
864    )
865))]
866static_assertions::assert_impl_all!(QuerySet: Send, Sync);
867
868impl Drop for QuerySet {
869    fn drop(&mut self) {
870        if !thread::panicking() {
871            self.context.query_set_drop(&self.id, self.data.as_ref());
872        }
873    }
874}
875
876/// Handle to a command queue on a device.
877///
878/// A `Queue` executes recorded [`CommandBuffer`] objects and provides convenience methods
879/// for writing to [buffers](Queue::write_buffer) and [textures](Queue::write_texture).
880/// It can be created along with a [`Device`] by calling [`Adapter::request_device`].
881///
882/// Corresponds to [WebGPU `GPUQueue`](https://gpuweb.github.io/gpuweb/#gpu-queue).
883#[derive(Debug)]
884pub struct Queue {
885    context: Arc<C>,
886    id: ObjectId,
887    data: Box<Data>,
888}
889#[cfg(any(
890    not(target_arch = "wasm32"),
891    all(
892        feature = "fragile-send-sync-non-atomic-wasm",
893        not(target_feature = "atomics")
894    )
895))]
896static_assertions::assert_impl_all!(Queue: Send, Sync);
897
898/// Resource that can be bound to a pipeline.
899///
900/// Corresponds to [WebGPU `GPUBindingResource`](
901/// https://gpuweb.github.io/gpuweb/#typedefdef-gpubindingresource).
902#[non_exhaustive]
903#[derive(Clone, Debug)]
904pub enum BindingResource<'a> {
905    /// Binding is backed by a buffer.
906    ///
907    /// Corresponds to [`wgt::BufferBindingType::Uniform`] and [`wgt::BufferBindingType::Storage`]
908    /// with [`BindGroupLayoutEntry::count`] set to None.
909    Buffer(BufferBinding<'a>),
910    /// Binding is backed by an array of buffers.
911    ///
912    /// [`Features::BUFFER_BINDING_ARRAY`] must be supported to use this feature.
913    ///
914    /// Corresponds to [`wgt::BufferBindingType::Uniform`] and [`wgt::BufferBindingType::Storage`]
915    /// with [`BindGroupLayoutEntry::count`] set to Some.
916    BufferArray(&'a [BufferBinding<'a>]),
917    /// Binding is a sampler.
918    ///
919    /// Corresponds to [`wgt::BindingType::Sampler`] with [`BindGroupLayoutEntry::count`] set to None.
920    Sampler(&'a Sampler),
921    /// Binding is backed by an array of samplers.
922    ///
923    /// [`Features::TEXTURE_BINDING_ARRAY`] must be supported to use this feature.
924    ///
925    /// Corresponds to [`wgt::BindingType::Sampler`] with [`BindGroupLayoutEntry::count`] set
926    /// to Some.
927    SamplerArray(&'a [&'a Sampler]),
928    /// Binding is backed by a texture.
929    ///
930    /// Corresponds to [`wgt::BindingType::Texture`] and [`wgt::BindingType::StorageTexture`] with
931    /// [`BindGroupLayoutEntry::count`] set to None.
932    TextureView(&'a TextureView),
933    /// Binding is backed by an array of textures.
934    ///
935    /// [`Features::TEXTURE_BINDING_ARRAY`] must be supported to use this feature.
936    ///
937    /// Corresponds to [`wgt::BindingType::Texture`] and [`wgt::BindingType::StorageTexture`] with
938    /// [`BindGroupLayoutEntry::count`] set to Some.
939    TextureViewArray(&'a [&'a TextureView]),
940}
941#[cfg(any(
942    not(target_arch = "wasm32"),
943    all(
944        feature = "fragile-send-sync-non-atomic-wasm",
945        not(target_feature = "atomics")
946    )
947))]
948static_assertions::assert_impl_all!(BindingResource: Send, Sync);
949
950/// Describes the segment of a buffer to bind.
951///
952/// Corresponds to [WebGPU `GPUBufferBinding`](
953/// https://gpuweb.github.io/gpuweb/#dictdef-gpubufferbinding).
954#[derive(Clone, Debug)]
955pub struct BufferBinding<'a> {
956    /// The buffer to bind.
957    pub buffer: &'a Buffer,
958
959    /// Base offset of the buffer, in bytes.
960    ///
961    /// If the [`has_dynamic_offset`] field of this buffer's layout entry is
962    /// `true`, the offset here will be added to the dynamic offset passed to
963    /// [`RenderPass::set_bind_group`] or [`ComputePass::set_bind_group`].
964    ///
965    /// If the buffer was created with [`BufferUsages::UNIFORM`], then this
966    /// offset must be a multiple of
967    /// [`Limits::min_uniform_buffer_offset_alignment`].
968    ///
969    /// If the buffer was created with [`BufferUsages::STORAGE`], then this
970    /// offset must be a multiple of
971    /// [`Limits::min_storage_buffer_offset_alignment`].
972    ///
973    /// [`has_dynamic_offset`]: BindingType::Buffer::has_dynamic_offset
974    pub offset: BufferAddress,
975
976    /// Size of the binding in bytes, or `None` for using the rest of the buffer.
977    pub size: Option<BufferSize>,
978}
979#[cfg(any(
980    not(target_arch = "wasm32"),
981    all(
982        feature = "fragile-send-sync-non-atomic-wasm",
983        not(target_feature = "atomics")
984    )
985))]
986static_assertions::assert_impl_all!(BufferBinding: Send, Sync);
987
988/// Operation to perform to the output attachment at the start of a render pass.
989///
990/// The render target must be cleared at least once before its content is loaded.
991///
992/// Corresponds to [WebGPU `GPULoadOp`](https://gpuweb.github.io/gpuweb/#enumdef-gpuloadop).
993#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
994#[cfg_attr(feature = "trace", derive(serde::Serialize))]
995#[cfg_attr(feature = "replay", derive(serde::Deserialize))]
996pub enum LoadOp<V> {
997    /// Clear with a specified value.
998    Clear(V),
999    /// Load from memory.
1000    Load,
1001}
1002
1003impl<V: Default> Default for LoadOp<V> {
1004    fn default() -> Self {
1005        Self::Clear(Default::default())
1006    }
1007}
1008
1009/// Pair of load and store operations for an attachment aspect.
1010///
1011/// This type is unique to the Rust API of `wgpu`. In the WebGPU specification,
1012/// separate `loadOp` and `storeOp` fields are used instead.
1013#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
1014#[cfg_attr(feature = "trace", derive(serde::Serialize))]
1015#[cfg_attr(feature = "replay", derive(serde::Deserialize))]
1016pub struct Operations<V> {
1017    /// How data should be read through this attachment.
1018    pub load: LoadOp<V>,
1019    /// Whether data will be written to through this attachment.
1020    pub store: bool,
1021}
1022
1023impl<V: Default> Default for Operations<V> {
1024    fn default() -> Self {
1025        Self {
1026            load: Default::default(),
1027            store: true,
1028        }
1029    }
1030}
1031
1032/// Describes a color attachment to a [`RenderPass`].
1033///
1034/// For use with [`RenderPassDescriptor`].
1035///
1036/// Corresponds to [WebGPU `GPURenderPassColorAttachment`](
1037/// https://gpuweb.github.io/gpuweb/#color-attachments).
1038#[derive(Clone, Debug)]
1039pub struct RenderPassColorAttachment<'tex> {
1040    /// The view to use as an attachment.
1041    pub view: &'tex TextureView,
1042    /// The view that will receive the resolved output if multisampling is used.
1043    pub resolve_target: Option<&'tex TextureView>,
1044    /// What operations will be performed on this color attachment.
1045    pub ops: Operations<Color>,
1046}
1047#[cfg(any(
1048    not(target_arch = "wasm32"),
1049    all(
1050        feature = "fragile-send-sync-non-atomic-wasm",
1051        not(target_feature = "atomics")
1052    )
1053))]
1054static_assertions::assert_impl_all!(RenderPassColorAttachment: Send, Sync);
1055
1056/// Describes a depth/stencil attachment to a [`RenderPass`].
1057///
1058/// For use with [`RenderPassDescriptor`].
1059///
1060/// Corresponds to [WebGPU `GPURenderPassDepthStencilAttachment`](
1061/// https://gpuweb.github.io/gpuweb/#depth-stencil-attachments).
1062#[derive(Clone, Debug)]
1063pub struct RenderPassDepthStencilAttachment<'tex> {
1064    /// The view to use as an attachment.
1065    pub view: &'tex TextureView,
1066    /// What operations will be performed on the depth part of the attachment.
1067    pub depth_ops: Option<Operations<f32>>,
1068    /// What operations will be performed on the stencil part of the attachment.
1069    pub stencil_ops: Option<Operations<u32>>,
1070}
1071#[cfg(any(
1072    not(target_arch = "wasm32"),
1073    all(
1074        feature = "fragile-send-sync-non-atomic-wasm",
1075        not(target_feature = "atomics")
1076    )
1077))]
1078static_assertions::assert_impl_all!(RenderPassDepthStencilAttachment: Send, Sync);
1079
1080// The underlying types are also exported so that documentation shows up for them
1081
1082/// Object debugging label.
1083pub type Label<'a> = Option<&'a str>;
1084pub use wgt::RequestAdapterOptions as RequestAdapterOptionsBase;
1085/// Additional information required when requesting an adapter.
1086///
1087/// For use with [`Instance::request_adapter`].
1088///
1089/// Corresponds to [WebGPU `GPURequestAdapterOptions`](
1090/// https://gpuweb.github.io/gpuweb/#dictdef-gpurequestadapteroptions).
1091pub type RequestAdapterOptions<'a> = RequestAdapterOptionsBase<&'a Surface>;
1092#[cfg(any(
1093    not(target_arch = "wasm32"),
1094    all(
1095        feature = "fragile-send-sync-non-atomic-wasm",
1096        not(target_feature = "atomics")
1097    )
1098))]
1099static_assertions::assert_impl_all!(RequestAdapterOptions: Send, Sync);
1100/// Describes a [`Device`].
1101///
1102/// For use with [`Adapter::request_device`].
1103///
1104/// Corresponds to [WebGPU `GPUDeviceDescriptor`](
1105/// https://gpuweb.github.io/gpuweb/#dictdef-gpudevicedescriptor).
1106pub type DeviceDescriptor<'a> = wgt::DeviceDescriptor<Label<'a>>;
1107static_assertions::assert_impl_all!(DeviceDescriptor: Send, Sync);
1108/// Describes a [`Buffer`].
1109///
1110/// For use with [`Device::create_buffer`].
1111///
1112/// Corresponds to [WebGPU `GPUBufferDescriptor`](
1113/// https://gpuweb.github.io/gpuweb/#dictdef-gpubufferdescriptor).
1114pub type BufferDescriptor<'a> = wgt::BufferDescriptor<Label<'a>>;
1115static_assertions::assert_impl_all!(BufferDescriptor: Send, Sync);
1116/// Describes a [`CommandEncoder`].
1117///
1118/// For use with [`Device::create_command_encoder`].
1119///
1120/// Corresponds to [WebGPU `GPUCommandEncoderDescriptor`](
1121/// https://gpuweb.github.io/gpuweb/#dictdef-gpucommandencoderdescriptor).
1122pub type CommandEncoderDescriptor<'a> = wgt::CommandEncoderDescriptor<Label<'a>>;
1123static_assertions::assert_impl_all!(CommandEncoderDescriptor: Send, Sync);
1124/// Describes a [`RenderBundle`].
1125///
1126/// For use with [`RenderBundleEncoder::finish`].
1127///
1128/// Corresponds to [WebGPU `GPURenderBundleDescriptor`](
1129/// https://gpuweb.github.io/gpuweb/#dictdef-gpurenderbundledescriptor).
1130pub type RenderBundleDescriptor<'a> = wgt::RenderBundleDescriptor<Label<'a>>;
1131static_assertions::assert_impl_all!(RenderBundleDescriptor: Send, Sync);
1132/// Describes a [`Texture`].
1133///
1134/// For use with [`Device::create_texture`].
1135///
1136/// Corresponds to [WebGPU `GPUTextureDescriptor`](
1137/// https://gpuweb.github.io/gpuweb/#dictdef-gputexturedescriptor).
1138pub type TextureDescriptor<'a> = wgt::TextureDescriptor<Label<'a>, &'a [TextureFormat]>;
1139static_assertions::assert_impl_all!(TextureDescriptor: Send, Sync);
1140/// Describes a [`QuerySet`].
1141///
1142/// For use with [`Device::create_query_set`].
1143///
1144/// Corresponds to [WebGPU `GPUQuerySetDescriptor`](
1145/// https://gpuweb.github.io/gpuweb/#dictdef-gpuquerysetdescriptor).
1146pub type QuerySetDescriptor<'a> = wgt::QuerySetDescriptor<Label<'a>>;
1147static_assertions::assert_impl_all!(QuerySetDescriptor: Send, Sync);
1148pub use wgt::Maintain as MaintainBase;
1149/// Passed to [`Device::poll`] to control how and if it should block.
1150pub type Maintain = wgt::Maintain<SubmissionIndex>;
1151#[cfg(any(
1152    not(target_arch = "wasm32"),
1153    all(
1154        feature = "fragile-send-sync-non-atomic-wasm",
1155        not(target_feature = "atomics")
1156    )
1157))]
1158static_assertions::assert_impl_all!(Maintain: Send, Sync);
1159
1160/// Describes a [`TextureView`].
1161///
1162/// For use with [`Texture::create_view`].
1163///
1164/// Corresponds to [WebGPU `GPUTextureViewDescriptor`](
1165/// https://gpuweb.github.io/gpuweb/#dictdef-gputextureviewdescriptor).
1166#[derive(Clone, Debug, Default, Eq, PartialEq)]
1167pub struct TextureViewDescriptor<'a> {
1168    /// Debug label of the texture view. This will show up in graphics debuggers for easy identification.
1169    pub label: Label<'a>,
1170    /// Format of the texture view. Either must be the same as the texture format or in the list
1171    /// of `view_formats` in the texture's descriptor.
1172    pub format: Option<TextureFormat>,
1173    /// The dimension of the texture view. For 1D textures, this must be `D1`. For 2D textures it must be one of
1174    /// `D2`, `D2Array`, `Cube`, and `CubeArray`. For 3D textures it must be `D3`
1175    pub dimension: Option<TextureViewDimension>,
1176    /// Aspect of the texture. Color textures must be [`TextureAspect::All`].
1177    pub aspect: TextureAspect,
1178    /// Base mip level.
1179    pub base_mip_level: u32,
1180    /// Mip level count.
1181    /// If `Some(count)`, `base_mip_level + count` must be less or equal to underlying texture mip count.
1182    /// If `None`, considered to include the rest of the mipmap levels, but at least 1 in total.
1183    pub mip_level_count: Option<u32>,
1184    /// Base array layer.
1185    pub base_array_layer: u32,
1186    /// Layer count.
1187    /// If `Some(count)`, `base_array_layer + count` must be less or equal to the underlying array count.
1188    /// If `None`, considered to include the rest of the array layers, but at least 1 in total.
1189    pub array_layer_count: Option<u32>,
1190}
1191static_assertions::assert_impl_all!(TextureViewDescriptor: Send, Sync);
1192
1193/// Describes a [`PipelineLayout`].
1194///
1195/// For use with [`Device::create_pipeline_layout`].
1196///
1197/// Corresponds to [WebGPU `GPUPipelineLayoutDescriptor`](
1198/// https://gpuweb.github.io/gpuweb/#dictdef-gpupipelinelayoutdescriptor).
1199#[derive(Clone, Debug, Default)]
1200pub struct PipelineLayoutDescriptor<'a> {
1201    /// Debug label of the pipeline layout. This will show up in graphics debuggers for easy identification.
1202    pub label: Label<'a>,
1203    /// Bind groups that this pipeline uses. The first entry will provide all the bindings for
1204    /// "set = 0", second entry will provide all the bindings for "set = 1" etc.
1205    pub bind_group_layouts: &'a [&'a BindGroupLayout],
1206    /// Set of push constant ranges this pipeline uses. Each shader stage that uses push constants
1207    /// must define the range in push constant memory that corresponds to its single `layout(push_constant)`
1208    /// uniform block.
1209    ///
1210    /// If this array is non-empty, the [`Features::PUSH_CONSTANTS`] must be enabled.
1211    pub push_constant_ranges: &'a [PushConstantRange],
1212}
1213#[cfg(any(
1214    not(target_arch = "wasm32"),
1215    all(
1216        feature = "fragile-send-sync-non-atomic-wasm",
1217        not(target_feature = "atomics")
1218    )
1219))]
1220static_assertions::assert_impl_all!(PipelineLayoutDescriptor: Send, Sync);
1221
1222/// Describes a [`Sampler`].
1223///
1224/// For use with [`Device::create_sampler`].
1225///
1226/// Corresponds to [WebGPU `GPUSamplerDescriptor`](
1227/// https://gpuweb.github.io/gpuweb/#dictdef-gpusamplerdescriptor).
1228#[derive(Clone, Debug, PartialEq)]
1229pub struct SamplerDescriptor<'a> {
1230    /// Debug label of the sampler. This will show up in graphics debuggers for easy identification.
1231    pub label: Label<'a>,
1232    /// How to deal with out of bounds accesses in the u (i.e. x) direction
1233    pub address_mode_u: AddressMode,
1234    /// How to deal with out of bounds accesses in the v (i.e. y) direction
1235    pub address_mode_v: AddressMode,
1236    /// How to deal with out of bounds accesses in the w (i.e. z) direction
1237    pub address_mode_w: AddressMode,
1238    /// How to filter the texture when it needs to be magnified (made larger)
1239    pub mag_filter: FilterMode,
1240    /// How to filter the texture when it needs to be minified (made smaller)
1241    pub min_filter: FilterMode,
1242    /// How to filter between mip map levels
1243    pub mipmap_filter: FilterMode,
1244    /// Minimum level of detail (i.e. mip level) to use
1245    pub lod_min_clamp: f32,
1246    /// Maximum level of detail (i.e. mip level) to use
1247    pub lod_max_clamp: f32,
1248    /// If this is enabled, this is a comparison sampler using the given comparison function.
1249    pub compare: Option<CompareFunction>,
1250    /// Must be at least 1. If this is not 1, all filter modes must be linear.
1251    pub anisotropy_clamp: u16,
1252    /// Border color to use when address_mode is [`AddressMode::ClampToBorder`]
1253    pub border_color: Option<SamplerBorderColor>,
1254}
1255static_assertions::assert_impl_all!(SamplerDescriptor: Send, Sync);
1256
1257impl Default for SamplerDescriptor<'_> {
1258    fn default() -> Self {
1259        Self {
1260            label: None,
1261            address_mode_u: Default::default(),
1262            address_mode_v: Default::default(),
1263            address_mode_w: Default::default(),
1264            mag_filter: Default::default(),
1265            min_filter: Default::default(),
1266            mipmap_filter: Default::default(),
1267            lod_min_clamp: 0.0,
1268            lod_max_clamp: 32.0,
1269            compare: None,
1270            anisotropy_clamp: 1,
1271            border_color: None,
1272        }
1273    }
1274}
1275
1276/// An element of a [`BindGroupDescriptor`], consisting of a bindable resource
1277/// and the slot to bind it to.
1278///
1279/// Corresponds to [WebGPU `GPUBindGroupEntry`](
1280/// https://gpuweb.github.io/gpuweb/#dictdef-gpubindgroupentry).
1281#[derive(Clone, Debug)]
1282pub struct BindGroupEntry<'a> {
1283    /// Slot for which binding provides resource. Corresponds to an entry of the same
1284    /// binding index in the [`BindGroupLayoutDescriptor`].
1285    pub binding: u32,
1286    /// Resource to attach to the binding
1287    pub resource: BindingResource<'a>,
1288}
1289#[cfg(any(
1290    not(target_arch = "wasm32"),
1291    all(
1292        feature = "fragile-send-sync-non-atomic-wasm",
1293        not(target_feature = "atomics")
1294    )
1295))]
1296static_assertions::assert_impl_all!(BindGroupEntry: Send, Sync);
1297
1298/// Describes a group of bindings and the resources to be bound.
1299///
1300/// For use with [`Device::create_bind_group`].
1301///
1302/// Corresponds to [WebGPU `GPUBindGroupDescriptor`](
1303/// https://gpuweb.github.io/gpuweb/#dictdef-gpubindgroupdescriptor).
1304#[derive(Clone, Debug)]
1305pub struct BindGroupDescriptor<'a> {
1306    /// Debug label of the bind group. This will show up in graphics debuggers for easy identification.
1307    pub label: Label<'a>,
1308    /// The [`BindGroupLayout`] that corresponds to this bind group.
1309    pub layout: &'a BindGroupLayout,
1310    /// The resources to bind to this bind group.
1311    pub entries: &'a [BindGroupEntry<'a>],
1312}
1313#[cfg(any(
1314    not(target_arch = "wasm32"),
1315    all(
1316        feature = "fragile-send-sync-non-atomic-wasm",
1317        not(target_feature = "atomics")
1318    )
1319))]
1320static_assertions::assert_impl_all!(BindGroupDescriptor: Send, Sync);
1321
1322/// Describes the attachments of a render pass.
1323///
1324/// For use with [`CommandEncoder::begin_render_pass`].
1325///
1326/// Note: separate lifetimes are needed because the texture views (`'tex`)
1327/// have to live as long as the pass is recorded, while everything else (`'desc`) doesn't.
1328///
1329/// Corresponds to [WebGPU `GPURenderPassDescriptor`](
1330/// https://gpuweb.github.io/gpuweb/#dictdef-gpurenderpassdescriptor).
1331#[derive(Clone, Debug, Default)]
1332pub struct RenderPassDescriptor<'tex, 'desc> {
1333    /// Debug label of the render pass. This will show up in graphics debuggers for easy identification.
1334    pub label: Label<'desc>,
1335    /// The color attachments of the render pass.
1336    pub color_attachments: &'desc [Option<RenderPassColorAttachment<'tex>>],
1337    /// The depth and stencil attachment of the render pass, if any.
1338    pub depth_stencil_attachment: Option<RenderPassDepthStencilAttachment<'tex>>,
1339}
1340#[cfg(any(
1341    not(target_arch = "wasm32"),
1342    all(
1343        feature = "fragile-send-sync-non-atomic-wasm",
1344        not(target_feature = "atomics")
1345    )
1346))]
1347static_assertions::assert_impl_all!(RenderPassDescriptor: Send, Sync);
1348
1349/// Describes how the vertex buffer is interpreted.
1350///
1351/// For use in [`VertexState`].
1352///
1353/// Corresponds to [WebGPU `GPUVertexBufferLayout`](
1354/// https://gpuweb.github.io/gpuweb/#dictdef-gpuvertexbufferlayout).
1355#[derive(Clone, Debug, Hash, Eq, PartialEq)]
1356pub struct VertexBufferLayout<'a> {
1357    /// The stride, in bytes, between elements of this buffer.
1358    pub array_stride: BufferAddress,
1359    /// How often this vertex buffer is "stepped" forward.
1360    pub step_mode: VertexStepMode,
1361    /// The list of attributes which comprise a single vertex.
1362    pub attributes: &'a [VertexAttribute],
1363}
1364static_assertions::assert_impl_all!(VertexBufferLayout: Send, Sync);
1365
1366/// Describes the vertex processing in a render pipeline.
1367///
1368/// For use in [`RenderPipelineDescriptor`].
1369///
1370/// Corresponds to [WebGPU `GPUVertexState`](
1371/// https://gpuweb.github.io/gpuweb/#dictdef-gpuvertexstate).
1372#[derive(Clone, Debug)]
1373pub struct VertexState<'a> {
1374    /// The compiled shader module for this stage.
1375    pub module: &'a ShaderModule,
1376    /// The name of the entry point in the compiled shader. There must be a function with this name
1377    /// in the shader.
1378    pub entry_point: &'a str,
1379    /// The format of any vertex buffers used with this pipeline.
1380    pub buffers: &'a [VertexBufferLayout<'a>],
1381}
1382#[cfg(any(
1383    not(target_arch = "wasm32"),
1384    all(
1385        feature = "fragile-send-sync-non-atomic-wasm",
1386        not(target_feature = "atomics")
1387    )
1388))]
1389static_assertions::assert_impl_all!(VertexState: Send, Sync);
1390
1391/// Describes the fragment processing in a render pipeline.
1392///
1393/// For use in [`RenderPipelineDescriptor`].
1394///
1395/// Corresponds to [WebGPU `GPUFragmentState`](
1396/// https://gpuweb.github.io/gpuweb/#dictdef-gpufragmentstate).
1397#[derive(Clone, Debug)]
1398pub struct FragmentState<'a> {
1399    /// The compiled shader module for this stage.
1400    pub module: &'a ShaderModule,
1401    /// The name of the entry point in the compiled shader. There must be a function with this name
1402    /// in the shader.
1403    pub entry_point: &'a str,
1404    /// The color state of the render targets.
1405    pub targets: &'a [Option<ColorTargetState>],
1406}
1407#[cfg(any(
1408    not(target_arch = "wasm32"),
1409    all(
1410        feature = "fragile-send-sync-non-atomic-wasm",
1411        not(target_feature = "atomics")
1412    )
1413))]
1414static_assertions::assert_impl_all!(FragmentState: Send, Sync);
1415
1416/// Describes a render (graphics) pipeline.
1417///
1418/// For use with [`Device::create_render_pipeline`].
1419///
1420/// Corresponds to [WebGPU `GPURenderPipelineDescriptor`](
1421/// https://gpuweb.github.io/gpuweb/#dictdef-gpurenderpipelinedescriptor).
1422#[derive(Clone, Debug)]
1423pub struct RenderPipelineDescriptor<'a> {
1424    /// Debug label of the pipeline. This will show up in graphics debuggers for easy identification.
1425    pub label: Label<'a>,
1426    /// The layout of bind groups for this pipeline.
1427    pub layout: Option<&'a PipelineLayout>,
1428    /// The compiled vertex stage, its entry point, and the input buffers layout.
1429    pub vertex: VertexState<'a>,
1430    /// The properties of the pipeline at the primitive assembly and rasterization level.
1431    pub primitive: PrimitiveState,
1432    /// The effect of draw calls on the depth and stencil aspects of the output target, if any.
1433    pub depth_stencil: Option<DepthStencilState>,
1434    /// The multi-sampling properties of the pipeline.
1435    pub multisample: MultisampleState,
1436    /// The compiled fragment stage, its entry point, and the color targets.
1437    pub fragment: Option<FragmentState<'a>>,
1438    /// If the pipeline will be used with a multiview render pass, this indicates how many array
1439    /// layers the attachments will have.
1440    pub multiview: Option<NonZeroU32>,
1441}
1442#[cfg(any(
1443    not(target_arch = "wasm32"),
1444    all(
1445        feature = "fragile-send-sync-non-atomic-wasm",
1446        not(target_feature = "atomics")
1447    )
1448))]
1449static_assertions::assert_impl_all!(RenderPipelineDescriptor: Send, Sync);
1450
1451/// Describes the attachments of a compute pass.
1452///
1453/// For use with [`CommandEncoder::begin_compute_pass`].
1454///
1455/// Corresponds to [WebGPU `GPUComputePassDescriptor`](
1456/// https://gpuweb.github.io/gpuweb/#dictdef-gpucomputepassdescriptor).
1457#[derive(Clone, Debug, Default)]
1458pub struct ComputePassDescriptor<'a> {
1459    /// Debug label of the compute pass. This will show up in graphics debuggers for easy identification.
1460    pub label: Label<'a>,
1461}
1462static_assertions::assert_impl_all!(ComputePassDescriptor: Send, Sync);
1463
1464/// Describes a compute pipeline.
1465///
1466/// For use with [`Device::create_compute_pipeline`].
1467///
1468/// Corresponds to [WebGPU `GPUComputePipelineDescriptor`](
1469/// https://gpuweb.github.io/gpuweb/#dictdef-gpucomputepipelinedescriptor).
1470#[derive(Clone, Debug)]
1471pub struct ComputePipelineDescriptor<'a> {
1472    /// Debug label of the pipeline. This will show up in graphics debuggers for easy identification.
1473    pub label: Label<'a>,
1474    /// The layout of bind groups for this pipeline.
1475    pub layout: Option<&'a PipelineLayout>,
1476    /// The compiled shader module for this stage.
1477    pub module: &'a ShaderModule,
1478    /// The name of the entry point in the compiled shader. There must be a function with this name
1479    /// and no return value in the shader.
1480    pub entry_point: &'a str,
1481}
1482#[cfg(any(
1483    not(target_arch = "wasm32"),
1484    all(
1485        feature = "fragile-send-sync-non-atomic-wasm",
1486        not(target_feature = "atomics")
1487    )
1488))]
1489static_assertions::assert_impl_all!(ComputePipelineDescriptor: Send, Sync);
1490
1491pub use wgt::ImageCopyBuffer as ImageCopyBufferBase;
1492/// View of a buffer which can be used to copy to/from a texture.
1493///
1494/// Corresponds to [WebGPU `GPUImageCopyBuffer`](
1495/// https://gpuweb.github.io/gpuweb/#dictdef-gpuimagecopybuffer).
1496pub type ImageCopyBuffer<'a> = ImageCopyBufferBase<&'a Buffer>;
1497#[cfg(any(
1498    not(target_arch = "wasm32"),
1499    all(
1500        feature = "fragile-send-sync-non-atomic-wasm",
1501        not(target_feature = "atomics")
1502    )
1503))]
1504static_assertions::assert_impl_all!(ImageCopyBuffer: Send, Sync);
1505
1506pub use wgt::ImageCopyTexture as ImageCopyTextureBase;
1507/// View of a texture which can be used to copy to/from a buffer/texture.
1508///
1509/// Corresponds to [WebGPU `GPUImageCopyTexture`](
1510/// https://gpuweb.github.io/gpuweb/#dictdef-gpuimagecopytexture).
1511pub type ImageCopyTexture<'a> = ImageCopyTextureBase<&'a Texture>;
1512#[cfg(any(
1513    not(target_arch = "wasm32"),
1514    all(
1515        feature = "fragile-send-sync-non-atomic-wasm",
1516        not(target_feature = "atomics")
1517    )
1518))]
1519static_assertions::assert_impl_all!(ImageCopyTexture: Send, Sync);
1520
1521pub use wgt::ImageCopyTextureTagged as ImageCopyTextureTaggedBase;
1522/// View of a texture which can be used to copy to a texture, including
1523/// color space and alpha premultiplication information.
1524///
1525/// Corresponds to [WebGPU `GPUImageCopyTextureTagged`](
1526/// https://gpuweb.github.io/gpuweb/#dictdef-gpuimagecopytexturetagged).
1527pub type ImageCopyTextureTagged<'a> = ImageCopyTextureTaggedBase<&'a Texture>;
1528#[cfg(any(
1529    not(target_arch = "wasm32"),
1530    all(
1531        feature = "fragile-send-sync-non-atomic-wasm",
1532        not(target_feature = "atomics")
1533    )
1534))]
1535static_assertions::assert_impl_all!(ImageCopyTexture: Send, Sync);
1536
1537/// Describes a [`BindGroupLayout`].
1538///
1539/// For use with [`Device::create_bind_group_layout`].
1540///
1541/// Corresponds to [WebGPU `GPUBindGroupLayoutDescriptor`](
1542/// https://gpuweb.github.io/gpuweb/#dictdef-gpubindgrouplayoutdescriptor).
1543#[derive(Clone, Debug)]
1544pub struct BindGroupLayoutDescriptor<'a> {
1545    /// Debug label of the bind group layout. This will show up in graphics debuggers for easy identification.
1546    pub label: Label<'a>,
1547
1548    /// Array of entries in this BindGroupLayout
1549    pub entries: &'a [BindGroupLayoutEntry],
1550}
1551static_assertions::assert_impl_all!(BindGroupLayoutDescriptor: Send, Sync);
1552
1553/// Describes a [`RenderBundleEncoder`].
1554///
1555/// For use with [`Device::create_render_bundle_encoder`].
1556///
1557/// Corresponds to [WebGPU `GPURenderBundleEncoderDescriptor`](
1558/// https://gpuweb.github.io/gpuweb/#dictdef-gpurenderbundleencoderdescriptor).
1559#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
1560pub struct RenderBundleEncoderDescriptor<'a> {
1561    /// Debug label of the render bundle encoder. This will show up in graphics debuggers for easy identification.
1562    pub label: Label<'a>,
1563    /// The formats of the color attachments that this render bundle is capable to rendering to. This
1564    /// must match the formats of the color attachments in the render pass this render bundle is executed in.
1565    pub color_formats: &'a [Option<TextureFormat>],
1566    /// Information about the depth attachment that this render bundle is capable to rendering to. This
1567    /// must match the format of the depth attachments in the render pass this render bundle is executed in.
1568    pub depth_stencil: Option<RenderBundleDepthStencil>,
1569    /// Sample count this render bundle is capable of rendering to. This must match the pipelines and
1570    /// the render passes it is used in.
1571    pub sample_count: u32,
1572    /// If this render bundle will rendering to multiple array layers in the attachments at the same time.
1573    pub multiview: Option<NonZeroU32>,
1574}
1575static_assertions::assert_impl_all!(RenderBundleEncoderDescriptor: Send, Sync);
1576
1577/// Surface texture that can be rendered to.
1578/// Result of a successful call to [`Surface::get_current_texture`].
1579///
1580/// This type is unique to the Rust API of `wgpu`. In the WebGPU specification,
1581/// the [`GPUCanvasContext`](https://gpuweb.github.io/gpuweb/#canvas-context) provides
1582/// a texture without any additional information.
1583#[derive(Debug)]
1584pub struct SurfaceTexture {
1585    /// Accessible view of the frame.
1586    pub texture: Texture,
1587    /// `true` if the acquired buffer can still be used for rendering,
1588    /// but should be recreated for maximum performance.
1589    pub suboptimal: bool,
1590    presented: bool,
1591    detail: Box<dyn AnyWasmNotSendSync>,
1592}
1593#[cfg(any(
1594    not(target_arch = "wasm32"),
1595    all(
1596        feature = "fragile-send-sync-non-atomic-wasm",
1597        not(target_feature = "atomics")
1598    )
1599))]
1600static_assertions::assert_impl_all!(SurfaceTexture: Send, Sync);
1601
1602/// Result of an unsuccessful call to [`Surface::get_current_texture`].
1603#[derive(Clone, PartialEq, Eq, Debug)]
1604pub enum SurfaceError {
1605    /// A timeout was encountered while trying to acquire the next frame.
1606    Timeout,
1607    /// The underlying surface has changed, and therefore the swap chain must be updated.
1608    Outdated,
1609    /// The swap chain has been lost and needs to be recreated.
1610    Lost,
1611    /// There is no more memory left to allocate a new frame.
1612    OutOfMemory,
1613}
1614static_assertions::assert_impl_all!(SurfaceError: Send, Sync);
1615
1616impl Display for SurfaceError {
1617    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1618        write!(f, "{}", match self {
1619            Self::Timeout => "A timeout was encountered while trying to acquire the next frame",
1620            Self::Outdated => "The underlying surface has changed, and therefore the swap chain must be updated",
1621            Self::Lost =>  "The swap chain has been lost and needs to be recreated",
1622            Self::OutOfMemory => "There is no more memory left to allocate a new frame",
1623        })
1624    }
1625}
1626
1627impl error::Error for SurfaceError {}
1628
1629impl Default for Instance {
1630    /// Creates a new instance of wgpu with default options.
1631    ///
1632    /// Backends are set to `Backends::all()`, and FXC is chosen as the `dx12_shader_compiler`.
1633    fn default() -> Self {
1634        Self::new(InstanceDescriptor::default())
1635    }
1636}
1637
1638impl Instance {
1639    /// Create an new instance of wgpu.
1640    ///
1641    /// # Arguments
1642    ///
1643    /// - `instance_desc` - Has fields for which [backends][Backends] wgpu will choose
1644    ///   during instantiation, and which [DX12 shader compiler][Dx12Compiler] wgpu will use.
1645    pub fn new(instance_desc: InstanceDescriptor) -> Self {
1646        Self {
1647            context: Arc::from(crate::backend::Context::init(instance_desc)),
1648        }
1649    }
1650
1651    /// Create an new instance of wgpu from a wgpu-hal instance.
1652    ///
1653    /// # Arguments
1654    ///
1655    /// - `hal_instance` - wgpu-hal instance.
1656    ///
1657    /// # Safety
1658    ///
1659    /// Refer to the creation of wgpu-hal Instance for every backend.
1660    #[cfg(any(
1661        not(target_arch = "wasm32"),
1662        target_os = "emscripten",
1663        feature = "webgl"
1664    ))]
1665    pub unsafe fn from_hal<A: wgc::hal_api::HalApi>(hal_instance: A::Instance) -> Self {
1666        Self {
1667            context: Arc::new(unsafe {
1668                crate::backend::Context::from_hal_instance::<A>(hal_instance)
1669            }),
1670        }
1671    }
1672
1673    /// Return a reference to a specific backend instance, if available.
1674    ///
1675    /// If this `Instance` has a wgpu-hal [`Instance`] for backend
1676    /// `A`, return a reference to it. Otherwise, return `None`.
1677    ///
1678    /// # Safety
1679    ///
1680    /// - The raw instance handle returned must not be manually destroyed.
1681    ///
1682    /// [`Instance`]: hal::Api::Instance
1683    #[cfg(any(
1684        not(target_arch = "wasm32"),
1685        target_os = "emscripten",
1686        feature = "webgl"
1687    ))]
1688    pub unsafe fn as_hal<A: wgc::hal_api::HalApi>(&self) -> Option<&A::Instance> {
1689        unsafe {
1690            self.context
1691                .as_any()
1692                .downcast_ref::<crate::backend::Context>()
1693                .unwrap()
1694                .instance_as_hal::<A>()
1695        }
1696    }
1697
1698    /// Create an new instance of wgpu from a wgpu-core instance.
1699    ///
1700    /// # Arguments
1701    ///
1702    /// - `core_instance` - wgpu-core instance.
1703    ///
1704    /// # Safety
1705    ///
1706    /// Refer to the creation of wgpu-core Instance.
1707    #[cfg(any(
1708        not(target_arch = "wasm32"),
1709        target_os = "emscripten",
1710        feature = "webgl"
1711    ))]
1712    pub unsafe fn from_core(core_instance: wgc::instance::Instance) -> Self {
1713        Self {
1714            context: Arc::new(unsafe {
1715                crate::backend::Context::from_core_instance(core_instance)
1716            }),
1717        }
1718    }
1719
1720    /// Retrieves all available [`Adapter`]s that match the given [`Backends`].
1721    ///
1722    /// # Arguments
1723    ///
1724    /// - `backends` - Backends from which to enumerate adapters.
1725    #[cfg(any(
1726        not(target_arch = "wasm32"),
1727        target_os = "emscripten",
1728        feature = "webgl"
1729    ))]
1730    pub fn enumerate_adapters(&self, backends: Backends) -> impl ExactSizeIterator<Item = Adapter> {
1731        let context = Arc::clone(&self.context);
1732        self.context
1733            .as_any()
1734            .downcast_ref::<crate::backend::Context>()
1735            .unwrap()
1736            .enumerate_adapters(backends)
1737            .into_iter()
1738            .map(move |id| crate::Adapter {
1739                context: Arc::clone(&context),
1740                id: ObjectId::from(id),
1741                data: Box::new(()),
1742            })
1743    }
1744
1745    /// Retrieves an [`Adapter`] which matches the given [`RequestAdapterOptions`].
1746    ///
1747    /// Some options are "soft", so treated as non-mandatory. Others are "hard".
1748    ///
1749    /// If no adapters are found that suffice all the "hard" options, `None` is returned.
1750    pub fn request_adapter(
1751        &self,
1752        options: &RequestAdapterOptions,
1753    ) -> impl Future<Output = Option<Adapter>> + WasmNotSend {
1754        let context = Arc::clone(&self.context);
1755        let adapter = self.context.instance_request_adapter(options);
1756        async move {
1757            adapter
1758                .await
1759                .map(|(id, data)| Adapter { context, id, data })
1760        }
1761    }
1762
1763    /// Converts a wgpu-hal `ExposedAdapter` to a wgpu [`Adapter`].
1764    ///
1765    /// # Safety
1766    ///
1767    /// `hal_adapter` must be created from this instance internal handle.
1768    #[cfg(any(
1769        not(target_arch = "wasm32"),
1770        target_os = "emscripten",
1771        feature = "webgl"
1772    ))]
1773    pub unsafe fn create_adapter_from_hal<A: wgc::hal_api::HalApi>(
1774        &self,
1775        hal_adapter: hal::ExposedAdapter<A>,
1776    ) -> Adapter {
1777        let context = Arc::clone(&self.context);
1778        let id = unsafe {
1779            context
1780                .as_any()
1781                .downcast_ref::<crate::backend::Context>()
1782                .unwrap()
1783                .create_adapter_from_hal(hal_adapter)
1784                .into()
1785        };
1786        Adapter {
1787            context,
1788            id,
1789            data: Box::new(()),
1790        }
1791    }
1792
1793    /// Creates a surface from a raw window handle.
1794    ///
1795    /// If the specified display and window handle are not supported by any of the backends, then the surface
1796    /// will not be supported by any adapters.
1797    ///
1798    /// # Safety
1799    ///
1800    /// - `raw_window_handle` must be a valid object to create a surface upon.
1801    /// - `raw_window_handle` must remain valid until after the returned [`Surface`] is
1802    ///   dropped.
1803    ///
1804    /// # Errors
1805    ///
1806    /// - On WebGL2: Will return an error if the browser does not support WebGL2,
1807    ///   or declines to provide GPU access (such as due to a resource shortage).
1808    ///
1809    /// # Panics
1810    ///
1811    /// - On macOS/Metal: will panic if not called on the main thread.
1812    /// - On web: will panic if the `raw_window_handle` does not properly refer to a
1813    ///   canvas element.
1814    pub unsafe fn create_surface<
1815        W: raw_window_handle::HasRawWindowHandle + raw_window_handle::HasRawDisplayHandle,
1816    >(
1817        &self,
1818        window: &W,
1819    ) -> Result<Surface, CreateSurfaceError> {
1820        let (id, data) = DynContext::instance_create_surface(
1821            &*self.context,
1822            raw_window_handle::HasRawDisplayHandle::raw_display_handle(window),
1823            raw_window_handle::HasRawWindowHandle::raw_window_handle(window),
1824        )?;
1825        Ok(Surface {
1826            context: Arc::clone(&self.context),
1827            id,
1828            data,
1829            config: Mutex::new(None),
1830        })
1831    }
1832
1833    /// Creates a surface from `CoreAnimationLayer`.
1834    ///
1835    /// # Safety
1836    ///
1837    /// - layer must be a valid object to create a surface upon.
1838    #[cfg(any(target_os = "ios", target_os = "macos"))]
1839    pub unsafe fn create_surface_from_core_animation_layer(
1840        &self,
1841        layer: *mut std::ffi::c_void,
1842    ) -> Surface {
1843        let surface = unsafe {
1844            self.context
1845                .as_any()
1846                .downcast_ref::<crate::backend::Context>()
1847                .unwrap()
1848                .create_surface_from_core_animation_layer(layer)
1849        };
1850        Surface {
1851            context: Arc::clone(&self.context),
1852            id: ObjectId::from(surface.id()),
1853            data: Box::new(surface),
1854            config: Mutex::new(None),
1855        }
1856    }
1857
1858    /// Creates a surface from `IDCompositionVisual`.
1859    ///
1860    /// # Safety
1861    ///
1862    /// - visual must be a valid IDCompositionVisual to create a surface upon.
1863    #[cfg(target_os = "windows")]
1864    pub unsafe fn create_surface_from_visual(&self, visual: *mut std::ffi::c_void) -> Surface {
1865        let surface = unsafe {
1866            self.context
1867                .as_any()
1868                .downcast_ref::<crate::backend::Context>()
1869                .unwrap()
1870                .create_surface_from_visual(visual)
1871        };
1872        Surface {
1873            context: Arc::clone(&self.context),
1874            id: ObjectId::from(surface.id()),
1875            data: Box::new(surface),
1876            config: Mutex::new(None),
1877        }
1878    }
1879
1880    /// Creates a surface from `SurfaceHandle`.
1881    ///
1882    /// # Safety
1883    ///
1884    /// - surface_handle must be a valid SurfaceHandle to create a surface upon.
1885    #[cfg(target_os = "windows")]
1886    pub unsafe fn create_surface_from_surface_handle(
1887        &self,
1888        surface_handle: *mut std::ffi::c_void,
1889    ) -> Surface {
1890        let surface = unsafe {
1891            self.context
1892                .as_any()
1893                .downcast_ref::<crate::backend::Context>()
1894                .unwrap()
1895                .create_surface_from_surface_handle(surface_handle)
1896        };
1897        Surface {
1898            context: Arc::clone(&self.context),
1899            id: ObjectId::from(surface.id()),
1900            data: Box::new(surface),
1901            config: Mutex::new(None),
1902        }
1903    }
1904
1905    /// Creates a surface from a `web_sys::HtmlCanvasElement`.
1906    ///
1907    /// The `canvas` argument must be a valid `<canvas>` element to
1908    /// create a surface upon.
1909    ///
1910    /// # Errors
1911    ///
1912    /// - On WebGL2: Will return an error if the browser does not support WebGL2,
1913    ///   or declines to provide GPU access (such as due to a resource shortage).
1914    #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
1915    pub fn create_surface_from_canvas(
1916        &self,
1917        canvas: web_sys::HtmlCanvasElement,
1918    ) -> Result<Surface, CreateSurfaceError> {
1919        let surface = self
1920            .context
1921            .as_any()
1922            .downcast_ref::<crate::backend::Context>()
1923            .unwrap()
1924            .instance_create_surface_from_canvas(canvas)?;
1925
1926        // TODO: This is ugly, a way to create things from a native context needs to be made nicer.
1927        Ok(Surface {
1928            context: Arc::clone(&self.context),
1929            #[cfg(any(not(target_arch = "wasm32"), feature = "webgl"))]
1930            id: ObjectId::from(surface.id()),
1931            #[cfg(any(not(target_arch = "wasm32"), feature = "webgl"))]
1932            data: Box::new(surface),
1933            #[cfg(all(target_arch = "wasm32", not(feature = "webgl")))]
1934            id: ObjectId::UNUSED,
1935            #[cfg(all(target_arch = "wasm32", not(feature = "webgl")))]
1936            data: Box::new(surface.1),
1937            config: Mutex::new(None),
1938        })
1939    }
1940
1941    /// Creates a surface from a `web_sys::OffscreenCanvas`.
1942    ///
1943    /// The `canvas` argument must be a valid `OffscreenCanvas` object
1944    /// to create a surface upon.
1945    ///
1946    /// # Errors
1947    ///
1948    /// - On WebGL2: Will return an error if the browser does not support WebGL2,
1949    ///   or declines to provide GPU access (such as due to a resource shortage).
1950    #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
1951    pub fn create_surface_from_offscreen_canvas(
1952        &self,
1953        canvas: web_sys::OffscreenCanvas,
1954    ) -> Result<Surface, CreateSurfaceError> {
1955        let surface = self
1956            .context
1957            .as_any()
1958            .downcast_ref::<crate::backend::Context>()
1959            .unwrap()
1960            .instance_create_surface_from_offscreen_canvas(canvas)?;
1961
1962        // TODO: This is ugly, a way to create things from a native context needs to be made nicer.
1963        Ok(Surface {
1964            context: Arc::clone(&self.context),
1965            #[cfg(any(not(target_arch = "wasm32"), feature = "webgl"))]
1966            id: ObjectId::from(surface.id()),
1967            #[cfg(any(not(target_arch = "wasm32"), feature = "webgl"))]
1968            data: Box::new(surface),
1969            #[cfg(all(target_arch = "wasm32", not(feature = "webgl")))]
1970            id: ObjectId::UNUSED,
1971            #[cfg(all(target_arch = "wasm32", not(feature = "webgl")))]
1972            data: Box::new(surface.1),
1973            config: Mutex::new(None),
1974        })
1975    }
1976
1977    /// Polls all devices.
1978    ///
1979    /// If `force_wait` is true and this is not running on the web, then this
1980    /// function will block until all in-flight buffers have been mapped and
1981    /// all submitted commands have finished execution.
1982    ///
1983    /// Return `true` if all devices' queues are empty, or `false` if there are
1984    /// queue submissions still in flight. (Note that, unless access to all
1985    /// [`Queue`s] associated with this [`Instance`] is coordinated somehow,
1986    /// this information could be out of date by the time the caller receives
1987    /// it. `Queue`s can be shared between threads, and other threads could
1988    /// submit new work at any time.)
1989    ///
1990    /// On the web, this is a no-op. `Device`s are automatically polled.
1991    ///
1992    /// [`Queue`s]: Queue
1993    pub fn poll_all(&self, force_wait: bool) -> bool {
1994        self.context.instance_poll_all_devices(force_wait)
1995    }
1996
1997    /// Generates memory report.
1998    #[cfg(any(
1999        not(target_arch = "wasm32"),
2000        target_os = "emscripten",
2001        feature = "webgl"
2002    ))]
2003    pub fn generate_report(&self) -> wgc::global::GlobalReport {
2004        self.context
2005            .as_any()
2006            .downcast_ref::<crate::backend::Context>()
2007            .unwrap()
2008            .generate_report()
2009    }
2010}
2011
2012impl Adapter {
2013    /// Requests a connection to a physical device, creating a logical device.
2014    ///
2015    /// Returns the [`Device`] together with a [`Queue`] that executes command buffers.
2016    ///
2017    /// # Arguments
2018    ///
2019    /// - `desc` - Description of the features and limits requested from the given device.
2020    /// - `trace_path` - Can be used for API call tracing, if that feature is
2021    ///   enabled in `wgpu-core`.
2022    ///
2023    /// # Panics
2024    ///
2025    /// - Features specified by `desc` are not supported by this adapter.
2026    /// - Unsafe features were requested but not enabled when requesting the adapter.
2027    /// - Limits requested exceed the values provided by the adapter.
2028    /// - Adapter does not support all features wgpu requires to safely operate.
2029    pub fn request_device(
2030        &self,
2031        desc: &DeviceDescriptor,
2032        trace_path: Option<&std::path::Path>,
2033    ) -> impl Future<Output = Result<(Device, Queue), RequestDeviceError>> + WasmNotSend {
2034        let context = Arc::clone(&self.context);
2035        let device = DynContext::adapter_request_device(
2036            &*self.context,
2037            &self.id,
2038            self.data.as_ref(),
2039            desc,
2040            trace_path,
2041        );
2042        async move {
2043            device.await.map(
2044                |DeviceRequest {
2045                     device_id,
2046                     device_data,
2047                     queue_id,
2048                     queue_data,
2049                 }| {
2050                    (
2051                        Device {
2052                            context: Arc::clone(&context),
2053                            id: device_id,
2054                            data: device_data,
2055                        },
2056                        Queue {
2057                            context,
2058                            id: queue_id,
2059                            data: queue_data,
2060                        },
2061                    )
2062                },
2063            )
2064        }
2065    }
2066
2067    /// Create a wgpu [`Device`] and [`Queue`] from a wgpu-hal `OpenDevice`
2068    ///
2069    /// # Safety
2070    ///
2071    /// - `hal_device` must be created from this adapter internal handle.
2072    /// - `desc.features` must be a subset of `hal_device` features.
2073    #[cfg(any(
2074        not(target_arch = "wasm32"),
2075        target_os = "emscripten",
2076        feature = "webgl"
2077    ))]
2078    pub unsafe fn create_device_from_hal<A: wgc::hal_api::HalApi>(
2079        &self,
2080        hal_device: hal::OpenDevice<A>,
2081        desc: &DeviceDescriptor,
2082        trace_path: Option<&std::path::Path>,
2083    ) -> Result<(Device, Queue), RequestDeviceError> {
2084        let context = Arc::clone(&self.context);
2085        unsafe {
2086            self.context
2087                .as_any()
2088                .downcast_ref::<crate::backend::Context>()
2089                .unwrap()
2090                .create_device_from_hal(&self.id.into(), hal_device, desc, trace_path)
2091        }
2092        .map(|(device, queue)| {
2093            (
2094                Device {
2095                    context: Arc::clone(&context),
2096                    id: device.id().into(),
2097                    data: Box::new(device),
2098                },
2099                Queue {
2100                    context,
2101                    id: queue.id().into(),
2102                    data: Box::new(queue),
2103                },
2104            )
2105        })
2106    }
2107
2108    /// Apply a callback to this `Adapter`'s underlying backend adapter.
2109    ///
2110    /// If this `Adapter` is implemented by the backend API given by `A` (Vulkan,
2111    /// Dx12, etc.), then apply `hal_adapter_callback` to `Some(&adapter)`, where
2112    /// `adapter` is the underlying backend adapter type, [`A::Adapter`].
2113    ///
2114    /// If this `Adapter` uses a different backend, apply `hal_adapter_callback`
2115    /// to `None`.
2116    ///
2117    /// The adapter is locked for reading while `hal_adapter_callback` runs. If
2118    /// the callback attempts to perform any `wgpu` operations that require
2119    /// write access to the adapter, deadlock will occur. The locks are
2120    /// automatically released when the callback returns.
2121    ///
2122    /// # Safety
2123    ///
2124    /// - The raw handle passed to the callback must not be manually destroyed.
2125    ///
2126    /// [`A::Adapter`]: hal::Api::Adapter
2127    #[cfg(any(
2128        not(target_arch = "wasm32"),
2129        target_os = "emscripten",
2130        feature = "webgl"
2131    ))]
2132    pub unsafe fn as_hal<A: wgc::hal_api::HalApi, F: FnOnce(Option<&A::Adapter>) -> R, R>(
2133        &self,
2134        hal_adapter_callback: F,
2135    ) -> R {
2136        unsafe {
2137            self.context
2138                .as_any()
2139                .downcast_ref::<crate::backend::Context>()
2140                .unwrap()
2141                .adapter_as_hal::<A, F, R>(self.id.into(), hal_adapter_callback)
2142        }
2143    }
2144
2145    /// Returns whether this adapter may present to the passed surface.
2146    pub fn is_surface_supported(&self, surface: &Surface) -> bool {
2147        DynContext::adapter_is_surface_supported(
2148            &*self.context,
2149            &self.id,
2150            self.data.as_ref(),
2151            &surface.id,
2152            surface.data.as_ref(),
2153        )
2154    }
2155
2156    /// List all features that are supported with this adapter.
2157    ///
2158    /// Features must be explicitly requested in [`Adapter::request_device`] in order
2159    /// to use them.
2160    pub fn features(&self) -> Features {
2161        DynContext::adapter_features(&*self.context, &self.id, self.data.as_ref())
2162    }
2163
2164    /// List the "best" limits that are supported by this adapter.
2165    ///
2166    /// Limits must be explicitly requested in [`Adapter::request_device`] to set
2167    /// the values that you are allowed to use.
2168    pub fn limits(&self) -> Limits {
2169        DynContext::adapter_limits(&*self.context, &self.id, self.data.as_ref())
2170    }
2171
2172    /// Get info about the adapter itself.
2173    pub fn get_info(&self) -> AdapterInfo {
2174        DynContext::adapter_get_info(&*self.context, &self.id, self.data.as_ref())
2175    }
2176
2177    /// Get info about the adapter itself.
2178    pub fn get_downlevel_capabilities(&self) -> DownlevelCapabilities {
2179        DynContext::adapter_downlevel_capabilities(&*self.context, &self.id, self.data.as_ref())
2180    }
2181
2182    /// Returns the features supported for a given texture format by this adapter.
2183    ///
2184    /// Note that the WebGPU spec further restricts the available usages/features.
2185    /// To disable these restrictions on a device, request the [`Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES`] feature.
2186    pub fn get_texture_format_features(&self, format: TextureFormat) -> TextureFormatFeatures {
2187        DynContext::adapter_get_texture_format_features(
2188            &*self.context,
2189            &self.id,
2190            self.data.as_ref(),
2191            format,
2192        )
2193    }
2194
2195    /// Generates a timestamp using the clock used by the presentation engine.
2196    ///
2197    /// When comparing completely opaque timestamp systems, we need a way of generating timestamps that signal
2198    /// the exact same time. You can do this by calling your own timestamp function immediately after a call to
2199    /// this function. This should result in timestamps that are 0.5 to 5 microseconds apart. There are locks
2200    /// that must be taken during the call, so don't call your function before.
2201    ///
2202    /// ```no_run
2203    /// # let adapter: wgpu::Adapter = panic!();
2204    /// # let some_code = || wgpu::PresentationTimestamp::INVALID_TIMESTAMP;
2205    /// use std::time::{Duration, Instant};
2206    /// let presentation = adapter.get_presentation_timestamp();
2207    /// let instant = Instant::now();
2208    ///
2209    /// // We can now turn a new presentation timestamp into an Instant.
2210    /// let some_pres_timestamp = some_code();
2211    /// let duration = Duration::from_nanos((some_pres_timestamp.0 - presentation.0) as u64);
2212    /// let new_instant: Instant = instant + duration;
2213    /// ```
2214    //
2215    /// [Instant]: std::time::Instant
2216    pub fn get_presentation_timestamp(&self) -> PresentationTimestamp {
2217        DynContext::adapter_get_presentation_timestamp(&*self.context, &self.id, self.data.as_ref())
2218    }
2219}
2220
2221impl Device {
2222    /// Check for resource cleanups and mapping callbacks.
2223    ///
2224    /// Return `true` if the queue is empty, or `false` if there are more queue
2225    /// submissions still in flight. (Note that, unless access to the [`Queue`] is
2226    /// coordinated somehow, this information could be out of date by the time
2227    /// the caller receives it. `Queue`s can be shared between threads, so
2228    /// other threads could submit new work at any time.)
2229    ///
2230    /// On the web, this is a no-op. `Device`s are automatically polled.
2231    pub fn poll(&self, maintain: Maintain) -> bool {
2232        DynContext::device_poll(&*self.context, &self.id, self.data.as_ref(), maintain)
2233    }
2234
2235    /// List all features that may be used with this device.
2236    ///
2237    /// Functions may panic if you use unsupported features.
2238    pub fn features(&self) -> Features {
2239        DynContext::device_features(&*self.context, &self.id, self.data.as_ref())
2240    }
2241
2242    /// List all limits that were requested of this device.
2243    ///
2244    /// If any of these limits are exceeded, functions may panic.
2245    pub fn limits(&self) -> Limits {
2246        DynContext::device_limits(&*self.context, &self.id, self.data.as_ref())
2247    }
2248
2249    /// Creates a shader module from either SPIR-V or WGSL source code.
2250    pub fn create_shader_module(&self, desc: ShaderModuleDescriptor) -> ShaderModule {
2251        let (id, data) = DynContext::device_create_shader_module(
2252            &*self.context,
2253            &self.id,
2254            self.data.as_ref(),
2255            desc,
2256            wgt::ShaderBoundChecks::new(),
2257        );
2258        ShaderModule {
2259            context: Arc::clone(&self.context),
2260            id,
2261            data,
2262        }
2263    }
2264
2265    /// Creates a shader module from either SPIR-V or WGSL source code without runtime checks.
2266    ///
2267    /// # Safety
2268    /// In contrast with [`create_shader_module`](Self::create_shader_module) this function
2269    /// creates a shader module without runtime checks which allows shaders to perform
2270    /// operations which can lead to undefined behavior like indexing out of bounds, thus it's
2271    /// the caller responsibility to pass a shader which doesn't perform any of this
2272    /// operations.
2273    ///
2274    /// This has no effect on web.
2275    pub unsafe fn create_shader_module_unchecked(
2276        &self,
2277        desc: ShaderModuleDescriptor,
2278    ) -> ShaderModule {
2279        let (id, data) = DynContext::device_create_shader_module(
2280            &*self.context,
2281            &self.id,
2282            self.data.as_ref(),
2283            desc,
2284            unsafe { wgt::ShaderBoundChecks::unchecked() },
2285        );
2286        ShaderModule {
2287            context: Arc::clone(&self.context),
2288            id,
2289            data,
2290        }
2291    }
2292
2293    /// Creates a shader module from SPIR-V binary directly.
2294    ///
2295    /// # Safety
2296    ///
2297    /// This function passes binary data to the backend as-is and can potentially result in a
2298    /// driver crash or bogus behaviour. No attempt is made to ensure that data is valid SPIR-V.
2299    ///
2300    /// See also [`include_spirv_raw!`] and [`util::make_spirv_raw`].
2301    pub unsafe fn create_shader_module_spirv(
2302        &self,
2303        desc: &ShaderModuleDescriptorSpirV,
2304    ) -> ShaderModule {
2305        let (id, data) = unsafe {
2306            DynContext::device_create_shader_module_spirv(
2307                &*self.context,
2308                &self.id,
2309                self.data.as_ref(),
2310                desc,
2311            )
2312        };
2313        ShaderModule {
2314            context: Arc::clone(&self.context),
2315            id,
2316            data,
2317        }
2318    }
2319
2320    /// Creates an empty [`CommandEncoder`].
2321    pub fn create_command_encoder(&self, desc: &CommandEncoderDescriptor) -> CommandEncoder {
2322        let (id, data) = DynContext::device_create_command_encoder(
2323            &*self.context,
2324            &self.id,
2325            self.data.as_ref(),
2326            desc,
2327        );
2328        CommandEncoder {
2329            context: Arc::clone(&self.context),
2330            id: Some(id),
2331            data,
2332        }
2333    }
2334
2335    /// Creates an empty [`RenderBundleEncoder`].
2336    pub fn create_render_bundle_encoder(
2337        &self,
2338        desc: &RenderBundleEncoderDescriptor,
2339    ) -> RenderBundleEncoder {
2340        let (id, data) = DynContext::device_create_render_bundle_encoder(
2341            &*self.context,
2342            &self.id,
2343            self.data.as_ref(),
2344            desc,
2345        );
2346        RenderBundleEncoder {
2347            context: Arc::clone(&self.context),
2348            id,
2349            data,
2350            parent: self,
2351            _p: Default::default(),
2352        }
2353    }
2354
2355    /// Creates a new [`BindGroup`].
2356    pub fn create_bind_group(&self, desc: &BindGroupDescriptor) -> BindGroup {
2357        let (id, data) = DynContext::device_create_bind_group(
2358            &*self.context,
2359            &self.id,
2360            self.data.as_ref(),
2361            desc,
2362        );
2363        BindGroup {
2364            context: Arc::clone(&self.context),
2365            id,
2366            data,
2367        }
2368    }
2369
2370    /// Creates a [`BindGroupLayout`].
2371    pub fn create_bind_group_layout(&self, desc: &BindGroupLayoutDescriptor) -> BindGroupLayout {
2372        let (id, data) = DynContext::device_create_bind_group_layout(
2373            &*self.context,
2374            &self.id,
2375            self.data.as_ref(),
2376            desc,
2377        );
2378        BindGroupLayout {
2379            context: Arc::clone(&self.context),
2380            id,
2381            data,
2382        }
2383    }
2384
2385    /// Creates a [`PipelineLayout`].
2386    pub fn create_pipeline_layout(&self, desc: &PipelineLayoutDescriptor) -> PipelineLayout {
2387        let (id, data) = DynContext::device_create_pipeline_layout(
2388            &*self.context,
2389            &self.id,
2390            self.data.as_ref(),
2391            desc,
2392        );
2393        PipelineLayout {
2394            context: Arc::clone(&self.context),
2395            id,
2396            data,
2397        }
2398    }
2399
2400    /// Creates a [`RenderPipeline`].
2401    pub fn create_render_pipeline(&self, desc: &RenderPipelineDescriptor) -> RenderPipeline {
2402        let (id, data) = DynContext::device_create_render_pipeline(
2403            &*self.context,
2404            &self.id,
2405            self.data.as_ref(),
2406            desc,
2407        );
2408        RenderPipeline {
2409            context: Arc::clone(&self.context),
2410            id,
2411            data,
2412        }
2413    }
2414
2415    /// Creates a [`ComputePipeline`].
2416    pub fn create_compute_pipeline(&self, desc: &ComputePipelineDescriptor) -> ComputePipeline {
2417        let (id, data) = DynContext::device_create_compute_pipeline(
2418            &*self.context,
2419            &self.id,
2420            self.data.as_ref(),
2421            desc,
2422        );
2423        ComputePipeline {
2424            context: Arc::clone(&self.context),
2425            id,
2426            data,
2427        }
2428    }
2429
2430    /// Creates a [`Buffer`].
2431    pub fn create_buffer(&self, desc: &BufferDescriptor) -> Buffer {
2432        let mut map_context = MapContext::new(desc.size);
2433        if desc.mapped_at_creation {
2434            map_context.initial_range = 0..desc.size;
2435        }
2436
2437        let (id, data) =
2438            DynContext::device_create_buffer(&*self.context, &self.id, self.data.as_ref(), desc);
2439
2440        Buffer {
2441            context: Arc::clone(&self.context),
2442            id,
2443            data,
2444            map_context: Mutex::new(map_context),
2445            size: desc.size,
2446            usage: desc.usage,
2447        }
2448    }
2449
2450    /// Creates a new [`Texture`].
2451    ///
2452    /// `desc` specifies the general format of the texture.
2453    pub fn create_texture(&self, desc: &TextureDescriptor) -> Texture {
2454        let (id, data) =
2455            DynContext::device_create_texture(&*self.context, &self.id, self.data.as_ref(), desc);
2456        Texture {
2457            context: Arc::clone(&self.context),
2458            id,
2459            data,
2460            owned: true,
2461            descriptor: TextureDescriptor {
2462                label: None,
2463                view_formats: &[],
2464                ..desc.clone()
2465            },
2466        }
2467    }
2468
2469    /// Creates a [`Texture`] from a wgpu-hal Texture.
2470    ///
2471    /// # Safety
2472    ///
2473    /// - `hal_texture` must be created from this device internal handle
2474    /// - `hal_texture` must be created respecting `desc`
2475    /// - `hal_texture` must be initialized
2476    #[cfg(any(
2477        not(target_arch = "wasm32"),
2478        target_os = "emscripten",
2479        feature = "webgl"
2480    ))]
2481    pub unsafe fn create_texture_from_hal<A: wgc::hal_api::HalApi>(
2482        &self,
2483        hal_texture: A::Texture,
2484        desc: &TextureDescriptor,
2485    ) -> Texture {
2486        let texture = unsafe {
2487            self.context
2488                .as_any()
2489                .downcast_ref::<crate::backend::Context>()
2490                .unwrap()
2491                .create_texture_from_hal::<A>(
2492                    hal_texture,
2493                    self.data.as_ref().downcast_ref().unwrap(),
2494                    desc,
2495                )
2496        };
2497        Texture {
2498            context: Arc::clone(&self.context),
2499            id: ObjectId::from(texture.id()),
2500            data: Box::new(texture),
2501            owned: true,
2502            descriptor: TextureDescriptor {
2503                label: None,
2504                view_formats: &[],
2505                ..desc.clone()
2506            },
2507        }
2508    }
2509
2510    /// Creates a [`Buffer`] from a wgpu-hal Buffer.
2511    ///
2512    /// # Safety
2513    ///
2514    /// - `hal_buffer` must be created from this device internal handle
2515    /// - `hal_buffer` must be created respecting `desc`
2516    /// - `hal_buffer` must be initialized
2517    #[cfg(any(
2518        not(target_arch = "wasm32"),
2519        target_os = "emscripten",
2520        feature = "webgl"
2521    ))]
2522    pub unsafe fn create_buffer_from_hal<A: wgc::hal_api::HalApi>(
2523        &self,
2524        hal_buffer: A::Buffer,
2525        desc: &BufferDescriptor,
2526    ) -> Buffer {
2527        let mut map_context = MapContext::new(desc.size);
2528        if desc.mapped_at_creation {
2529            map_context.initial_range = 0..desc.size;
2530        }
2531
2532        let (id, buffer) = unsafe {
2533            self.context
2534                .as_any()
2535                .downcast_ref::<crate::backend::Context>()
2536                .unwrap()
2537                .create_buffer_from_hal::<A>(
2538                    hal_buffer,
2539                    self.data.as_ref().downcast_ref().unwrap(),
2540                    desc,
2541                )
2542        };
2543
2544        Buffer {
2545            context: Arc::clone(&self.context),
2546            id: ObjectId::from(id),
2547            data: Box::new(buffer),
2548            map_context: Mutex::new(map_context),
2549            size: desc.size,
2550            usage: desc.usage,
2551        }
2552    }
2553
2554    /// Creates a new [`Sampler`].
2555    ///
2556    /// `desc` specifies the behavior of the sampler.
2557    pub fn create_sampler(&self, desc: &SamplerDescriptor) -> Sampler {
2558        let (id, data) =
2559            DynContext::device_create_sampler(&*self.context, &self.id, self.data.as_ref(), desc);
2560        Sampler {
2561            context: Arc::clone(&self.context),
2562            id,
2563            data,
2564        }
2565    }
2566
2567    /// Creates a new [`QuerySet`].
2568    pub fn create_query_set(&self, desc: &QuerySetDescriptor) -> QuerySet {
2569        let (id, data) =
2570            DynContext::device_create_query_set(&*self.context, &self.id, self.data.as_ref(), desc);
2571        QuerySet {
2572            context: Arc::clone(&self.context),
2573            id,
2574            data,
2575        }
2576    }
2577
2578    /// Set a callback for errors that are not handled in error scopes.
2579    pub fn on_uncaptured_error(&self, handler: Box<dyn UncapturedErrorHandler>) {
2580        self.context
2581            .device_on_uncaptured_error(&self.id, self.data.as_ref(), handler);
2582    }
2583
2584    /// Push an error scope.
2585    pub fn push_error_scope(&self, filter: ErrorFilter) {
2586        self.context
2587            .device_push_error_scope(&self.id, self.data.as_ref(), filter);
2588    }
2589
2590    /// Pop an error scope.
2591    pub fn pop_error_scope(&self) -> impl Future<Output = Option<Error>> + WasmNotSend {
2592        self.context
2593            .device_pop_error_scope(&self.id, self.data.as_ref())
2594    }
2595
2596    /// Starts frame capture.
2597    pub fn start_capture(&self) {
2598        DynContext::device_start_capture(&*self.context, &self.id, self.data.as_ref())
2599    }
2600
2601    /// Stops frame capture.
2602    pub fn stop_capture(&self) {
2603        DynContext::device_stop_capture(&*self.context, &self.id, self.data.as_ref())
2604    }
2605
2606    /// Apply a callback to this `Device`'s underlying backend device.
2607    ///
2608    /// If this `Device` is implemented by the backend API given by `A` (Vulkan,
2609    /// Dx12, etc.), then apply `hal_device_callback` to `Some(&device)`, where
2610    /// `device` is the underlying backend device type, [`A::Device`].
2611    ///
2612    /// If this `Device` uses a different backend, apply `hal_device_callback`
2613    /// to `None`.
2614    ///
2615    /// The device is locked for reading while `hal_device_callback` runs. If
2616    /// the callback attempts to perform any `wgpu` operations that require
2617    /// write access to the device (destroying a buffer, say), deadlock will
2618    /// occur. The locks are automatically released when the callback returns.
2619    ///
2620    /// # Safety
2621    ///
2622    /// - The raw handle passed to the callback must not be manually destroyed.
2623    ///
2624    /// [`A::Device`]: hal::Api::Device
2625    #[cfg(any(
2626        not(target_arch = "wasm32"),
2627        target_os = "emscripten",
2628        feature = "webgl"
2629    ))]
2630    pub unsafe fn as_hal<A: wgc::hal_api::HalApi, F: FnOnce(Option<&A::Device>) -> R, R>(
2631        &self,
2632        hal_device_callback: F,
2633    ) -> R {
2634        unsafe {
2635            self.context
2636                .as_any()
2637                .downcast_ref::<crate::backend::Context>()
2638                .unwrap()
2639                .device_as_hal::<A, F, R>(
2640                    self.data.as_ref().downcast_ref().unwrap(),
2641                    hal_device_callback,
2642                )
2643        }
2644    }
2645}
2646
2647impl Drop for Device {
2648    fn drop(&mut self) {
2649        if !thread::panicking() {
2650            self.context.device_drop(&self.id, self.data.as_ref());
2651        }
2652    }
2653}
2654
2655/// Requesting a device failed.
2656#[derive(Clone, PartialEq, Eq, Debug)]
2657pub struct RequestDeviceError;
2658static_assertions::assert_impl_all!(RequestDeviceError: Send, Sync);
2659
2660impl Display for RequestDeviceError {
2661    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2662        write!(f, "Requesting a device failed")
2663    }
2664}
2665
2666impl error::Error for RequestDeviceError {}
2667
2668/// [`Instance::create_surface()`] or a related function failed.
2669#[derive(Clone, PartialEq, Eq, Debug)]
2670#[non_exhaustive]
2671pub struct CreateSurfaceError {
2672    // TODO: Report diagnostic clues
2673}
2674static_assertions::assert_impl_all!(CreateSurfaceError: Send, Sync);
2675
2676impl Display for CreateSurfaceError {
2677    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2678        write!(f, "Creating a surface failed")
2679    }
2680}
2681
2682impl error::Error for CreateSurfaceError {}
2683
2684/// Error occurred when trying to async map a buffer.
2685#[derive(Clone, PartialEq, Eq, Debug)]
2686pub struct BufferAsyncError;
2687static_assertions::assert_impl_all!(BufferAsyncError: Send, Sync);
2688
2689impl Display for BufferAsyncError {
2690    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2691        write!(f, "Error occurred when trying to async map a buffer")
2692    }
2693}
2694
2695impl error::Error for BufferAsyncError {}
2696
2697/// Type of buffer mapping.
2698#[derive(Debug, Clone, Copy, Eq, PartialEq)]
2699pub enum MapMode {
2700    /// Map only for reading
2701    Read,
2702    /// Map only for writing
2703    Write,
2704}
2705static_assertions::assert_impl_all!(MapMode: Send, Sync);
2706
2707fn range_to_offset_size<S: RangeBounds<BufferAddress>>(
2708    bounds: S,
2709) -> (BufferAddress, Option<BufferSize>) {
2710    let offset = match bounds.start_bound() {
2711        Bound::Included(&bound) => bound,
2712        Bound::Excluded(&bound) => bound + 1,
2713        Bound::Unbounded => 0,
2714    };
2715    let size = match bounds.end_bound() {
2716        Bound::Included(&bound) => Some(bound + 1 - offset),
2717        Bound::Excluded(&bound) => Some(bound - offset),
2718        Bound::Unbounded => None,
2719    }
2720    .map(|size| BufferSize::new(size).expect("Buffer slices can not be empty"));
2721
2722    (offset, size)
2723}
2724
2725#[cfg(test)]
2726mod tests {
2727    use crate::BufferSize;
2728
2729    #[test]
2730    fn range_to_offset_size_works() {
2731        assert_eq!(crate::range_to_offset_size(0..2), (0, BufferSize::new(2)));
2732        assert_eq!(crate::range_to_offset_size(2..5), (2, BufferSize::new(3)));
2733        assert_eq!(crate::range_to_offset_size(..), (0, None));
2734        assert_eq!(crate::range_to_offset_size(21..), (21, None));
2735        assert_eq!(crate::range_to_offset_size(0..), (0, None));
2736        assert_eq!(crate::range_to_offset_size(..21), (0, BufferSize::new(21)));
2737    }
2738
2739    #[test]
2740    #[should_panic]
2741    fn range_to_offset_size_panics_for_empty_range() {
2742        crate::range_to_offset_size(123..123);
2743    }
2744
2745    #[test]
2746    #[should_panic]
2747    fn range_to_offset_size_panics_for_unbounded_empty_range() {
2748        crate::range_to_offset_size(..0);
2749    }
2750}
2751
2752/// Read only view into a mapped buffer.
2753#[derive(Debug)]
2754pub struct BufferView<'a> {
2755    slice: BufferSlice<'a>,
2756    data: Box<dyn crate::context::BufferMappedRange>,
2757}
2758
2759/// Write only view into mapped buffer.
2760///
2761/// It is possible to read the buffer using this view, but doing so is not
2762/// recommended, as it is likely to be slow.
2763#[derive(Debug)]
2764pub struct BufferViewMut<'a> {
2765    slice: BufferSlice<'a>,
2766    data: Box<dyn crate::context::BufferMappedRange>,
2767    readable: bool,
2768}
2769
2770impl std::ops::Deref for BufferView<'_> {
2771    type Target = [u8];
2772
2773    #[inline]
2774    fn deref(&self) -> &[u8] {
2775        self.data.slice()
2776    }
2777}
2778
2779impl AsRef<[u8]> for BufferView<'_> {
2780    #[inline]
2781    fn as_ref(&self) -> &[u8] {
2782        self.data.slice()
2783    }
2784}
2785
2786impl AsMut<[u8]> for BufferViewMut<'_> {
2787    #[inline]
2788    fn as_mut(&mut self) -> &mut [u8] {
2789        self.data.slice_mut()
2790    }
2791}
2792
2793impl Deref for BufferViewMut<'_> {
2794    type Target = [u8];
2795
2796    fn deref(&self) -> &Self::Target {
2797        if !self.readable {
2798            log::warn!("Reading from a BufferViewMut is slow and not recommended.");
2799        }
2800
2801        self.data.slice()
2802    }
2803}
2804
2805impl DerefMut for BufferViewMut<'_> {
2806    fn deref_mut(&mut self) -> &mut Self::Target {
2807        self.data.slice_mut()
2808    }
2809}
2810
2811impl Drop for BufferView<'_> {
2812    fn drop(&mut self) {
2813        self.slice
2814            .buffer
2815            .map_context
2816            .lock()
2817            .remove(self.slice.offset, self.slice.size);
2818    }
2819}
2820
2821impl Drop for BufferViewMut<'_> {
2822    fn drop(&mut self) {
2823        self.slice
2824            .buffer
2825            .map_context
2826            .lock()
2827            .remove(self.slice.offset, self.slice.size);
2828    }
2829}
2830
2831impl Buffer {
2832    /// Return the binding view of the entire buffer.
2833    pub fn as_entire_binding(&self) -> BindingResource {
2834        BindingResource::Buffer(self.as_entire_buffer_binding())
2835    }
2836
2837    /// Return the binding view of the entire buffer.
2838    pub fn as_entire_buffer_binding(&self) -> BufferBinding {
2839        BufferBinding {
2840            buffer: self,
2841            offset: 0,
2842            size: None,
2843        }
2844    }
2845
2846    /// Use only a portion of this Buffer for a given operation. Choosing a range with no end
2847    /// will use the rest of the buffer. Using a totally unbounded range will use the entire buffer.
2848    pub fn slice<S: RangeBounds<BufferAddress>>(&self, bounds: S) -> BufferSlice {
2849        let (offset, size) = range_to_offset_size(bounds);
2850        BufferSlice {
2851            buffer: self,
2852            offset,
2853            size,
2854        }
2855    }
2856
2857    /// Flushes any pending write operations and unmaps the buffer from host memory.
2858    pub fn unmap(&self) {
2859        self.map_context.lock().reset();
2860        DynContext::buffer_unmap(&*self.context, &self.id, self.data.as_ref());
2861    }
2862
2863    /// Destroy the associated native resources as soon as possible.
2864    pub fn destroy(&self) {
2865        DynContext::buffer_destroy(&*self.context, &self.id, self.data.as_ref());
2866    }
2867
2868    /// Returns the length of the buffer allocation in bytes.
2869    ///
2870    /// This is always equal to the `size` that was specified when creating the buffer.
2871    pub fn size(&self) -> BufferAddress {
2872        self.size
2873    }
2874
2875    /// Returns the allowed usages for this `Buffer`.
2876    ///
2877    /// This is always equal to the `usage` that was specified when creating the buffer.
2878    pub fn usage(&self) -> BufferUsages {
2879        self.usage
2880    }
2881}
2882
2883impl<'a> BufferSlice<'a> {
2884    /// Map the buffer. Buffer is ready to map once the callback is called.
2885    ///
2886    /// For the callback to complete, either `queue.submit(..)`, `instance.poll_all(..)`, or `device.poll(..)`
2887    /// must be called elsewhere in the runtime, possibly integrated into an event loop or run on a separate thread.
2888    ///
2889    /// The callback will be called on the thread that first calls the above functions after the gpu work
2890    /// has completed. There are no restrictions on the code you can run in the callback, however on native the
2891    /// call to the function will not complete until the callback returns, so prefer keeping callbacks short
2892    /// and used to set flags, send messages, etc.
2893    pub fn map_async(
2894        &self,
2895        mode: MapMode,
2896        callback: impl FnOnce(Result<(), BufferAsyncError>) + WasmNotSend + 'static,
2897    ) {
2898        let mut mc = self.buffer.map_context.lock();
2899        assert_eq!(
2900            mc.initial_range,
2901            0..0,
2902            "Buffer {:?} is already mapped",
2903            self.buffer.id
2904        );
2905        let end = match self.size {
2906            Some(s) => self.offset + s.get(),
2907            None => mc.total_size,
2908        };
2909        mc.initial_range = self.offset..end;
2910
2911        DynContext::buffer_map_async(
2912            &*self.buffer.context,
2913            &self.buffer.id,
2914            self.buffer.data.as_ref(),
2915            mode,
2916            self.offset..end,
2917            Box::new(callback),
2918        )
2919    }
2920
2921    /// Synchronously and immediately map a buffer for reading. If the buffer is not immediately mappable
2922    /// through [`BufferDescriptor::mapped_at_creation`] or [`BufferSlice::map_async`], will panic.
2923    pub fn get_mapped_range(&self) -> BufferView<'a> {
2924        let end = self.buffer.map_context.lock().add(self.offset, self.size);
2925        let data = DynContext::buffer_get_mapped_range(
2926            &*self.buffer.context,
2927            &self.buffer.id,
2928            self.buffer.data.as_ref(),
2929            self.offset..end,
2930        );
2931        BufferView { slice: *self, data }
2932    }
2933
2934    /// Synchronously and immediately map a buffer for reading. If the buffer is not immediately mappable
2935    /// through [`BufferDescriptor::mapped_at_creation`] or [`BufferSlice::map_async`], will panic.
2936    ///
2937    /// This is useful in wasm builds when you want to pass mapped data directly to js. Unlike `get_mapped_range`
2938    /// which unconditionally copies mapped data into the wasm heap, this function directly hands you the
2939    /// ArrayBuffer that we mapped the data into in js.
2940    #[cfg(all(
2941        target_arch = "wasm32",
2942        not(any(target_os = "emscripten", feature = "webgl"))
2943    ))]
2944    pub fn get_mapped_range_as_array_buffer(&self) -> js_sys::ArrayBuffer {
2945        let end = self.buffer.map_context.lock().add(self.offset, self.size);
2946        DynContext::buffer_get_mapped_range_as_array_buffer(
2947            &*self.buffer.context,
2948            &self.buffer.id,
2949            self.buffer.data.as_ref(),
2950            self.offset..end,
2951        )
2952    }
2953
2954    /// Synchronously and immediately map a buffer for writing. If the buffer is not immediately mappable
2955    /// through [`BufferDescriptor::mapped_at_creation`] or [`BufferSlice::map_async`], will panic.
2956    pub fn get_mapped_range_mut(&self) -> BufferViewMut<'a> {
2957        let end = self.buffer.map_context.lock().add(self.offset, self.size);
2958        let data = DynContext::buffer_get_mapped_range(
2959            &*self.buffer.context,
2960            &self.buffer.id,
2961            self.buffer.data.as_ref(),
2962            self.offset..end,
2963        );
2964        BufferViewMut {
2965            slice: *self,
2966            data,
2967            readable: self.buffer.usage.contains(BufferUsages::MAP_READ),
2968        }
2969    }
2970}
2971
2972impl Drop for Buffer {
2973    fn drop(&mut self) {
2974        if !thread::panicking() {
2975            self.context.buffer_drop(&self.id, self.data.as_ref());
2976        }
2977    }
2978}
2979
2980impl Texture {
2981    /// Returns the inner hal Texture using a callback. The hal texture will be `None` if the
2982    /// backend type argument does not match with this wgpu Texture
2983    ///
2984    /// # Safety
2985    ///
2986    /// - The raw handle obtained from the hal Texture must not be manually destroyed
2987    #[cfg(any(
2988        not(target_arch = "wasm32"),
2989        target_os = "emscripten",
2990        feature = "webgl"
2991    ))]
2992    pub unsafe fn as_hal<A: wgc::hal_api::HalApi, F: FnOnce(Option<&A::Texture>)>(
2993        &self,
2994        hal_texture_callback: F,
2995    ) {
2996        let texture = self.data.as_ref().downcast_ref().unwrap();
2997        unsafe {
2998            self.context
2999                .as_any()
3000                .downcast_ref::<crate::backend::Context>()
3001                .unwrap()
3002                .texture_as_hal::<A, F>(texture, hal_texture_callback)
3003        }
3004    }
3005
3006    /// Creates a view of this texture.
3007    pub fn create_view(&self, desc: &TextureViewDescriptor) -> TextureView {
3008        let (id, data) =
3009            DynContext::texture_create_view(&*self.context, &self.id, self.data.as_ref(), desc);
3010        TextureView {
3011            context: Arc::clone(&self.context),
3012            id,
3013            data,
3014        }
3015    }
3016
3017    /// Destroy the associated native resources as soon as possible.
3018    pub fn destroy(&self) {
3019        DynContext::texture_destroy(&*self.context, &self.id, self.data.as_ref());
3020    }
3021
3022    /// Make an `ImageCopyTexture` representing the whole texture.
3023    pub fn as_image_copy(&self) -> ImageCopyTexture {
3024        ImageCopyTexture {
3025            texture: self,
3026            mip_level: 0,
3027            origin: Origin3d::ZERO,
3028            aspect: TextureAspect::All,
3029        }
3030    }
3031
3032    /// Returns the size of this `Texture`.
3033    ///
3034    /// This is always equal to the `size` that was specified when creating the texture.
3035    pub fn size(&self) -> Extent3d {
3036        self.descriptor.size
3037    }
3038
3039    /// Returns the width of this `Texture`.
3040    ///
3041    /// This is always equal to the `size.width` that was specified when creating the texture.
3042    pub fn width(&self) -> u32 {
3043        self.descriptor.size.width
3044    }
3045
3046    /// Returns the height of this `Texture`.
3047    ///
3048    /// This is always equal to the `size.height` that was specified when creating the texture.
3049    pub fn height(&self) -> u32 {
3050        self.descriptor.size.height
3051    }
3052
3053    /// Returns the depth or layer count of this `Texture`.
3054    ///
3055    /// This is always equal to the `size.depth_or_array_layers` that was specified when creating the texture.
3056    pub fn depth_or_array_layers(&self) -> u32 {
3057        self.descriptor.size.depth_or_array_layers
3058    }
3059
3060    /// Returns the mip_level_count of this `Texture`.
3061    ///
3062    /// This is always equal to the `mip_level_count` that was specified when creating the texture.
3063    pub fn mip_level_count(&self) -> u32 {
3064        self.descriptor.mip_level_count
3065    }
3066
3067    /// Returns the sample_count of this `Texture`.
3068    ///
3069    /// This is always equal to the `sample_count` that was specified when creating the texture.
3070    pub fn sample_count(&self) -> u32 {
3071        self.descriptor.sample_count
3072    }
3073
3074    /// Returns the dimension of this `Texture`.
3075    ///
3076    /// This is always equal to the `dimension` that was specified when creating the texture.
3077    pub fn dimension(&self) -> TextureDimension {
3078        self.descriptor.dimension
3079    }
3080
3081    /// Returns the format of this `Texture`.
3082    ///
3083    /// This is always equal to the `format` that was specified when creating the texture.
3084    pub fn format(&self) -> TextureFormat {
3085        self.descriptor.format
3086    }
3087
3088    /// Returns the allowed usages of this `Texture`.
3089    ///
3090    /// This is always equal to the `usage` that was specified when creating the texture.
3091    pub fn usage(&self) -> TextureUsages {
3092        self.descriptor.usage
3093    }
3094}
3095
3096impl Drop for Texture {
3097    fn drop(&mut self) {
3098        if self.owned && !thread::panicking() {
3099            self.context.texture_drop(&self.id, self.data.as_ref());
3100        }
3101    }
3102}
3103
3104impl Drop for TextureView {
3105    fn drop(&mut self) {
3106        if !thread::panicking() {
3107            self.context.texture_view_drop(&self.id, self.data.as_ref());
3108        }
3109    }
3110}
3111
3112impl CommandEncoder {
3113    /// Finishes recording and returns a [`CommandBuffer`] that can be submitted for execution.
3114    pub fn finish(mut self) -> CommandBuffer {
3115        let (id, data) = DynContext::command_encoder_finish(
3116            &*self.context,
3117            self.id.take().unwrap(),
3118            self.data.as_mut(),
3119        );
3120        CommandBuffer {
3121            context: Arc::clone(&self.context),
3122            id: Some(id),
3123            data: Some(data),
3124        }
3125    }
3126
3127    /// Begins recording of a render pass.
3128    ///
3129    /// This function returns a [`RenderPass`] object which records a single render pass.
3130    pub fn begin_render_pass<'pass>(
3131        &'pass mut self,
3132        desc: &RenderPassDescriptor<'pass, '_>,
3133    ) -> RenderPass<'pass> {
3134        let id = self.id.as_ref().unwrap();
3135        let (id, data) = DynContext::command_encoder_begin_render_pass(
3136            &*self.context,
3137            id,
3138            self.data.as_ref(),
3139            desc,
3140        );
3141        RenderPass {
3142            id,
3143            data,
3144            parent: self,
3145        }
3146    }
3147
3148    /// Begins recording of a compute pass.
3149    ///
3150    /// This function returns a [`ComputePass`] object which records a single compute pass.
3151    pub fn begin_compute_pass(&mut self, desc: &ComputePassDescriptor) -> ComputePass {
3152        let id = self.id.as_ref().unwrap();
3153        let (id, data) = DynContext::command_encoder_begin_compute_pass(
3154            &*self.context,
3155            id,
3156            self.data.as_ref(),
3157            desc,
3158        );
3159        ComputePass {
3160            id,
3161            data,
3162            parent: self,
3163        }
3164    }
3165
3166    /// Copy data from one buffer to another.
3167    ///
3168    /// # Panics
3169    ///
3170    /// - Buffer offsets or copy size not a multiple of [`COPY_BUFFER_ALIGNMENT`].
3171    /// - Copy would overrun buffer.
3172    /// - Copy within the same buffer.
3173    pub fn copy_buffer_to_buffer(
3174        &mut self,
3175        source: &Buffer,
3176        source_offset: BufferAddress,
3177        destination: &Buffer,
3178        destination_offset: BufferAddress,
3179        copy_size: BufferAddress,
3180    ) {
3181        DynContext::command_encoder_copy_buffer_to_buffer(
3182            &*self.context,
3183            self.id.as_ref().unwrap(),
3184            self.data.as_ref(),
3185            &source.id,
3186            source.data.as_ref(),
3187            source_offset,
3188            &destination.id,
3189            destination.data.as_ref(),
3190            destination_offset,
3191            copy_size,
3192        );
3193    }
3194
3195    /// Copy data from a buffer to a texture.
3196    pub fn copy_buffer_to_texture(
3197        &mut self,
3198        source: ImageCopyBuffer,
3199        destination: ImageCopyTexture,
3200        copy_size: Extent3d,
3201    ) {
3202        DynContext::command_encoder_copy_buffer_to_texture(
3203            &*self.context,
3204            self.id.as_ref().unwrap(),
3205            self.data.as_ref(),
3206            source,
3207            destination,
3208            copy_size,
3209        );
3210    }
3211
3212    /// Copy data from a texture to a buffer.
3213    pub fn copy_texture_to_buffer(
3214        &mut self,
3215        source: ImageCopyTexture,
3216        destination: ImageCopyBuffer,
3217        copy_size: Extent3d,
3218    ) {
3219        DynContext::command_encoder_copy_texture_to_buffer(
3220            &*self.context,
3221            self.id.as_ref().unwrap(),
3222            self.data.as_ref(),
3223            source,
3224            destination,
3225            copy_size,
3226        );
3227    }
3228
3229    /// Copy data from one texture to another.
3230    ///
3231    /// # Panics
3232    ///
3233    /// - Textures are not the same type
3234    /// - If a depth texture, or a multisampled texture, the entire texture must be copied
3235    /// - Copy would overrun either texture
3236    pub fn copy_texture_to_texture(
3237        &mut self,
3238        source: ImageCopyTexture,
3239        destination: ImageCopyTexture,
3240        copy_size: Extent3d,
3241    ) {
3242        DynContext::command_encoder_copy_texture_to_texture(
3243            &*self.context,
3244            self.id.as_ref().unwrap(),
3245            self.data.as_ref(),
3246            source,
3247            destination,
3248            copy_size,
3249        );
3250    }
3251
3252    /// Clears texture to zero.
3253    ///
3254    /// Note that unlike with clear_buffer, `COPY_DST` usage is not required.
3255    ///
3256    /// # Implementation notes
3257    ///
3258    /// - implemented either via buffer copies and render/depth target clear, path depends on texture usages
3259    /// - behaves like texture zero init, but is performed immediately (clearing is *not* delayed via marking it as uninitialized)
3260    ///
3261    /// # Panics
3262    ///
3263    /// - `CLEAR_TEXTURE` extension not enabled
3264    /// - Range is out of bounds
3265    pub fn clear_texture(&mut self, texture: &Texture, subresource_range: &ImageSubresourceRange) {
3266        DynContext::command_encoder_clear_texture(
3267            &*self.context,
3268            self.id.as_ref().unwrap(),
3269            self.data.as_ref(),
3270            texture,
3271            subresource_range,
3272        );
3273    }
3274
3275    /// Clears buffer to zero.
3276    ///
3277    /// # Panics
3278    ///
3279    /// - Buffer does not have `COPY_DST` usage.
3280    /// - Range it out of bounds
3281    pub fn clear_buffer(
3282        &mut self,
3283        buffer: &Buffer,
3284        offset: BufferAddress,
3285        size: Option<BufferSize>,
3286    ) {
3287        DynContext::command_encoder_clear_buffer(
3288            &*self.context,
3289            self.id.as_ref().unwrap(),
3290            self.data.as_ref(),
3291            buffer,
3292            offset,
3293            size,
3294        );
3295    }
3296
3297    /// Inserts debug marker.
3298    pub fn insert_debug_marker(&mut self, label: &str) {
3299        let id = self.id.as_ref().unwrap();
3300        DynContext::command_encoder_insert_debug_marker(
3301            &*self.context,
3302            id,
3303            self.data.as_ref(),
3304            label,
3305        );
3306    }
3307
3308    /// Start record commands and group it into debug marker group.
3309    pub fn push_debug_group(&mut self, label: &str) {
3310        let id = self.id.as_ref().unwrap();
3311        DynContext::command_encoder_push_debug_group(&*self.context, id, self.data.as_ref(), label);
3312    }
3313
3314    /// Stops command recording and creates debug group.
3315    pub fn pop_debug_group(&mut self) {
3316        let id = self.id.as_ref().unwrap();
3317        DynContext::command_encoder_pop_debug_group(&*self.context, id, self.data.as_ref());
3318    }
3319}
3320
3321/// [`Features::TIMESTAMP_QUERY`] must be enabled on the device in order to call these functions.
3322impl CommandEncoder {
3323    /// Issue a timestamp command at this point in the queue.
3324    /// The timestamp will be written to the specified query set, at the specified index.
3325    ///
3326    /// Must be multiplied by [`Queue::get_timestamp_period`] to get
3327    /// the value in nanoseconds. Absolute values have no meaning,
3328    /// but timestamps can be subtracted to get the time it takes
3329    /// for a string of operations to complete.
3330    pub fn write_timestamp(&mut self, query_set: &QuerySet, query_index: u32) {
3331        DynContext::command_encoder_write_timestamp(
3332            &*self.context,
3333            self.id.as_ref().unwrap(),
3334            self.data.as_mut(),
3335            &query_set.id,
3336            query_set.data.as_ref(),
3337            query_index,
3338        )
3339    }
3340}
3341
3342/// [`Features::TIMESTAMP_QUERY`] or [`Features::PIPELINE_STATISTICS_QUERY`] must be enabled on the device in order to call these functions.
3343impl CommandEncoder {
3344    /// Resolve a query set, writing the results into the supplied destination buffer.
3345    ///
3346    /// Queries may be between 8 and 40 bytes each. See [`PipelineStatisticsTypes`] for more information.
3347    pub fn resolve_query_set(
3348        &mut self,
3349        query_set: &QuerySet,
3350        query_range: Range<u32>,
3351        destination: &Buffer,
3352        destination_offset: BufferAddress,
3353    ) {
3354        DynContext::command_encoder_resolve_query_set(
3355            &*self.context,
3356            self.id.as_ref().unwrap(),
3357            self.data.as_ref(),
3358            &query_set.id,
3359            query_set.data.as_ref(),
3360            query_range.start,
3361            query_range.end - query_range.start,
3362            &destination.id,
3363            destination.data.as_ref(),
3364            destination_offset,
3365        )
3366    }
3367}
3368
3369impl<'a> RenderPass<'a> {
3370    /// Sets the active bind group for a given bind group index. The bind group layout
3371    /// in the active pipeline when any `draw()` function is called must match the layout of this bind group.
3372    ///
3373    /// If the bind group have dynamic offsets, provide them in binding order.
3374    /// These offsets have to be aligned to [`Limits::min_uniform_buffer_offset_alignment`]
3375    /// or [`Limits::min_storage_buffer_offset_alignment`] appropriately.
3376    pub fn set_bind_group(
3377        &mut self,
3378        index: u32,
3379        bind_group: &'a BindGroup,
3380        offsets: &[DynamicOffset],
3381    ) {
3382        DynContext::render_pass_set_bind_group(
3383            &*self.parent.context,
3384            &mut self.id,
3385            self.data.as_mut(),
3386            index,
3387            &bind_group.id,
3388            bind_group.data.as_ref(),
3389            offsets,
3390        )
3391    }
3392
3393    /// Sets the active render pipeline.
3394    ///
3395    /// Subsequent draw calls will exhibit the behavior defined by `pipeline`.
3396    pub fn set_pipeline(&mut self, pipeline: &'a RenderPipeline) {
3397        DynContext::render_pass_set_pipeline(
3398            &*self.parent.context,
3399            &mut self.id,
3400            self.data.as_mut(),
3401            &pipeline.id,
3402            pipeline.data.as_ref(),
3403        )
3404    }
3405
3406    /// Sets the blend color as used by some of the blending modes.
3407    ///
3408    /// Subsequent blending tests will test against this value.
3409    pub fn set_blend_constant(&mut self, color: Color) {
3410        DynContext::render_pass_set_blend_constant(
3411            &*self.parent.context,
3412            &mut self.id,
3413            self.data.as_mut(),
3414            color,
3415        )
3416    }
3417
3418    /// Sets the active index buffer.
3419    ///
3420    /// Subsequent calls to [`draw_indexed`](RenderPass::draw_indexed) on this [`RenderPass`] will
3421    /// use `buffer` as the source index buffer.
3422    pub fn set_index_buffer(&mut self, buffer_slice: BufferSlice<'a>, index_format: IndexFormat) {
3423        DynContext::render_pass_set_index_buffer(
3424            &*self.parent.context,
3425            &mut self.id,
3426            self.data.as_mut(),
3427            &buffer_slice.buffer.id,
3428            buffer_slice.buffer.data.as_ref(),
3429            index_format,
3430            buffer_slice.offset,
3431            buffer_slice.size,
3432        )
3433    }
3434
3435    /// Assign a vertex buffer to a slot.
3436    ///
3437    /// Subsequent calls to [`draw`] and [`draw_indexed`] on this
3438    /// [`RenderPass`] will use `buffer` as one of the source vertex buffers.
3439    ///
3440    /// The `slot` refers to the index of the matching descriptor in
3441    /// [`VertexState::buffers`].
3442    ///
3443    /// [`draw`]: RenderPass::draw
3444    /// [`draw_indexed`]: RenderPass::draw_indexed
3445    pub fn set_vertex_buffer(&mut self, slot: u32, buffer_slice: BufferSlice<'a>) {
3446        DynContext::render_pass_set_vertex_buffer(
3447            &*self.parent.context,
3448            &mut self.id,
3449            self.data.as_mut(),
3450            slot,
3451            &buffer_slice.buffer.id,
3452            buffer_slice.buffer.data.as_ref(),
3453            buffer_slice.offset,
3454            buffer_slice.size,
3455        )
3456    }
3457
3458    /// Sets the scissor rectangle used during the rasterization stage.
3459    /// After transformation into [viewport coordinates](https://www.w3.org/TR/webgpu/#viewport-coordinates).
3460    ///
3461    /// Subsequent draw calls will discard any fragments which fall outside the scissor rectangle.
3462    pub fn set_scissor_rect(&mut self, x: u32, y: u32, width: u32, height: u32) {
3463        DynContext::render_pass_set_scissor_rect(
3464            &*self.parent.context,
3465            &mut self.id,
3466            self.data.as_mut(),
3467            x,
3468            y,
3469            width,
3470            height,
3471        );
3472    }
3473
3474    /// Sets the viewport used during the rasterization stage to linearly map
3475    /// from [normalized device coordinates](https://www.w3.org/TR/webgpu/#ndc) to [viewport coordinates](https://www.w3.org/TR/webgpu/#viewport-coordinates).
3476    ///
3477    /// Subsequent draw calls will draw any fragments in this region.
3478    pub fn set_viewport(&mut self, x: f32, y: f32, w: f32, h: f32, min_depth: f32, max_depth: f32) {
3479        DynContext::render_pass_set_viewport(
3480            &*self.parent.context,
3481            &mut self.id,
3482            self.data.as_mut(),
3483            x,
3484            y,
3485            w,
3486            h,
3487            min_depth,
3488            max_depth,
3489        );
3490    }
3491
3492    /// Sets the stencil reference.
3493    ///
3494    /// Subsequent stencil tests will test against this value.
3495    pub fn set_stencil_reference(&mut self, reference: u32) {
3496        DynContext::render_pass_set_stencil_reference(
3497            &*self.parent.context,
3498            &mut self.id,
3499            self.data.as_mut(),
3500            reference,
3501        );
3502    }
3503
3504    /// Draws primitives from the active vertex buffer(s).
3505    ///
3506    /// The active vertex buffer(s) can be set with [`RenderPass::set_vertex_buffer`].
3507    /// Does not use an Index Buffer. If you need this see [`RenderPass::draw_indexed`]
3508    ///
3509    /// Panics if vertices Range is outside of the range of the vertices range of any set vertex buffer.
3510    ///
3511    /// vertices: The range of vertices to draw.
3512    /// instances: Range of Instances to draw. Use 0..1 if instance buffers are not used.
3513    /// E.g.of how its used internally
3514    /// ```rust ignore
3515    /// for instance_id in instance_range {
3516    ///     for vertex_id in vertex_range {
3517    ///         let vertex = vertex[vertex_id];
3518    ///         vertex_shader(vertex, vertex_id, instance_id);
3519    ///     }
3520    /// }
3521    /// ```
3522    pub fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>) {
3523        DynContext::render_pass_draw(
3524            &*self.parent.context,
3525            &mut self.id,
3526            self.data.as_mut(),
3527            vertices,
3528            instances,
3529        )
3530    }
3531
3532    /// Inserts debug marker.
3533    pub fn insert_debug_marker(&mut self, label: &str) {
3534        DynContext::render_pass_insert_debug_marker(
3535            &*self.parent.context,
3536            &mut self.id,
3537            self.data.as_mut(),
3538            label,
3539        );
3540    }
3541
3542    /// Start record commands and group it into debug marker group.
3543    pub fn push_debug_group(&mut self, label: &str) {
3544        DynContext::render_pass_push_debug_group(
3545            &*self.parent.context,
3546            &mut self.id,
3547            self.data.as_mut(),
3548            label,
3549        );
3550    }
3551
3552    /// Stops command recording and creates debug group.
3553    pub fn pop_debug_group(&mut self) {
3554        DynContext::render_pass_pop_debug_group(
3555            &*self.parent.context,
3556            &mut self.id,
3557            self.data.as_mut(),
3558        );
3559    }
3560
3561    /// Draws indexed primitives using the active index buffer and the active vertex buffers.
3562    ///
3563    /// The active index buffer can be set with [`RenderPass::set_index_buffer`]
3564    /// The active vertex buffers can be set with [`RenderPass::set_vertex_buffer`].
3565    ///
3566    /// Panics if indices Range is outside of the range of the indices range of any set index buffer.
3567    ///
3568    /// indices: The range of indices to draw.
3569    /// base_vertex: value added to each index value before indexing into the vertex buffers.
3570    /// instances: Range of Instances to draw. Use 0..1 if instance buffers are not used.
3571    /// E.g.of how its used internally
3572    /// ```rust ignore
3573    /// for instance_id in instance_range {
3574    ///     for index_index in index_range {
3575    ///         let vertex_id = index_buffer[index_index];
3576    ///         let adjusted_vertex_id = vertex_id + base_vertex;
3577    ///         let vertex = vertex[adjusted_vertex_id];
3578    ///         vertex_shader(vertex, adjusted_vertex_id, instance_id);
3579    ///     }
3580    /// }
3581    /// ```
3582    pub fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>) {
3583        DynContext::render_pass_draw_indexed(
3584            &*self.parent.context,
3585            &mut self.id,
3586            self.data.as_mut(),
3587            indices,
3588            base_vertex,
3589            instances,
3590        );
3591    }
3592
3593    /// Draws primitives from the active vertex buffer(s) based on the contents of the `indirect_buffer`.
3594    ///
3595    /// The active vertex buffers can be set with [`RenderPass::set_vertex_buffer`].
3596    ///
3597    /// The structure expected in `indirect_buffer` must conform to [`DrawIndirect`](crate::util::DrawIndirect).
3598    pub fn draw_indirect(&mut self, indirect_buffer: &'a Buffer, indirect_offset: BufferAddress) {
3599        DynContext::render_pass_draw_indirect(
3600            &*self.parent.context,
3601            &mut self.id,
3602            self.data.as_mut(),
3603            &indirect_buffer.id,
3604            indirect_buffer.data.as_ref(),
3605            indirect_offset,
3606        );
3607    }
3608
3609    /// Draws indexed primitives using the active index buffer and the active vertex buffers,
3610    /// based on the contents of the `indirect_buffer`.
3611    ///
3612    /// The active index buffer can be set with [`RenderPass::set_index_buffer`], while the active
3613    /// vertex buffers can be set with [`RenderPass::set_vertex_buffer`].
3614    ///
3615    /// The structure expected in `indirect_buffer` must conform to [`DrawIndexedIndirect`](crate::util::DrawIndexedIndirect).
3616    pub fn draw_indexed_indirect(
3617        &mut self,
3618        indirect_buffer: &'a Buffer,
3619        indirect_offset: BufferAddress,
3620    ) {
3621        DynContext::render_pass_draw_indexed_indirect(
3622            &*self.parent.context,
3623            &mut self.id,
3624            self.data.as_mut(),
3625            &indirect_buffer.id,
3626            indirect_buffer.data.as_ref(),
3627            indirect_offset,
3628        );
3629    }
3630
3631    /// Execute a [render bundle][RenderBundle], which is a set of pre-recorded commands
3632    /// that can be run together.
3633    pub fn execute_bundles<I: IntoIterator<Item = &'a RenderBundle> + 'a>(
3634        &mut self,
3635        render_bundles: I,
3636    ) {
3637        DynContext::render_pass_execute_bundles(
3638            &*self.parent.context,
3639            &mut self.id,
3640            self.data.as_mut(),
3641            Box::new(
3642                render_bundles
3643                    .into_iter()
3644                    .map(|rb| (&rb.id, rb.data.as_ref())),
3645            ),
3646        )
3647    }
3648}
3649
3650/// [`Features::MULTI_DRAW_INDIRECT`] must be enabled on the device in order to call these functions.
3651impl<'a> RenderPass<'a> {
3652    /// Dispatches multiple draw calls from the active vertex buffer(s) based on the contents of the `indirect_buffer`.
3653    /// `count` draw calls are issued.
3654    ///
3655    /// The active vertex buffers can be set with [`RenderPass::set_vertex_buffer`].
3656    ///
3657    /// The structure expected in `indirect_buffer` must conform to [`DrawIndirect`](crate::util::DrawIndirect).
3658    ///
3659    /// These draw structures are expected to be tightly packed.
3660    pub fn multi_draw_indirect(
3661        &mut self,
3662        indirect_buffer: &'a Buffer,
3663        indirect_offset: BufferAddress,
3664        count: u32,
3665    ) {
3666        DynContext::render_pass_multi_draw_indirect(
3667            &*self.parent.context,
3668            &mut self.id,
3669            self.data.as_mut(),
3670            &indirect_buffer.id,
3671            indirect_buffer.data.as_ref(),
3672            indirect_offset,
3673            count,
3674        );
3675    }
3676
3677    /// Dispatches multiple draw calls from the active index buffer and the active vertex buffers,
3678    /// based on the contents of the `indirect_buffer`. `count` draw calls are issued.
3679    ///
3680    /// The active index buffer can be set with [`RenderPass::set_index_buffer`], while the active
3681    /// vertex buffers can be set with [`RenderPass::set_vertex_buffer`].
3682    ///
3683    /// The structure expected in `indirect_buffer` must conform to [`DrawIndexedIndirect`](crate::util::DrawIndexedIndirect).
3684    ///
3685    /// These draw structures are expected to be tightly packed.
3686    pub fn multi_draw_indexed_indirect(
3687        &mut self,
3688        indirect_buffer: &'a Buffer,
3689        indirect_offset: BufferAddress,
3690        count: u32,
3691    ) {
3692        DynContext::render_pass_multi_draw_indexed_indirect(
3693            &*self.parent.context,
3694            &mut self.id,
3695            self.data.as_mut(),
3696            &indirect_buffer.id,
3697            indirect_buffer.data.as_ref(),
3698            indirect_offset,
3699            count,
3700        );
3701    }
3702}
3703
3704/// [`Features::MULTI_DRAW_INDIRECT_COUNT`] must be enabled on the device in order to call these functions.
3705impl<'a> RenderPass<'a> {
3706    /// Dispatches multiple draw calls from the active vertex buffer(s) based on the contents of the `indirect_buffer`.
3707    /// The count buffer is read to determine how many draws to issue.
3708    ///
3709    /// The indirect buffer must be long enough to account for `max_count` draws, however only `count`
3710    /// draws will be read. If `count` is greater than `max_count`, `max_count` will be used.
3711    ///
3712    /// The active vertex buffers can be set with [`RenderPass::set_vertex_buffer`].
3713    ///
3714    /// The structure expected in `indirect_buffer` must conform to [`DrawIndirect`](crate::util::DrawIndirect).
3715    ///
3716    /// These draw structures are expected to be tightly packed.
3717    ///
3718    /// The structure expected in `count_buffer` is the following:
3719    ///
3720    /// ```rust
3721    /// #[repr(C)]
3722    /// struct DrawIndirectCount {
3723    ///     count: u32, // Number of draw calls to issue.
3724    /// }
3725    /// ```
3726    pub fn multi_draw_indirect_count(
3727        &mut self,
3728        indirect_buffer: &'a Buffer,
3729        indirect_offset: BufferAddress,
3730        count_buffer: &'a Buffer,
3731        count_offset: BufferAddress,
3732        max_count: u32,
3733    ) {
3734        DynContext::render_pass_multi_draw_indirect_count(
3735            &*self.parent.context,
3736            &mut self.id,
3737            self.data.as_mut(),
3738            &indirect_buffer.id,
3739            indirect_buffer.data.as_ref(),
3740            indirect_offset,
3741            &count_buffer.id,
3742            count_buffer.data.as_ref(),
3743            count_offset,
3744            max_count,
3745        );
3746    }
3747
3748    /// Dispatches multiple draw calls from the active index buffer and the active vertex buffers,
3749    /// based on the contents of the `indirect_buffer`. The count buffer is read to determine how many draws to issue.
3750    ///
3751    /// The indirect buffer must be long enough to account for `max_count` draws, however only `count`
3752    /// draws will be read. If `count` is greater than `max_count`, `max_count` will be used.
3753    ///
3754    /// The active index buffer can be set with [`RenderPass::set_index_buffer`], while the active
3755    /// vertex buffers can be set with [`RenderPass::set_vertex_buffer`].
3756    ///
3757    ///
3758    /// The structure expected in `indirect_buffer` must conform to [`DrawIndexedIndirect`](crate::util::DrawIndexedIndirect).
3759    ///
3760    /// These draw structures are expected to be tightly packed.
3761    ///
3762    /// The structure expected in `count_buffer` is the following:
3763    ///
3764    /// ```rust
3765    /// #[repr(C)]
3766    /// struct DrawIndexedIndirectCount {
3767    ///     count: u32, // Number of draw calls to issue.
3768    /// }
3769    /// ```
3770    pub fn multi_draw_indexed_indirect_count(
3771        &mut self,
3772        indirect_buffer: &'a Buffer,
3773        indirect_offset: BufferAddress,
3774        count_buffer: &'a Buffer,
3775        count_offset: BufferAddress,
3776        max_count: u32,
3777    ) {
3778        DynContext::render_pass_multi_draw_indexed_indirect_count(
3779            &*self.parent.context,
3780            &mut self.id,
3781            self.data.as_mut(),
3782            &indirect_buffer.id,
3783            indirect_buffer.data.as_ref(),
3784            indirect_offset,
3785            &count_buffer.id,
3786            count_buffer.data.as_ref(),
3787            count_offset,
3788            max_count,
3789        );
3790    }
3791}
3792
3793/// [`Features::PUSH_CONSTANTS`] must be enabled on the device in order to call these functions.
3794impl<'a> RenderPass<'a> {
3795    /// Set push constant data for subsequent draw calls.
3796    ///
3797    /// Write the bytes in `data` at offset `offset` within push constant
3798    /// storage, all of which are accessible by all the pipeline stages in
3799    /// `stages`, and no others.  Both `offset` and the length of `data` must be
3800    /// multiples of [`PUSH_CONSTANT_ALIGNMENT`], which is always 4.
3801    ///
3802    /// For example, if `offset` is `4` and `data` is eight bytes long, this
3803    /// call will write `data` to bytes `4..12` of push constant storage.
3804    ///
3805    /// # Stage matching
3806    ///
3807    /// Every byte in the affected range of push constant storage must be
3808    /// accessible to exactly the same set of pipeline stages, which must match
3809    /// `stages`. If there are two bytes of storage that are accessible by
3810    /// different sets of pipeline stages - say, one is accessible by fragment
3811    /// shaders, and the other is accessible by both fragment shaders and vertex
3812    /// shaders - then no single `set_push_constants` call may affect both of
3813    /// them; to write both, you must make multiple calls, each with the
3814    /// appropriate `stages` value.
3815    ///
3816    /// Which pipeline stages may access a given byte is determined by the
3817    /// pipeline's [`PushConstant`] global variable and (if it is a struct) its
3818    /// members' offsets.
3819    ///
3820    /// For example, suppose you have twelve bytes of push constant storage,
3821    /// where bytes `0..8` are accessed by the vertex shader, and bytes `4..12`
3822    /// are accessed by the fragment shader. This means there are three byte
3823    /// ranges each accessed by a different set of stages:
3824    ///
3825    /// - Bytes `0..4` are accessed only by the fragment shader.
3826    ///
3827    /// - Bytes `4..8` are accessed by both the fragment shader and the vertex shader.
3828    ///
3829    /// - Bytes `8..12` are accessed only by the vertex shader.
3830    ///
3831    /// To write all twelve bytes requires three `set_push_constants` calls, one
3832    /// for each range, each passing the matching `stages` mask.
3833    ///
3834    /// [`PushConstant`]: https://docs.rs/naga/latest/naga/enum.StorageClass.html#variant.PushConstant
3835    pub fn set_push_constants(&mut self, stages: ShaderStages, offset: u32, data: &[u8]) {
3836        DynContext::render_pass_set_push_constants(
3837            &*self.parent.context,
3838            &mut self.id,
3839            self.data.as_mut(),
3840            stages,
3841            offset,
3842            data,
3843        );
3844    }
3845}
3846
3847/// [`Features::TIMESTAMP_QUERY_INSIDE_PASSES`] must be enabled on the device in order to call these functions.
3848impl<'a> RenderPass<'a> {
3849    /// Issue a timestamp command at this point in the queue. The
3850    /// timestamp will be written to the specified query set, at the specified index.
3851    ///
3852    /// Must be multiplied by [`Queue::get_timestamp_period`] to get
3853    /// the value in nanoseconds. Absolute values have no meaning,
3854    /// but timestamps can be subtracted to get the time it takes
3855    /// for a string of operations to complete.
3856    pub fn write_timestamp(&mut self, query_set: &QuerySet, query_index: u32) {
3857        DynContext::render_pass_write_timestamp(
3858            &*self.parent.context,
3859            &mut self.id,
3860            self.data.as_mut(),
3861            &query_set.id,
3862            query_set.data.as_ref(),
3863            query_index,
3864        )
3865    }
3866}
3867
3868/// [`Features::PIPELINE_STATISTICS_QUERY`] must be enabled on the device in order to call these functions.
3869impl<'a> RenderPass<'a> {
3870    /// Start a pipeline statistics query on this render pass. It can be ended with
3871    /// `end_pipeline_statistics_query`. Pipeline statistics queries may not be nested.
3872    pub fn begin_pipeline_statistics_query(&mut self, query_set: &QuerySet, query_index: u32) {
3873        DynContext::render_pass_begin_pipeline_statistics_query(
3874            &*self.parent.context,
3875            &mut self.id,
3876            self.data.as_mut(),
3877            &query_set.id,
3878            query_set.data.as_ref(),
3879            query_index,
3880        );
3881    }
3882
3883    /// End the pipeline statistics query on this render pass. It can be started with
3884    /// `begin_pipeline_statistics_query`. Pipeline statistics queries may not be nested.
3885    pub fn end_pipeline_statistics_query(&mut self) {
3886        DynContext::render_pass_end_pipeline_statistics_query(
3887            &*self.parent.context,
3888            &mut self.id,
3889            self.data.as_mut(),
3890        );
3891    }
3892}
3893
3894impl<'a> Drop for RenderPass<'a> {
3895    fn drop(&mut self) {
3896        if !thread::panicking() {
3897            let parent_id = self.parent.id.as_ref().unwrap();
3898            self.parent.context.command_encoder_end_render_pass(
3899                parent_id,
3900                self.parent.data.as_ref(),
3901                &mut self.id,
3902                self.data.as_mut(),
3903            );
3904        }
3905    }
3906}
3907
3908impl<'a> ComputePass<'a> {
3909    /// Sets the active bind group for a given bind group index. The bind group layout
3910    /// in the active pipeline when the `dispatch()` function is called must match the layout of this bind group.
3911    ///
3912    /// If the bind group have dynamic offsets, provide them in the binding order.
3913    /// These offsets have to be aligned to [`Limits::min_uniform_buffer_offset_alignment`]
3914    /// or [`Limits::min_storage_buffer_offset_alignment`] appropriately.
3915    pub fn set_bind_group(
3916        &mut self,
3917        index: u32,
3918        bind_group: &'a BindGroup,
3919        offsets: &[DynamicOffset],
3920    ) {
3921        DynContext::compute_pass_set_bind_group(
3922            &*self.parent.context,
3923            &mut self.id,
3924            self.data.as_mut(),
3925            index,
3926            &bind_group.id,
3927            bind_group.data.as_ref(),
3928            offsets,
3929        );
3930    }
3931
3932    /// Sets the active compute pipeline.
3933    pub fn set_pipeline(&mut self, pipeline: &'a ComputePipeline) {
3934        DynContext::compute_pass_set_pipeline(
3935            &*self.parent.context,
3936            &mut self.id,
3937            self.data.as_mut(),
3938            &pipeline.id,
3939            pipeline.data.as_ref(),
3940        );
3941    }
3942
3943    /// Inserts debug marker.
3944    pub fn insert_debug_marker(&mut self, label: &str) {
3945        DynContext::compute_pass_insert_debug_marker(
3946            &*self.parent.context,
3947            &mut self.id,
3948            self.data.as_mut(),
3949            label,
3950        );
3951    }
3952
3953    /// Start record commands and group it into debug marker group.
3954    pub fn push_debug_group(&mut self, label: &str) {
3955        DynContext::compute_pass_push_debug_group(
3956            &*self.parent.context,
3957            &mut self.id,
3958            self.data.as_mut(),
3959            label,
3960        );
3961    }
3962
3963    /// Stops command recording and creates debug group.
3964    pub fn pop_debug_group(&mut self) {
3965        DynContext::compute_pass_pop_debug_group(
3966            &*self.parent.context,
3967            &mut self.id,
3968            self.data.as_mut(),
3969        );
3970    }
3971
3972    /// Dispatches compute work operations.
3973    ///
3974    /// `x`, `y` and `z` denote the number of work groups to dispatch in each dimension.
3975    pub fn dispatch_workgroups(&mut self, x: u32, y: u32, z: u32) {
3976        DynContext::compute_pass_dispatch_workgroups(
3977            &*self.parent.context,
3978            &mut self.id,
3979            self.data.as_mut(),
3980            x,
3981            y,
3982            z,
3983        );
3984    }
3985
3986    /// Dispatches compute work operations, based on the contents of the `indirect_buffer`.
3987    ///
3988    /// The structure expected in `indirect_buffer` must conform to [`DispatchIndirect`](crate::util::DispatchIndirect).
3989    pub fn dispatch_workgroups_indirect(
3990        &mut self,
3991        indirect_buffer: &'a Buffer,
3992        indirect_offset: BufferAddress,
3993    ) {
3994        DynContext::compute_pass_dispatch_workgroups_indirect(
3995            &*self.parent.context,
3996            &mut self.id,
3997            self.data.as_mut(),
3998            &indirect_buffer.id,
3999            indirect_buffer.data.as_ref(),
4000            indirect_offset,
4001        );
4002    }
4003}
4004
4005/// [`Features::PUSH_CONSTANTS`] must be enabled on the device in order to call these functions.
4006impl<'a> ComputePass<'a> {
4007    /// Set push constant data for subsequent dispatch calls.
4008    ///
4009    /// Write the bytes in `data` at offset `offset` within push constant
4010    /// storage.  Both `offset` and the length of `data` must be
4011    /// multiples of [`PUSH_CONSTANT_ALIGNMENT`], which is always 4.
4012    ///
4013    /// For example, if `offset` is `4` and `data` is eight bytes long, this
4014    /// call will write `data` to bytes `4..12` of push constant storage.
4015    pub fn set_push_constants(&mut self, offset: u32, data: &[u8]) {
4016        DynContext::compute_pass_set_push_constants(
4017            &*self.parent.context,
4018            &mut self.id,
4019            self.data.as_mut(),
4020            offset,
4021            data,
4022        );
4023    }
4024}
4025
4026/// [`Features::TIMESTAMP_QUERY_INSIDE_PASSES`] must be enabled on the device in order to call these functions.
4027impl<'a> ComputePass<'a> {
4028    /// Issue a timestamp command at this point in the queue. The timestamp will be written to the specified query set, at the specified index.
4029    ///
4030    /// Must be multiplied by [`Queue::get_timestamp_period`] to get
4031    /// the value in nanoseconds. Absolute values have no meaning,
4032    /// but timestamps can be subtracted to get the time it takes
4033    /// for a string of operations to complete.
4034    pub fn write_timestamp(&mut self, query_set: &QuerySet, query_index: u32) {
4035        DynContext::compute_pass_write_timestamp(
4036            &*self.parent.context,
4037            &mut self.id,
4038            self.data.as_mut(),
4039            &query_set.id,
4040            query_set.data.as_ref(),
4041            query_index,
4042        )
4043    }
4044}
4045
4046/// [`Features::PIPELINE_STATISTICS_QUERY`] must be enabled on the device in order to call these functions.
4047impl<'a> ComputePass<'a> {
4048    /// Start a pipeline statistics query on this render pass. It can be ended with
4049    /// `end_pipeline_statistics_query`. Pipeline statistics queries may not be nested.
4050    pub fn begin_pipeline_statistics_query(&mut self, query_set: &QuerySet, query_index: u32) {
4051        DynContext::compute_pass_begin_pipeline_statistics_query(
4052            &*self.parent.context,
4053            &mut self.id,
4054            self.data.as_mut(),
4055            &query_set.id,
4056            query_set.data.as_ref(),
4057            query_index,
4058        );
4059    }
4060
4061    /// End the pipeline statistics query on this render pass. It can be started with
4062    /// `begin_pipeline_statistics_query`. Pipeline statistics queries may not be nested.
4063    pub fn end_pipeline_statistics_query(&mut self) {
4064        DynContext::compute_pass_end_pipeline_statistics_query(
4065            &*self.parent.context,
4066            &mut self.id,
4067            self.data.as_mut(),
4068        );
4069    }
4070}
4071
4072impl<'a> Drop for ComputePass<'a> {
4073    fn drop(&mut self) {
4074        if !thread::panicking() {
4075            let parent_id = self.parent.id.as_ref().unwrap();
4076            self.parent.context.command_encoder_end_compute_pass(
4077                parent_id,
4078                self.parent.data.as_ref(),
4079                &mut self.id,
4080                self.data.as_mut(),
4081            );
4082        }
4083    }
4084}
4085
4086impl<'a> RenderBundleEncoder<'a> {
4087    /// Finishes recording and returns a [`RenderBundle`] that can be executed in other render passes.
4088    pub fn finish(self, desc: &RenderBundleDescriptor) -> RenderBundle {
4089        let (id, data) =
4090            DynContext::render_bundle_encoder_finish(&*self.context, self.id, self.data, desc);
4091        RenderBundle {
4092            context: Arc::clone(&self.context),
4093            id,
4094            data,
4095        }
4096    }
4097
4098    /// Sets the active bind group for a given bind group index. The bind group layout
4099    /// in the active pipeline when any `draw()` function is called must match the layout of this bind group.
4100    ///
4101    /// If the bind group have dynamic offsets, provide them in the binding order.
4102    pub fn set_bind_group(
4103        &mut self,
4104        index: u32,
4105        bind_group: &'a BindGroup,
4106        offsets: &[DynamicOffset],
4107    ) {
4108        DynContext::render_bundle_encoder_set_bind_group(
4109            &*self.parent.context,
4110            &mut self.id,
4111            self.data.as_mut(),
4112            index,
4113            &bind_group.id,
4114            bind_group.data.as_ref(),
4115            offsets,
4116        )
4117    }
4118
4119    /// Sets the active render pipeline.
4120    ///
4121    /// Subsequent draw calls will exhibit the behavior defined by `pipeline`.
4122    pub fn set_pipeline(&mut self, pipeline: &'a RenderPipeline) {
4123        DynContext::render_bundle_encoder_set_pipeline(
4124            &*self.parent.context,
4125            &mut self.id,
4126            self.data.as_mut(),
4127            &pipeline.id,
4128            pipeline.data.as_ref(),
4129        )
4130    }
4131
4132    /// Sets the active index buffer.
4133    ///
4134    /// Subsequent calls to [`draw_indexed`](RenderBundleEncoder::draw_indexed) on this [`RenderBundleEncoder`] will
4135    /// use `buffer` as the source index buffer.
4136    pub fn set_index_buffer(&mut self, buffer_slice: BufferSlice<'a>, index_format: IndexFormat) {
4137        DynContext::render_bundle_encoder_set_index_buffer(
4138            &*self.parent.context,
4139            &mut self.id,
4140            self.data.as_mut(),
4141            &buffer_slice.buffer.id,
4142            buffer_slice.buffer.data.as_ref(),
4143            index_format,
4144            buffer_slice.offset,
4145            buffer_slice.size,
4146        )
4147    }
4148
4149    /// Assign a vertex buffer to a slot.
4150    ///
4151    /// Subsequent calls to [`draw`] and [`draw_indexed`] on this
4152    /// [`RenderBundleEncoder`] will use `buffer` as one of the source vertex buffers.
4153    ///
4154    /// The `slot` refers to the index of the matching descriptor in
4155    /// [`VertexState::buffers`].
4156    ///
4157    /// [`draw`]: RenderBundleEncoder::draw
4158    /// [`draw_indexed`]: RenderBundleEncoder::draw_indexed
4159    pub fn set_vertex_buffer(&mut self, slot: u32, buffer_slice: BufferSlice<'a>) {
4160        DynContext::render_bundle_encoder_set_vertex_buffer(
4161            &*self.parent.context,
4162            &mut self.id,
4163            self.data.as_mut(),
4164            slot,
4165            &buffer_slice.buffer.id,
4166            buffer_slice.buffer.data.as_ref(),
4167            buffer_slice.offset,
4168            buffer_slice.size,
4169        )
4170    }
4171
4172    /// Draws primitives from the active vertex buffer(s).
4173    ///
4174    /// The active vertex buffers can be set with [`RenderBundleEncoder::set_vertex_buffer`].
4175    /// Does not use an Index Buffer. If you need this see [`RenderBundleEncoder::draw_indexed`]
4176    ///
4177    /// Panics if vertices Range is outside of the range of the vertices range of any set vertex buffer.
4178    ///
4179    /// vertices: The range of vertices to draw.
4180    /// instances: Range of Instances to draw. Use 0..1 if instance buffers are not used.
4181    /// E.g.of how its used internally
4182    /// ```rust ignore
4183    /// for instance_id in instance_range {
4184    ///     for vertex_id in vertex_range {
4185    ///         let vertex = vertex[vertex_id];
4186    ///         vertex_shader(vertex, vertex_id, instance_id);
4187    ///     }
4188    /// }
4189    /// ```
4190    pub fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>) {
4191        DynContext::render_bundle_encoder_draw(
4192            &*self.parent.context,
4193            &mut self.id,
4194            self.data.as_mut(),
4195            vertices,
4196            instances,
4197        )
4198    }
4199
4200    /// Draws indexed primitives using the active index buffer and the active vertex buffer(s).
4201    ///
4202    /// The active index buffer can be set with [`RenderBundleEncoder::set_index_buffer`].
4203    /// The active vertex buffer(s) can be set with [`RenderBundleEncoder::set_vertex_buffer`].
4204    ///
4205    /// Panics if indices Range is outside of the range of the indices range of any set index buffer.
4206    ///
4207    /// indices: The range of indices to draw.
4208    /// base_vertex: value added to each index value before indexing into the vertex buffers.
4209    /// instances: Range of Instances to draw. Use 0..1 if instance buffers are not used.
4210    /// E.g.of how its used internally
4211    /// ```rust ignore
4212    /// for instance_id in instance_range {
4213    ///     for index_index in index_range {
4214    ///         let vertex_id = index_buffer[index_index];
4215    ///         let adjusted_vertex_id = vertex_id + base_vertex;
4216    ///         let vertex = vertex[adjusted_vertex_id];
4217    ///         vertex_shader(vertex, adjusted_vertex_id, instance_id);
4218    ///     }
4219    /// }
4220    /// ```
4221    pub fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>) {
4222        DynContext::render_bundle_encoder_draw_indexed(
4223            &*self.parent.context,
4224            &mut self.id,
4225            self.data.as_mut(),
4226            indices,
4227            base_vertex,
4228            instances,
4229        );
4230    }
4231
4232    /// Draws primitives from the active vertex buffer(s) based on the contents of the `indirect_buffer`.
4233    ///
4234    /// The active vertex buffers can be set with [`RenderBundleEncoder::set_vertex_buffer`].
4235    ///
4236    /// The structure expected in `indirect_buffer` must conform to [`DrawIndirect`](crate::util::DrawIndirect).
4237    pub fn draw_indirect(&mut self, indirect_buffer: &'a Buffer, indirect_offset: BufferAddress) {
4238        DynContext::render_bundle_encoder_draw_indirect(
4239            &*self.parent.context,
4240            &mut self.id,
4241            self.data.as_mut(),
4242            &indirect_buffer.id,
4243            indirect_buffer.data.as_ref(),
4244            indirect_offset,
4245        );
4246    }
4247
4248    /// Draws indexed primitives using the active index buffer and the active vertex buffers,
4249    /// based on the contents of the `indirect_buffer`.
4250    ///
4251    /// The active index buffer can be set with [`RenderBundleEncoder::set_index_buffer`], while the active
4252    /// vertex buffers can be set with [`RenderBundleEncoder::set_vertex_buffer`].
4253    ///
4254    /// The structure expected in `indirect_buffer` must conform to [`DrawIndexedIndirect`](crate::util::DrawIndexedIndirect).
4255    pub fn draw_indexed_indirect(
4256        &mut self,
4257        indirect_buffer: &'a Buffer,
4258        indirect_offset: BufferAddress,
4259    ) {
4260        DynContext::render_bundle_encoder_draw_indexed_indirect(
4261            &*self.parent.context,
4262            &mut self.id,
4263            self.data.as_mut(),
4264            &indirect_buffer.id,
4265            indirect_buffer.data.as_ref(),
4266            indirect_offset,
4267        );
4268    }
4269}
4270
4271/// [`Features::PUSH_CONSTANTS`] must be enabled on the device in order to call these functions.
4272impl<'a> RenderBundleEncoder<'a> {
4273    /// Set push constant data.
4274    ///
4275    /// Offset is measured in bytes, but must be a multiple of [`PUSH_CONSTANT_ALIGNMENT`].
4276    ///
4277    /// Data size must be a multiple of 4 and must have an alignment of 4.
4278    /// For example, with an offset of 4 and an array of `[u8; 8]`, that will write to the range
4279    /// of 4..12.
4280    ///
4281    /// For each byte in the range of push constant data written, the union of the stages of all push constant
4282    /// ranges that covers that byte must be exactly `stages`. There's no good way of explaining this simply,
4283    /// so here are some examples:
4284    ///
4285    /// ```text
4286    /// For the given ranges:
4287    /// - 0..4 Vertex
4288    /// - 4..8 Fragment
4289    /// ```
4290    ///
4291    /// You would need to upload this in two set_push_constants calls. First for the `Vertex` range, second for the `Fragment` range.
4292    ///
4293    /// ```text
4294    /// For the given ranges:
4295    /// - 0..8  Vertex
4296    /// - 4..12 Fragment
4297    /// ```
4298    ///
4299    /// You would need to upload this in three set_push_constants calls. First for the `Vertex` only range 0..4, second
4300    /// for the `Vertex | Fragment` range 4..8, third for the `Fragment` range 8..12.
4301    pub fn set_push_constants(&mut self, stages: ShaderStages, offset: u32, data: &[u8]) {
4302        DynContext::render_bundle_encoder_set_push_constants(
4303            &*self.parent.context,
4304            &mut self.id,
4305            self.data.as_mut(),
4306            stages,
4307            offset,
4308            data,
4309        );
4310    }
4311}
4312
4313/// A read-only view into a staging buffer.
4314///
4315/// Reading into this buffer won't yield the contents of the buffer from the
4316/// GPU and is likely to be slow. Because of this, although [`AsMut`] is
4317/// implemented for this type, [`AsRef`] is not.
4318pub struct QueueWriteBufferView<'a> {
4319    queue: &'a Queue,
4320    buffer: &'a Buffer,
4321    offset: BufferAddress,
4322    inner: Box<dyn context::QueueWriteBuffer>,
4323}
4324#[cfg(any(
4325    not(target_arch = "wasm32"),
4326    all(
4327        feature = "fragile-send-sync-non-atomic-wasm",
4328        not(target_feature = "atomics")
4329    )
4330))]
4331static_assertions::assert_impl_all!(QueueWriteBufferView: Send, Sync);
4332
4333impl Deref for QueueWriteBufferView<'_> {
4334    type Target = [u8];
4335
4336    fn deref(&self) -> &Self::Target {
4337        log::warn!("Reading from a QueueWriteBufferView won't yield the contents of the buffer and may be slow.");
4338        self.inner.slice()
4339    }
4340}
4341
4342impl DerefMut for QueueWriteBufferView<'_> {
4343    fn deref_mut(&mut self) -> &mut Self::Target {
4344        self.inner.slice_mut()
4345    }
4346}
4347
4348impl<'a> AsMut<[u8]> for QueueWriteBufferView<'a> {
4349    fn as_mut(&mut self) -> &mut [u8] {
4350        self.inner.slice_mut()
4351    }
4352}
4353
4354impl<'a> Drop for QueueWriteBufferView<'a> {
4355    fn drop(&mut self) {
4356        DynContext::queue_write_staging_buffer(
4357            &*self.queue.context,
4358            &self.queue.id,
4359            self.queue.data.as_ref(),
4360            &self.buffer.id,
4361            self.buffer.data.as_ref(),
4362            self.offset,
4363            &*self.inner,
4364        );
4365    }
4366}
4367
4368impl Queue {
4369    /// Schedule a data write into `buffer` starting at `offset`.
4370    ///
4371    /// This method is intended to have low performance costs.
4372    /// As such, the write is not immediately submitted, and instead enqueued
4373    /// internally to happen at the start of the next `submit()` call.
4374    ///
4375    /// This method fails if `data` overruns the size of `buffer` starting at `offset`.
4376    pub fn write_buffer(&self, buffer: &Buffer, offset: BufferAddress, data: &[u8]) {
4377        DynContext::queue_write_buffer(
4378            &*self.context,
4379            &self.id,
4380            self.data.as_ref(),
4381            &buffer.id,
4382            buffer.data.as_ref(),
4383            offset,
4384            data,
4385        )
4386    }
4387
4388    /// Schedule a data write into `buffer` starting at `offset` via the returned
4389    /// [`QueueWriteBufferView`].
4390    ///
4391    /// Reading from this buffer is slow and will not yield the actual contents of the buffer.
4392    ///
4393    /// This method is intended to have low performance costs.
4394    /// As such, the write is not immediately submitted, and instead enqueued
4395    /// internally to happen at the start of the next `submit()` call.
4396    ///
4397    /// This method fails if `size` is greater than the size of `buffer` starting at `offset`.
4398    #[must_use]
4399    pub fn write_buffer_with<'a>(
4400        &'a self,
4401        buffer: &'a Buffer,
4402        offset: BufferAddress,
4403        size: BufferSize,
4404    ) -> Option<QueueWriteBufferView<'a>> {
4405        profiling::scope!("Queue::write_buffer_with");
4406        DynContext::queue_validate_write_buffer(
4407            &*self.context,
4408            &self.id,
4409            self.data.as_ref(),
4410            &buffer.id,
4411            buffer.data.as_ref(),
4412            offset,
4413            size,
4414        )?;
4415        let staging_buffer = DynContext::queue_create_staging_buffer(
4416            &*self.context,
4417            &self.id,
4418            self.data.as_ref(),
4419            size,
4420        )?;
4421        Some(QueueWriteBufferView {
4422            queue: self,
4423            buffer,
4424            offset,
4425            inner: staging_buffer,
4426        })
4427    }
4428
4429    /// Schedule a write of some data into a texture.
4430    ///
4431    /// * `data` contains the texels to be written, which must be in
4432    ///   [the same format as the texture](TextureFormat).
4433    /// * `data_layout` describes the memory layout of `data`, which does not necessarily
4434    ///   have to have tightly packed rows.
4435    /// * `texture` specifies the texture to write into, and the location within the
4436    ///   texture (coordinate offset, mip level) that will be overwritten.
4437    /// * `size` is the size, in texels, of the region to be written.
4438    ///
4439    /// This method is intended to have low performance costs.
4440    /// As such, the write is not immediately submitted, and instead enqueued
4441    /// internally to happen at the start of the next `submit()` call.
4442    /// However, `data` will be immediately copied into staging memory; so the caller may
4443    /// discard it any time after this call completes.
4444    ///
4445    /// This method fails if `size` overruns the size of `texture`, or if `data` is too short.
4446    pub fn write_texture(
4447        &self,
4448        texture: ImageCopyTexture,
4449        data: &[u8],
4450        data_layout: ImageDataLayout,
4451        size: Extent3d,
4452    ) {
4453        DynContext::queue_write_texture(
4454            &*self.context,
4455            &self.id,
4456            self.data.as_ref(),
4457            texture,
4458            data,
4459            data_layout,
4460            size,
4461        )
4462    }
4463
4464    /// Schedule a copy of data from `image` into `texture`.
4465    #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
4466    pub fn copy_external_image_to_texture(
4467        &self,
4468        source: &wgt::ImageCopyExternalImage,
4469        dest: ImageCopyTextureTagged,
4470        size: Extent3d,
4471    ) {
4472        DynContext::queue_copy_external_image_to_texture(
4473            &*self.context,
4474            &self.id,
4475            self.data.as_ref(),
4476            source,
4477            dest,
4478            size,
4479        )
4480    }
4481
4482    /// Submits a series of finished command buffers for execution.
4483    pub fn submit<I: IntoIterator<Item = CommandBuffer>>(
4484        &self,
4485        command_buffers: I,
4486    ) -> SubmissionIndex {
4487        let (raw, data) = DynContext::queue_submit(
4488            &*self.context,
4489            &self.id,
4490            self.data.as_ref(),
4491            Box::new(
4492                command_buffers
4493                    .into_iter()
4494                    .map(|mut comb| (comb.id.take().unwrap(), comb.data.take().unwrap())),
4495            ),
4496        );
4497
4498        SubmissionIndex(raw, data)
4499    }
4500
4501    /// Gets the amount of nanoseconds each tick of a timestamp query represents.
4502    ///
4503    /// Returns zero if timestamp queries are unsupported.
4504    pub fn get_timestamp_period(&self) -> f32 {
4505        DynContext::queue_get_timestamp_period(&*self.context, &self.id, self.data.as_ref())
4506    }
4507
4508    /// Registers a callback when the previous call to submit finishes running on the gpu. This callback
4509    /// being called implies that all mapped buffer callbacks attached to the same submission have also
4510    /// been called.
4511    ///
4512    /// For the callback to complete, either `queue.submit(..)`, `instance.poll_all(..)`, or `device.poll(..)`
4513    /// must be called elsewhere in the runtime, possibly integrated into an event loop or run on a separate thread.
4514    ///
4515    /// The callback will be called on the thread that first calls the above functions after the gpu work
4516    /// has completed. There are no restrictions on the code you can run in the callback, however on native the
4517    /// call to the function will not complete until the callback returns, so prefer keeping callbacks short
4518    /// and used to set flags, send messages, etc.
4519    pub fn on_submitted_work_done(&self, callback: impl FnOnce() + Send + 'static) {
4520        DynContext::queue_on_submitted_work_done(
4521            &*self.context,
4522            &self.id,
4523            self.data.as_ref(),
4524            Box::new(callback),
4525        )
4526    }
4527}
4528
4529impl SurfaceTexture {
4530    /// Schedule this texture to be presented on the owning surface.
4531    ///
4532    /// Needs to be called after any work on the texture is scheduled via [`Queue::submit`].
4533    pub fn present(mut self) {
4534        self.presented = true;
4535        DynContext::surface_present(
4536            &*self.texture.context,
4537            &self.texture.id,
4538            // This call to as_ref is essential because we want the DynContext implementation to see the inner
4539            // value of the Box (T::SurfaceOutputDetail), not the Box itself.
4540            self.detail.as_ref(),
4541        );
4542    }
4543}
4544
4545impl Drop for SurfaceTexture {
4546    fn drop(&mut self) {
4547        if !self.presented && !thread::panicking() {
4548            DynContext::surface_texture_discard(
4549                &*self.texture.context,
4550                &self.texture.id,
4551                // This call to as_ref is essential because we want the DynContext implementation to see the inner
4552                // value of the Box (T::SurfaceOutputDetail), not the Box itself.
4553                self.detail.as_ref(),
4554            );
4555        }
4556    }
4557}
4558
4559impl Surface {
4560    /// Returns the capabilities of the surface when used with the given adapter.
4561    ///
4562    /// Returns specified values (see [`SurfaceCapabilities`]) if surface is incompatible with the adapter.
4563    pub fn get_capabilities(&self, adapter: &Adapter) -> SurfaceCapabilities {
4564        DynContext::surface_get_capabilities(
4565            &*self.context,
4566            &self.id,
4567            self.data.as_ref(),
4568            &adapter.id,
4569            adapter.data.as_ref(),
4570        )
4571    }
4572
4573    /// Return a default `SurfaceConfiguration` from width and height to use for the [`Surface`] with this adapter.
4574    ///
4575    /// Returns None if the surface isn't supported by this adapter
4576    pub fn get_default_config(
4577        &self,
4578        adapter: &Adapter,
4579        width: u32,
4580        height: u32,
4581    ) -> Option<SurfaceConfiguration> {
4582        let caps = self.get_capabilities(adapter);
4583        Some(SurfaceConfiguration {
4584            usage: wgt::TextureUsages::RENDER_ATTACHMENT,
4585            format: *caps.formats.get(0)?,
4586            width,
4587            height,
4588            present_mode: *caps.present_modes.get(0)?,
4589            alpha_mode: wgt::CompositeAlphaMode::Auto,
4590            view_formats: vec![],
4591        })
4592    }
4593
4594    /// Initializes [`Surface`] for presentation.
4595    ///
4596    /// # Panics
4597    ///
4598    /// - A old [`SurfaceTexture`] is still alive referencing an old surface.
4599    /// - Texture format requested is unsupported on the surface.
4600    pub fn configure(&self, device: &Device, config: &SurfaceConfiguration) {
4601        DynContext::surface_configure(
4602            &*self.context,
4603            &self.id,
4604            self.data.as_ref(),
4605            &device.id,
4606            device.data.as_ref(),
4607            config,
4608        );
4609
4610        let mut conf = self.config.lock();
4611        *conf = Some(config.clone());
4612    }
4613
4614    /// Returns the next texture to be presented by the swapchain for drawing.
4615    ///
4616    /// In order to present the [`SurfaceTexture`] returned by this method,
4617    /// first a [`Queue::submit`] needs to be done with some work rendering to this texture.
4618    /// Then [`SurfaceTexture::present`] needs to be called.
4619    ///
4620    /// If a SurfaceTexture referencing this surface is alive when the swapchain is recreated,
4621    /// recreating the swapchain will panic.
4622    pub fn get_current_texture(&self) -> Result<SurfaceTexture, SurfaceError> {
4623        let (texture_id, texture_data, status, detail) =
4624            DynContext::surface_get_current_texture(&*self.context, &self.id, self.data.as_ref());
4625
4626        let suboptimal = match status {
4627            SurfaceStatus::Good => false,
4628            SurfaceStatus::Suboptimal => true,
4629            SurfaceStatus::Timeout => return Err(SurfaceError::Timeout),
4630            SurfaceStatus::Outdated => return Err(SurfaceError::Outdated),
4631            SurfaceStatus::Lost => return Err(SurfaceError::Lost),
4632        };
4633
4634        let guard = self.config.lock();
4635        let config = guard
4636            .as_ref()
4637            .expect("This surface has not been configured yet.");
4638
4639        let descriptor = TextureDescriptor {
4640            label: None,
4641            size: Extent3d {
4642                width: config.width,
4643                height: config.height,
4644                depth_or_array_layers: 1,
4645            },
4646            format: config.format,
4647            usage: config.usage,
4648            mip_level_count: 1,
4649            sample_count: 1,
4650            dimension: TextureDimension::D2,
4651            view_formats: &[],
4652        };
4653
4654        texture_id
4655            .zip(texture_data)
4656            .map(|(id, data)| SurfaceTexture {
4657                texture: Texture {
4658                    context: Arc::clone(&self.context),
4659                    id,
4660                    data,
4661                    owned: false,
4662                    descriptor,
4663                },
4664                suboptimal,
4665                presented: false,
4666                detail,
4667            })
4668            .ok_or(SurfaceError::Lost)
4669    }
4670
4671    /// Returns the inner hal Surface using a callback. The hal surface will be `None` if the
4672    /// backend type argument does not match with this wgpu Surface
4673    ///
4674    /// # Safety
4675    ///
4676    /// - The raw handle obtained from the hal Surface must not be manually destroyed
4677    #[cfg(any(
4678        not(target_arch = "wasm32"),
4679        target_os = "emscripten",
4680        feature = "webgl"
4681    ))]
4682    pub unsafe fn as_hal_mut<
4683        A: wgc::hal_api::HalApi,
4684        F: FnOnce(Option<&mut A::Surface>) -> R,
4685        R,
4686    >(
4687        &mut self,
4688        hal_surface_callback: F,
4689    ) -> R {
4690        unsafe {
4691            self.context
4692                .as_any()
4693                .downcast_ref::<crate::backend::Context>()
4694                .unwrap()
4695                .surface_as_hal_mut::<A, F, R>(
4696                    self.data.downcast_ref().unwrap(),
4697                    hal_surface_callback,
4698                )
4699        }
4700    }
4701}
4702
4703/// Opaque globally-unique identifier
4704#[cfg(feature = "expose-ids")]
4705#[cfg_attr(docsrs, doc(cfg(feature = "expose-ids")))]
4706#[repr(transparent)]
4707pub struct Id<T>(::core::num::NonZeroU64, std::marker::PhantomData<*mut T>);
4708
4709// SAFETY: `Id` is a bare `NonZeroU64`, the type parameter is a marker purely to avoid confusing Ids
4710// returned for different types , so `Id` can safely implement Send and Sync.
4711#[cfg(feature = "expose-ids")]
4712unsafe impl<T> Send for Id<T> {}
4713
4714// SAFETY: See the implementation for `Send`.
4715#[cfg(feature = "expose-ids")]
4716unsafe impl<T> Sync for Id<T> {}
4717
4718#[cfg(feature = "expose-ids")]
4719impl<T> Clone for Id<T> {
4720    fn clone(&self) -> Self {
4721        *self
4722    }
4723}
4724
4725#[cfg(feature = "expose-ids")]
4726impl<T> Copy for Id<T> {}
4727
4728#[cfg(feature = "expose-ids")]
4729impl<T> Debug for Id<T> {
4730    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
4731        f.debug_tuple("Id").field(&self.0).finish()
4732    }
4733}
4734
4735#[cfg(feature = "expose-ids")]
4736impl<T> PartialEq for Id<T> {
4737    fn eq(&self, other: &Id<T>) -> bool {
4738        self.0 == other.0
4739    }
4740}
4741
4742#[cfg(feature = "expose-ids")]
4743impl<T> Eq for Id<T> {}
4744
4745#[cfg(feature = "expose-ids")]
4746impl<T> std::hash::Hash for Id<T> {
4747    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
4748        self.0.hash(state)
4749    }
4750}
4751
4752#[cfg(feature = "expose-ids")]
4753impl Adapter {
4754    /// Returns a globally-unique identifier for this `Adapter`.
4755    ///
4756    /// Calling this method multiple times on the same object will always return the same value.
4757    /// The returned value is guaranteed to be unique among all `Adapter`s created from the same
4758    /// `Instance`.
4759    #[cfg_attr(docsrs, doc(cfg(feature = "expose-ids")))]
4760    pub fn global_id(&self) -> Id<Adapter> {
4761        Id(self.id.global_id(), std::marker::PhantomData)
4762    }
4763}
4764
4765#[cfg(feature = "expose-ids")]
4766impl Device {
4767    /// Returns a globally-unique identifier for this `Device`.
4768    ///
4769    /// Calling this method multiple times on the same object will always return the same value.
4770    /// The returned value is guaranteed to be unique among all `Device`s created from the same
4771    /// `Instance`.
4772    #[cfg_attr(docsrs, doc(cfg(feature = "expose-ids")))]
4773    pub fn global_id(&self) -> Id<Device> {
4774        Id(self.id.global_id(), std::marker::PhantomData)
4775    }
4776}
4777
4778#[cfg(feature = "expose-ids")]
4779impl Queue {
4780    /// Returns a globally-unique identifier for this `Queue`.
4781    ///
4782    /// Calling this method multiple times on the same object will always return the same value.
4783    /// The returned value is guaranteed to be unique among all `Queue`s created from the same
4784    /// `Instance`.
4785    #[cfg_attr(docsrs, doc(cfg(feature = "expose-ids")))]
4786    pub fn global_id(&self) -> Id<Queue> {
4787        Id(self.id.global_id(), std::marker::PhantomData)
4788    }
4789}
4790
4791#[cfg(feature = "expose-ids")]
4792impl ShaderModule {
4793    /// Returns a globally-unique identifier for this `ShaderModule`.
4794    ///
4795    /// Calling this method multiple times on the same object will always return the same value.
4796    /// The returned value is guaranteed to be unique among all `ShaderModule`s created from the same
4797    /// `Instance`.
4798    #[cfg_attr(docsrs, doc(cfg(feature = "expose-ids")))]
4799    pub fn global_id(&self) -> Id<ShaderModule> {
4800        Id(self.id.global_id(), std::marker::PhantomData)
4801    }
4802}
4803
4804#[cfg(feature = "expose-ids")]
4805impl BindGroupLayout {
4806    /// Returns a globally-unique identifier for this `BindGroupLayout`.
4807    ///
4808    /// Calling this method multiple times on the same object will always return the same value.
4809    /// The returned value is guaranteed to be unique among all `BindGroupLayout`s created from the same
4810    /// `Instance`.
4811    #[cfg_attr(docsrs, doc(cfg(feature = "expose-ids")))]
4812    pub fn global_id(&self) -> Id<BindGroupLayout> {
4813        Id(self.id.global_id(), std::marker::PhantomData)
4814    }
4815}
4816
4817#[cfg(feature = "expose-ids")]
4818impl BindGroup {
4819    /// Returns a globally-unique identifier for this `BindGroup`.
4820    ///
4821    /// Calling this method multiple times on the same object will always return the same value.
4822    /// The returned value is guaranteed to be unique among all `BindGroup`s created from the same
4823    /// `Instance`.
4824    #[cfg_attr(docsrs, doc(cfg(feature = "expose-ids")))]
4825    pub fn global_id(&self) -> Id<BindGroup> {
4826        Id(self.id.global_id(), std::marker::PhantomData)
4827    }
4828}
4829
4830#[cfg(feature = "expose-ids")]
4831impl TextureView {
4832    /// Returns a globally-unique identifier for this `TextureView`.
4833    ///
4834    /// Calling this method multiple times on the same object will always return the same value.
4835    /// The returned value is guaranteed to be unique among all `TextureView`s created from the same
4836    /// `Instance`.
4837    #[cfg_attr(docsrs, doc(cfg(feature = "expose-ids")))]
4838    pub fn global_id(&self) -> Id<TextureView> {
4839        Id(self.id.global_id(), std::marker::PhantomData)
4840    }
4841}
4842
4843#[cfg(feature = "expose-ids")]
4844impl Sampler {
4845    /// Returns a globally-unique identifier for this `Sampler`.
4846    ///
4847    /// Calling this method multiple times on the same object will always return the same value.
4848    /// The returned value is guaranteed to be unique among all `Sampler`s created from the same
4849    /// `Instance`.
4850    #[cfg_attr(docsrs, doc(cfg(feature = "expose-ids")))]
4851    pub fn global_id(&self) -> Id<Sampler> {
4852        Id(self.id.global_id(), std::marker::PhantomData)
4853    }
4854}
4855
4856#[cfg(feature = "expose-ids")]
4857impl Buffer {
4858    /// Returns a globally-unique identifier for this `Buffer`.
4859    ///
4860    /// Calling this method multiple times on the same object will always return the same value.
4861    /// The returned value is guaranteed to be unique among all `Buffer`s created from the same
4862    /// `Instance`.
4863    #[cfg_attr(docsrs, doc(cfg(feature = "expose-ids")))]
4864    pub fn global_id(&self) -> Id<Buffer> {
4865        Id(self.id.global_id(), std::marker::PhantomData)
4866    }
4867}
4868
4869#[cfg(feature = "expose-ids")]
4870impl Texture {
4871    /// Returns a globally-unique identifier for this `Texture`.
4872    ///
4873    /// Calling this method multiple times on the same object will always return the same value.
4874    /// The returned value is guaranteed to be unique among all `Texture`s created from the same
4875    /// `Instance`.
4876    #[cfg_attr(docsrs, doc(cfg(feature = "expose-ids")))]
4877    pub fn global_id(&self) -> Id<Texture> {
4878        Id(self.id.global_id(), std::marker::PhantomData)
4879    }
4880}
4881
4882#[cfg(feature = "expose-ids")]
4883impl QuerySet {
4884    /// Returns a globally-unique identifier for this `QuerySet`.
4885    ///
4886    /// Calling this method multiple times on the same object will always return the same value.
4887    /// The returned value is guaranteed to be unique among all `QuerySet`s created from the same
4888    /// `Instance`.
4889    #[cfg_attr(docsrs, doc(cfg(feature = "expose-ids")))]
4890    pub fn global_id(&self) -> Id<QuerySet> {
4891        Id(self.id.global_id(), std::marker::PhantomData)
4892    }
4893}
4894
4895#[cfg(feature = "expose-ids")]
4896impl PipelineLayout {
4897    /// Returns a globally-unique identifier for this `PipelineLayout`.
4898    ///
4899    /// Calling this method multiple times on the same object will always return the same value.
4900    /// The returned value is guaranteed to be unique among all `PipelineLayout`s created from the same
4901    /// `Instance`.
4902    #[cfg_attr(docsrs, doc(cfg(feature = "expose-ids")))]
4903    pub fn global_id(&self) -> Id<PipelineLayout> {
4904        Id(self.id.global_id(), std::marker::PhantomData)
4905    }
4906}
4907
4908#[cfg(feature = "expose-ids")]
4909impl RenderPipeline {
4910    /// Returns a globally-unique identifier for this `RenderPipeline`.
4911    ///
4912    /// Calling this method multiple times on the same object will always return the same value.
4913    /// The returned value is guaranteed to be unique among all `RenderPipeline`s created from the same
4914    /// `Instance`.
4915    #[cfg_attr(docsrs, doc(cfg(feature = "expose-ids")))]
4916    pub fn global_id(&self) -> Id<RenderPipeline> {
4917        Id(self.id.global_id(), std::marker::PhantomData)
4918    }
4919}
4920
4921#[cfg(feature = "expose-ids")]
4922impl ComputePipeline {
4923    /// Returns a globally-unique identifier for this `ComputePipeline`.
4924    ///
4925    /// Calling this method multiple times on the same object will always return the same value.
4926    /// The returned value is guaranteed to be unique among all `ComputePipeline`s created from the same
4927    /// `Instance`.
4928    #[cfg_attr(docsrs, doc(cfg(feature = "expose-ids")))]
4929    pub fn global_id(&self) -> Id<ComputePipeline> {
4930        Id(self.id.global_id(), std::marker::PhantomData)
4931    }
4932}
4933
4934#[cfg(feature = "expose-ids")]
4935impl RenderBundle {
4936    /// Returns a globally-unique identifier for this `RenderBundle`.
4937    ///
4938    /// Calling this method multiple times on the same object will always return the same value.
4939    /// The returned value is guaranteed to be unique among all `RenderBundle`s created from the same
4940    /// `Instance`.
4941    #[cfg_attr(docsrs, doc(cfg(feature = "expose-ids")))]
4942    pub fn global_id(&self) -> Id<RenderBundle> {
4943        Id(self.id.global_id(), std::marker::PhantomData)
4944    }
4945}
4946
4947#[cfg(feature = "expose-ids")]
4948impl Surface {
4949    /// Returns a globally-unique identifier for this `Surface`.
4950    ///
4951    /// Calling this method multiple times on the same object will always return the same value.
4952    /// The returned value is guaranteed to be unique among all `Surface`s created from the same
4953    /// `Instance`.
4954    #[cfg_attr(docsrs, doc(cfg(feature = "expose-ids")))]
4955    pub fn global_id(&self) -> Id<Surface> {
4956        Id(self.id.global_id(), std::marker::PhantomData)
4957    }
4958}
4959
4960/// Type for the callback of uncaptured error handler
4961pub trait UncapturedErrorHandler: Fn(Error) + Send + 'static {}
4962impl<T> UncapturedErrorHandler for T where T: Fn(Error) + Send + 'static {}
4963
4964/// Error type
4965#[derive(Debug)]
4966pub enum Error {
4967    /// Out of memory error
4968    OutOfMemory {
4969        /// Lower level source of the error.
4970        #[cfg(any(
4971            not(target_arch = "wasm32"),
4972            all(
4973                feature = "fragile-send-sync-non-atomic-wasm",
4974                not(target_feature = "atomics")
4975            )
4976        ))]
4977        source: Box<dyn error::Error + Send + 'static>,
4978        /// Lower level source of the error.
4979        #[cfg(not(any(
4980            not(target_arch = "wasm32"),
4981            all(
4982                feature = "fragile-send-sync-non-atomic-wasm",
4983                not(target_feature = "atomics")
4984            )
4985        )))]
4986        source: Box<dyn error::Error + 'static>,
4987    },
4988    /// Validation error, signifying a bug in code or data
4989    Validation {
4990        /// Lower level source of the error.
4991        #[cfg(any(
4992            not(target_arch = "wasm32"),
4993            all(
4994                feature = "fragile-send-sync-non-atomic-wasm",
4995                not(target_feature = "atomics")
4996            )
4997        ))]
4998        source: Box<dyn error::Error + Send + 'static>,
4999        /// Lower level source of the error.
5000        #[cfg(not(any(
5001            not(target_arch = "wasm32"),
5002            all(
5003                feature = "fragile-send-sync-non-atomic-wasm",
5004                not(target_feature = "atomics")
5005            )
5006        )))]
5007        source: Box<dyn error::Error + 'static>,
5008        /// Description of the validation error.
5009        description: String,
5010    },
5011}
5012#[cfg(any(
5013    not(target_arch = "wasm32"),
5014    all(
5015        feature = "fragile-send-sync-non-atomic-wasm",
5016        not(target_feature = "atomics")
5017    )
5018))]
5019static_assertions::assert_impl_all!(Error: Send);
5020
5021impl error::Error for Error {
5022    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
5023        match self {
5024            Error::OutOfMemory { source } => Some(source.as_ref()),
5025            Error::Validation { source, .. } => Some(source.as_ref()),
5026        }
5027    }
5028}
5029
5030impl Display for Error {
5031    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5032        match self {
5033            Error::OutOfMemory { .. } => f.write_str("Out of Memory"),
5034            Error::Validation { description, .. } => f.write_str(description),
5035        }
5036    }
5037}
5038
5039use send_sync::*;
5040
5041mod send_sync {
5042    use std::any::Any;
5043    use std::fmt;
5044
5045    use wgt::{WasmNotSend, WasmNotSync};
5046
5047    pub trait AnyWasmNotSendSync: Any + WasmNotSend + WasmNotSync {
5048        fn upcast_any_ref(&self) -> &dyn Any;
5049    }
5050    impl<T: Any + WasmNotSend + WasmNotSync> AnyWasmNotSendSync for T {
5051        #[inline]
5052        fn upcast_any_ref(&self) -> &dyn Any {
5053            self
5054        }
5055    }
5056
5057    impl dyn AnyWasmNotSendSync + 'static {
5058        #[inline]
5059        pub fn downcast_ref<T: 'static>(&self) -> Option<&T> {
5060            self.upcast_any_ref().downcast_ref::<T>()
5061        }
5062    }
5063
5064    impl fmt::Debug for dyn AnyWasmNotSendSync {
5065        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
5066            f.debug_struct("Any").finish_non_exhaustive()
5067        }
5068    }
5069}