cart_tmp_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#![doc(html_logo_url = "https://raw.githubusercontent.com/gfx-rs/wgpu-rs/master/logo.png")]
6#![warn(missing_docs)]
7
8mod backend;
9pub mod util;
10#[macro_use]
11mod macros;
12
13use std::{
14    future::Future,
15    marker::PhantomData,
16    ops::{Bound, Range, RangeBounds},
17    sync::Arc,
18    thread,
19};
20
21use futures::FutureExt as _;
22use parking_lot::Mutex;
23
24#[cfg(not(target_arch = "wasm32"))]
25pub use wgc::instance::{AdapterInfo, DeviceType};
26pub use wgt::{
27    AddressMode, Backend, BackendBit, BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingType,
28    BlendDescriptor, BlendFactor, BlendOperation, BufferAddress, BufferSize, BufferUsage, Color,
29    ColorStateDescriptor, ColorWrite, CommandBufferDescriptor, CompareFunction, CullMode,
30    DepthStencilStateDescriptor, DeviceDescriptor, DynamicOffset, Extent3d, Features, FilterMode,
31    FrontFace, IndexFormat, InputStepMode, Limits, Origin3d, PowerPreference, PresentMode,
32    PrimitiveTopology, RasterizationStateDescriptor, RenderBundleEncoderDescriptor, ShaderLocation,
33    ShaderStage, StencilOperation, StencilStateFaceDescriptor, SwapChainDescriptor,
34    SwapChainStatus, TextureAspect, TextureComponentType, TextureDataLayout, TextureDimension,
35    TextureFormat, TextureUsage, TextureViewDimension, VertexAttributeDescriptor,
36    VertexBufferDescriptor, VertexFormat, VertexStateDescriptor, BIND_BUFFER_ALIGNMENT,
37    COPY_BUFFER_ALIGNMENT, COPY_BYTES_PER_ROW_ALIGNMENT,
38};
39
40use backend::Context as C;
41
42trait ComputePassInner<Ctx: Context> {
43    fn set_pipeline(&mut self, pipeline: &Ctx::ComputePipelineId);
44    fn set_bind_group(
45        &mut self,
46        index: u32,
47        bind_group: &Ctx::BindGroupId,
48        offsets: &[DynamicOffset],
49    );
50    fn dispatch(&mut self, x: u32, y: u32, z: u32);
51    fn dispatch_indirect(
52        &mut self,
53        indirect_buffer: &Ctx::BufferId,
54        indirect_offset: BufferAddress,
55    );
56}
57
58trait RenderInner<Ctx: Context> {
59    fn set_pipeline(&mut self, pipeline: &Ctx::RenderPipelineId);
60    fn set_bind_group(
61        &mut self,
62        index: u32,
63        bind_group: &Ctx::BindGroupId,
64        offsets: &[DynamicOffset],
65    );
66    fn set_index_buffer(
67        &mut self,
68        buffer: &Ctx::BufferId,
69        offset: BufferAddress,
70        size: Option<BufferSize>,
71    );
72    fn set_vertex_buffer(
73        &mut self,
74        slot: u32,
75        buffer: &Ctx::BufferId,
76        offset: BufferAddress,
77        size: Option<BufferSize>,
78    );
79    fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>);
80    fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>);
81    fn draw_indirect(&mut self, indirect_buffer: &Ctx::BufferId, indirect_offset: BufferAddress);
82    fn draw_indexed_indirect(
83        &mut self,
84        indirect_buffer: &Ctx::BufferId,
85        indirect_offset: BufferAddress,
86    );
87    fn multi_draw_indirect(
88        &mut self,
89        indirect_buffer: &Ctx::BufferId,
90        indirect_offset: BufferAddress,
91        count: u32,
92    );
93    fn multi_draw_indexed_indirect(
94        &mut self,
95        indirect_buffer: &Ctx::BufferId,
96        indirect_offset: BufferAddress,
97        count: u32,
98    );
99    fn multi_draw_indirect_count(
100        &mut self,
101        indirect_buffer: &Ctx::BufferId,
102        indirect_offset: BufferAddress,
103        count_buffer: &Ctx::BufferId,
104        count_buffer_offset: BufferAddress,
105        max_count: u32,
106    );
107    fn multi_draw_indexed_indirect_count(
108        &mut self,
109        indirect_buffer: &Ctx::BufferId,
110        indirect_offset: BufferAddress,
111        count_buffer: &Ctx::BufferId,
112        count_buffer_offset: BufferAddress,
113        max_count: u32,
114    );
115}
116
117trait RenderPassInner<Ctx: Context>: RenderInner<Ctx> {
118    fn set_blend_color(&mut self, color: Color);
119    fn set_scissor_rect(&mut self, x: u32, y: u32, width: u32, height: u32);
120    fn set_viewport(
121        &mut self,
122        x: f32,
123        y: f32,
124        width: f32,
125        height: f32,
126        min_depth: f32,
127        max_depth: f32,
128    );
129    fn set_stencil_reference(&mut self, reference: u32);
130    fn insert_debug_marker(&mut self, label: &str);
131    fn push_debug_group(&mut self, group_label: &str);
132    fn pop_debug_group(&mut self);
133    fn execute_bundles<'a, I: Iterator<Item = &'a Ctx::RenderBundleId>>(
134        &mut self,
135        render_bundles: I,
136    );
137}
138
139trait Context: Sized {
140    type AdapterId: Send + Sync + 'static;
141    type DeviceId: Send + Sync + 'static;
142    type QueueId: Send + Sync + 'static;
143    type ShaderModuleId: Send + Sync + 'static;
144    type BindGroupLayoutId: Send + Sync + 'static;
145    type BindGroupId: Send + Sync + 'static;
146    type TextureViewId: Send + Sync + 'static;
147    type SamplerId: Send + Sync + 'static;
148    type BufferId: Send + Sync + 'static;
149    type TextureId: Send + Sync + 'static;
150    type PipelineLayoutId: Send + Sync + 'static;
151    type RenderPipelineId: Send + Sync + 'static;
152    type ComputePipelineId: Send + Sync + 'static;
153    type CommandEncoderId;
154    type ComputePassId: ComputePassInner<Self>;
155    type RenderPassId: RenderPassInner<Self>;
156    type CommandBufferId: Send + Sync;
157    type RenderBundleEncoderId: RenderInner<Self>;
158    type RenderBundleId: Send + Sync + 'static;
159    type SurfaceId: Send + Sync + 'static;
160    type SwapChainId: Send + Sync + 'static;
161
162    type SwapChainOutputDetail: Send;
163
164    type RequestAdapterFuture: Future<Output = Option<Self::AdapterId>> + Send;
165    type RequestDeviceFuture: Future<Output = Result<(Self::DeviceId, Self::QueueId), RequestDeviceError>>
166        + Send;
167    type MapAsyncFuture: Future<Output = Result<(), BufferAsyncError>> + Send;
168
169    fn init(backends: BackendBit) -> Self;
170    fn instance_create_surface(
171        &self,
172        handle: &impl raw_window_handle::HasRawWindowHandle,
173    ) -> Self::SurfaceId;
174    fn instance_request_adapter(
175        &self,
176        options: &RequestAdapterOptions<'_>,
177    ) -> Self::RequestAdapterFuture;
178    fn adapter_request_device(
179        &self,
180        adapter: &Self::AdapterId,
181        desc: &DeviceDescriptor,
182        trace_dir: Option<&std::path::Path>,
183    ) -> Self::RequestDeviceFuture;
184    fn adapter_features(&self, adapter: &Self::AdapterId) -> Features;
185    fn adapter_limits(&self, adapter: &Self::AdapterId) -> Limits;
186
187    fn device_features(&self, device: &Self::DeviceId) -> Features;
188    fn device_limits(&self, device: &Self::DeviceId) -> Limits;
189    fn device_create_swap_chain(
190        &self,
191        device: &Self::DeviceId,
192        surface: &Self::SurfaceId,
193        desc: &SwapChainDescriptor,
194    ) -> Self::SwapChainId;
195    fn device_create_shader_module(
196        &self,
197        device: &Self::DeviceId,
198        source: ShaderModuleSource,
199    ) -> Self::ShaderModuleId;
200    fn device_create_bind_group_layout(
201        &self,
202        device: &Self::DeviceId,
203        desc: &BindGroupLayoutDescriptor,
204    ) -> Self::BindGroupLayoutId;
205    fn device_create_bind_group(
206        &self,
207        device: &Self::DeviceId,
208        desc: &BindGroupDescriptor,
209    ) -> Self::BindGroupId;
210    fn device_create_pipeline_layout(
211        &self,
212        device: &Self::DeviceId,
213        desc: &PipelineLayoutDescriptor,
214    ) -> Self::PipelineLayoutId;
215    fn device_create_render_pipeline(
216        &self,
217        device: &Self::DeviceId,
218        desc: &RenderPipelineDescriptor,
219    ) -> Self::RenderPipelineId;
220    fn device_create_compute_pipeline(
221        &self,
222        device: &Self::DeviceId,
223        desc: &ComputePipelineDescriptor,
224    ) -> Self::ComputePipelineId;
225    fn device_create_buffer(
226        &self,
227        device: &Self::DeviceId,
228        desc: &BufferDescriptor,
229    ) -> Self::BufferId;
230    fn device_create_texture(
231        &self,
232        device: &Self::DeviceId,
233        desc: &TextureDescriptor,
234    ) -> Self::TextureId;
235    fn device_create_sampler(
236        &self,
237        device: &Self::DeviceId,
238        desc: &SamplerDescriptor,
239    ) -> Self::SamplerId;
240    fn device_create_command_encoder(
241        &self,
242        device: &Self::DeviceId,
243        desc: &CommandEncoderDescriptor,
244    ) -> Self::CommandEncoderId;
245    fn device_create_render_bundle_encoder(
246        &self,
247        device: &Self::DeviceId,
248        desc: &RenderBundleEncoderDescriptor,
249    ) -> Self::RenderBundleEncoderId;
250    fn device_drop(&self, device: &Self::DeviceId);
251    fn device_poll(&self, device: &Self::DeviceId, maintain: Maintain);
252
253    fn buffer_map_async(
254        &self,
255        buffer: &Self::BufferId,
256        mode: MapMode,
257        range: Range<BufferAddress>,
258    ) -> Self::MapAsyncFuture;
259    //TODO: we might be able to merge these, depending on how Web backend
260    // turns out to be implemented.
261    fn buffer_get_mapped_range(
262        &self,
263        buffer: &Self::BufferId,
264        sub_range: Range<BufferAddress>,
265    ) -> &[u8];
266    fn buffer_get_mapped_range_mut(
267        &self,
268        buffer: &Self::BufferId,
269        sub_range: Range<BufferAddress>,
270    ) -> &mut [u8];
271    fn buffer_unmap(&self, buffer: &Self::BufferId);
272    fn swap_chain_get_next_texture(
273        &self,
274        swap_chain: &Self::SwapChainId,
275    ) -> (
276        Option<Self::TextureViewId>,
277        SwapChainStatus,
278        Self::SwapChainOutputDetail,
279    );
280    fn swap_chain_present(&self, view: &Self::TextureViewId, detail: &Self::SwapChainOutputDetail);
281    fn texture_create_view(
282        &self,
283        texture: &Self::TextureId,
284        desc: Option<&TextureViewDescriptor>,
285    ) -> Self::TextureViewId;
286    fn texture_drop(&self, texture: &Self::TextureId);
287    fn texture_view_drop(&self, texture_view: &Self::TextureViewId);
288    fn sampler_drop(&self, sampler: &Self::SamplerId);
289    fn buffer_drop(&self, buffer: &Self::BufferId);
290    fn bind_group_drop(&self, bind_group: &Self::BindGroupId);
291    fn bind_group_layout_drop(&self, bind_group_layout: &Self::BindGroupLayoutId);
292    fn pipeline_layout_drop(&self, pipeline_layout: &Self::PipelineLayoutId);
293    fn shader_module_drop(&self, shader_module: &Self::ShaderModuleId);
294    fn command_buffer_drop(&self, command_buffer: &Self::CommandBufferId);
295    fn render_bundle_drop(&self, render_bundle: &Self::RenderBundleId);
296    fn compute_pipeline_drop(&self, pipeline: &Self::ComputePipelineId);
297    fn render_pipeline_drop(&self, pipeline: &Self::RenderPipelineId);
298
299    fn command_encoder_copy_buffer_to_buffer(
300        &self,
301        encoder: &Self::CommandEncoderId,
302        source: &Self::BufferId,
303        source_offset: BufferAddress,
304        destination: &Self::BufferId,
305        destination_offset: BufferAddress,
306        copy_size: BufferAddress,
307    );
308    fn command_encoder_copy_buffer_to_texture(
309        &self,
310        encoder: &Self::CommandEncoderId,
311        source: BufferCopyView,
312        destination: TextureCopyView,
313        copy_size: Extent3d,
314    );
315    fn command_encoder_copy_texture_to_buffer(
316        &self,
317        encoder: &Self::CommandEncoderId,
318        source: TextureCopyView,
319        destination: BufferCopyView,
320        copy_size: Extent3d,
321    );
322    fn command_encoder_copy_texture_to_texture(
323        &self,
324        encoder: &Self::CommandEncoderId,
325        source: TextureCopyView,
326        destination: TextureCopyView,
327        copy_size: Extent3d,
328    );
329
330    fn command_encoder_begin_compute_pass(
331        &self,
332        encoder: &Self::CommandEncoderId,
333    ) -> Self::ComputePassId;
334    fn command_encoder_end_compute_pass(
335        &self,
336        encoder: &Self::CommandEncoderId,
337        pass: &mut Self::ComputePassId,
338    );
339    fn command_encoder_begin_render_pass<'a>(
340        &self,
341        encoder: &Self::CommandEncoderId,
342        desc: &RenderPassDescriptor<'a, '_>,
343    ) -> Self::RenderPassId;
344    fn command_encoder_end_render_pass(
345        &self,
346        encoder: &Self::CommandEncoderId,
347        pass: &mut Self::RenderPassId,
348    );
349    fn command_encoder_finish(&self, encoder: &Self::CommandEncoderId) -> Self::CommandBufferId;
350    fn render_bundle_encoder_finish(
351        &self,
352        encoder: Self::RenderBundleEncoderId,
353        desc: &RenderBundleDescriptor,
354    ) -> Self::RenderBundleId;
355    fn queue_write_buffer(
356        &self,
357        queue: &Self::QueueId,
358        buffer: &Self::BufferId,
359        offset: BufferAddress,
360        data: &[u8],
361    );
362    fn queue_write_texture(
363        &self,
364        queue: &Self::QueueId,
365        texture: TextureCopyView,
366        data: &[u8],
367        data_layout: TextureDataLayout,
368        size: Extent3d,
369    );
370    fn queue_submit<I: Iterator<Item = Self::CommandBufferId>>(
371        &self,
372        queue: &Self::QueueId,
373        command_buffers: I,
374    );
375}
376
377/// Context for all other wgpu objects. Instance of wgpu.
378///
379/// This is the first thing you create when using wgpu.
380/// Its primary use is to create [`Adapter`]s and [`Surface`]s.
381///
382/// Does not have to be kept alive.
383pub struct Instance {
384    context: Arc<C>,
385}
386
387/// Handle to a physical graphics and/or compute device.
388///
389/// Adapters can be used to open a connection to the corresponding [`Device`]
390/// on the host system by using [`Adapter::request_device`].
391///
392/// Does not have to be kept alive.
393pub struct Adapter {
394    context: Arc<C>,
395    id: <C as Context>::AdapterId,
396}
397
398/// Options for requesting adapter.
399#[derive(Clone)]
400pub struct RequestAdapterOptions<'a> {
401    /// Power preference for the adapter.
402    pub power_preference: PowerPreference,
403    /// Surface that is required to be presentable with the requested adapter. This does not
404    /// create the surface, only guarantees that the adapter can present to said surface.
405    pub compatible_surface: Option<&'a Surface>,
406}
407
408/// Open connection to a graphics and/or compute device.
409///
410/// Responsible for the creation of most rendering and compute resources.
411/// These are then used in commands, which are submitted to a [`Queue`].
412///
413/// A device may be requested from an adapter with [`Adapter::request_device`].
414pub struct Device {
415    context: Arc<C>,
416    id: <C as Context>::DeviceId,
417}
418
419/// Passed to [`Device::poll`] to control if it should block or not. This has no effect on
420/// the web.
421#[derive(Debug, Copy, Clone, PartialEq, Eq)]
422pub enum Maintain {
423    /// Block
424    Wait,
425    /// Don't block
426    Poll,
427}
428
429/// The main purpose of this struct is to resolve mapped ranges
430/// (convert sizes to end points), and to ensure that the sub-ranges
431/// don't intersect.
432#[derive(Debug)]
433struct MapContext {
434    total_size: BufferAddress,
435    initial_range: Range<BufferAddress>,
436    sub_ranges: Vec<Range<BufferAddress>>,
437}
438
439impl MapContext {
440    fn new(total_size: BufferAddress) -> Self {
441        MapContext {
442            total_size,
443            initial_range: 0..0,
444            sub_ranges: Vec::new(),
445        }
446    }
447
448    fn reset(&mut self) {
449        self.initial_range = 0..0;
450
451        assert!(
452            self.sub_ranges.is_empty(),
453            "You cannot unmap a buffer that still has accessible mapped views"
454        );
455    }
456
457    fn add(&mut self, offset: BufferAddress, size: Option<BufferSize>) -> BufferAddress {
458        let end = match size {
459            Some(s) => offset + s.get(),
460            None => self.initial_range.end,
461        };
462        assert!(self.initial_range.start <= offset && end <= self.initial_range.end);
463        for sub in self.sub_ranges.iter() {
464            assert!(
465                end <= sub.start || offset >= sub.end,
466                "Intersecting map range with {:?}",
467                sub
468            );
469        }
470        self.sub_ranges.push(offset..end);
471        end
472    }
473
474    fn remove(&mut self, offset: BufferAddress, size: Option<BufferSize>) {
475        let end = match size {
476            Some(s) => offset + s.get(),
477            None => self.initial_range.end,
478        };
479
480        // Switch this out with `Vec::remove_item` once that stabilizes.
481        let index = self
482            .sub_ranges
483            .iter()
484            .position(|r| *r == (offset..end))
485            .expect("unable to remove range from map context");
486        self.sub_ranges.swap_remove(index);
487    }
488}
489
490/// Handle to a GPU-accessible buffer.
491///
492/// Created with [`Device::create_buffer`] or [`Device::create_buffer_with_data`]
493pub struct Buffer {
494    context: Arc<C>,
495    id: <C as Context>::BufferId,
496    map_context: Mutex<MapContext>,
497    usage: BufferUsage,
498}
499
500/// Slice into a [`Buffer`].
501///
502/// Created by calling [`Buffer::slice`]. To use the whole buffer, call with unbounded slice:
503///
504/// `buffer.slice(..)`
505#[derive(Copy, Clone)]
506pub struct BufferSlice<'a> {
507    buffer: &'a Buffer,
508    offset: BufferAddress,
509    size: Option<BufferSize>,
510}
511
512/// Handle to a texture on the GPU.
513///
514/// Created by calling [`Device::create_texture`]
515pub struct Texture {
516    context: Arc<C>,
517    id: <C as Context>::TextureId,
518    owned: bool,
519}
520
521/// Handle to a texture view.
522///
523/// A `TextureView` object describes a texture and associated metadata needed by a
524/// [`RenderPipeline`] or [`BindGroup`].
525pub struct TextureView {
526    context: Arc<C>,
527    id: <C as Context>::TextureViewId,
528    owned: bool,
529}
530
531/// Handle to a sampler.
532///
533/// A `Sampler` object defines how a pipeline will sample from a [`TextureView`]. Samplers define
534/// image filters (including anisotropy) and address (wrapping) modes, among other things. See
535/// the documentation for [`SamplerDescriptor`] for more information.
536pub struct Sampler {
537    context: Arc<C>,
538    id: <C as Context>::SamplerId,
539}
540
541impl Drop for Sampler {
542    fn drop(&mut self) {
543        if !thread::panicking() {
544            self.context.sampler_drop(&self.id);
545        }
546    }
547}
548
549/// Handle to a presentable surface.
550///
551/// A `Surface` represents a platform-specific surface (e.g. a window) onto which rendered images may
552/// be presented. A `Surface` may be created with the unsafe function [`Instance::create_surface`].
553pub struct Surface {
554    id: <C as Context>::SurfaceId,
555}
556
557/// Handle to a swap chain.
558///
559/// A `SwapChain` represents the image or series of images that will be presented to a [`Surface`].
560/// A `SwapChain` may be created with [`Device::create_swap_chain`].
561pub struct SwapChain {
562    context: Arc<C>,
563    id: <C as Context>::SwapChainId,
564}
565
566/// Handle to a binding group layout.
567///
568/// A `BindGroupLayout` is a handle to the GPU-side layout of a binding group. It can be used to
569/// create a [`BindGroupDescriptor`] object, which in turn can be used to create a [`BindGroup`]
570/// object with [`Device::create_bind_group`]. A series of `BindGroupLayout`s can also be used to
571/// create a [`PipelineLayoutDescriptor`], which can be used to create a [`PipelineLayout`].
572pub struct BindGroupLayout {
573    context: Arc<C>,
574    id: <C as Context>::BindGroupLayoutId,
575}
576
577impl Drop for BindGroupLayout {
578    fn drop(&mut self) {
579        if !thread::panicking() {
580            self.context.bind_group_layout_drop(&self.id);
581        }
582    }
583}
584
585/// Handle to a binding group.
586///
587/// A `BindGroup` represents the set of resources bound to the bindings described by a
588/// [`BindGroupLayout`]. It can be created with [`Device::create_bind_group`]. A `BindGroup` can
589/// be bound to a particular [`RenderPass`] with [`RenderPass::set_bind_group`], or to a
590/// [`ComputePass`] with [`ComputePass::set_bind_group`].
591pub struct BindGroup {
592    context: Arc<C>,
593    id: <C as Context>::BindGroupId,
594}
595
596impl Drop for BindGroup {
597    fn drop(&mut self) {
598        if !thread::panicking() {
599            self.context.bind_group_drop(&self.id);
600        }
601    }
602}
603
604/// Handle to a compiled shader module.
605///
606/// A `ShaderModule` represents a compiled shader module on the GPU. It can be created by passing
607/// valid SPIR-V source code to [`Device::create_shader_module`]. Shader modules are used to define
608/// programmable stages of a pipeline.
609pub struct ShaderModule {
610    context: Arc<C>,
611    id: <C as Context>::ShaderModuleId,
612}
613
614impl Drop for ShaderModule {
615    fn drop(&mut self) {
616        if !thread::panicking() {
617            self.context.shader_module_drop(&self.id);
618        }
619    }
620}
621
622/// Source of a shader module.
623pub enum ShaderModuleSource<'a> {
624    /// SPIR-V module represented as a slice of words.
625    ///
626    /// wgpu will attempt to parse and validate it, but the original binary
627    /// is passed to `gfx-rs` and `spirv_cross` for translation.
628    SpirV(&'a [u32]),
629    /// WGSL module as a string slice.
630    ///
631    /// wgpu-rs will parse it and use for validation. It will attempt
632    /// to build a SPIR-V module internally and panic otherwise.
633    ///
634    /// Note: WGSL is not yet supported on the Web.
635    Wgsl(&'a str),
636}
637
638/// Handle to a pipeline layout.
639///
640/// A `PipelineLayout` object describes the available binding groups of a pipeline.
641pub struct PipelineLayout {
642    context: Arc<C>,
643    id: <C as Context>::PipelineLayoutId,
644}
645
646impl Drop for PipelineLayout {
647    fn drop(&mut self) {
648        if !thread::panicking() {
649            self.context.pipeline_layout_drop(&self.id);
650        }
651    }
652}
653
654/// Handle to a rendering (graphics) pipeline.
655///
656/// A `RenderPipeline` object represents a graphics pipeline and its stages, bindings, vertex
657/// buffers and targets. A `RenderPipeline` may be created with [`Device::create_render_pipeline`].
658pub struct RenderPipeline {
659    context: Arc<C>,
660    id: <C as Context>::RenderPipelineId,
661}
662
663impl Drop for RenderPipeline {
664    fn drop(&mut self) {
665        if !thread::panicking() {
666            self.context.render_pipeline_drop(&self.id);
667        }
668    }
669}
670
671/// Handle to a compute pipeline.
672///
673/// A `ComputePipeline` object represents a compute pipeline and its single shader stage.
674/// A `ComputePipeline` may be created with [`Device::create_compute_pipeline`].
675pub struct ComputePipeline {
676    context: Arc<C>,
677    id: <C as Context>::ComputePipelineId,
678}
679
680impl Drop for ComputePipeline {
681    fn drop(&mut self) {
682        if !thread::panicking() {
683            self.context.compute_pipeline_drop(&self.id);
684        }
685    }
686}
687
688/// Handle to a command buffer on the GPU.
689///
690/// A `CommandBuffer` represents a complete sequence of commands that may be submitted to a command
691/// queue with [`Queue::submit`]. A `CommandBuffer` is obtained by recording a series of commands to
692/// a [`CommandEncoder`] and then calling [`CommandEncoder::finish`].
693pub struct CommandBuffer {
694    context: Arc<C>,
695    id: Option<<C as Context>::CommandBufferId>,
696}
697
698impl Drop for CommandBuffer {
699    fn drop(&mut self) {
700        if !thread::panicking() {
701            if let Some(ref id) = self.id {
702                self.context.command_buffer_drop(id);
703            }
704        }
705    }
706}
707
708/// Encodes a series of GPU operations.
709///
710/// A command encoder can record [`RenderPass`]es, [`ComputePass`]es,
711/// and transfer operations between driver-managed resources like [`Buffer`]s and [`Texture`]s.
712///
713/// When finished recording, call [`CommandEncoder::finish`] to obtain a [`CommandBuffer`] which may
714/// be submitted for execution.
715pub struct CommandEncoder {
716    context: Arc<C>,
717    id: <C as Context>::CommandEncoderId,
718    /// This type should be !Send !Sync, because it represents an allocation on this thread's
719    /// command buffer.
720    _p: PhantomData<*const u8>,
721}
722
723/// In-progress recording of a render pass.
724pub struct RenderPass<'a> {
725    id: <C as Context>::RenderPassId,
726    parent: &'a mut CommandEncoder,
727}
728
729/// In-progress recording of a compute pass.
730pub struct ComputePass<'a> {
731    id: <C as Context>::ComputePassId,
732    parent: &'a mut CommandEncoder,
733}
734
735/// Encodes a series of GPU operations into a reusable "render bundle".
736///
737/// It only supports a handful of render commands, but it makes them reusable. [`RenderBundle`]s
738/// can be executed onto a [`CommandEncoder`] using [`RenderPass::execute_bundles`].
739///
740/// Executing a [`RenderBundle`] is often more efficient then issuing the underlying commands manually.
741pub struct RenderBundleEncoder<'a> {
742    context: Arc<C>,
743    id: <C as Context>::RenderBundleEncoderId,
744    _parent: &'a Device,
745    /// This type should be !Send !Sync, because it represents an allocation on this thread's
746    /// command buffer.
747    _p: PhantomData<*const u8>,
748}
749
750/// Pre-prepared reusable bundle of GPU operations.
751///
752/// It only supports a handful of render commands, but it makes them reusable. [`RenderBundle`]s
753/// can be executed onto a [`CommandEncoder`] using [`RenderPass::execute_bundles`].
754///
755/// Executing a [`RenderBundle`] is often more efficient then issuing the underlying commands manually.
756pub struct RenderBundle {
757    context: Arc<C>,
758    id: <C as Context>::RenderBundleId,
759}
760
761impl Drop for RenderBundle {
762    fn drop(&mut self) {
763        if !thread::panicking() {
764            self.context.render_bundle_drop(&self.id);
765        }
766    }
767}
768
769/// Handle to a command queue on a device.
770///
771/// A `Queue` executes recorded [`CommandBuffer`] objects and provides convenience methods
772/// for writing to [buffers](Queue::write_buffer) and [textures](Queue::write_texture).
773pub struct Queue {
774    context: Arc<C>,
775    id: <C as Context>::QueueId,
776}
777
778/// Resource that can be bound to a pipeline.
779#[non_exhaustive]
780pub enum BindingResource<'a> {
781    /// Binding is backed by a buffer.
782    ///
783    /// Corresponds to [`BindingType::UniformBuffer`] and [`BindingType::StorageBuffer`]
784    /// with [`BindGroupLayoutEntry::count`] set to None.
785    Buffer(BufferSlice<'a>),
786    /// Binding is a sampler.
787    ///
788    /// Corresponds to [`BindingType::Sampler`] with [`BindGroupLayoutEntry::count`] set to None.
789    Sampler(&'a Sampler),
790    /// Binding is backed by a texture.
791    ///
792    /// Corresponds to [`BindingType::SampledTexture`] and [`BindingType::StorageTexture`] with
793    /// [`BindGroupLayoutEntry::count`] set to None.
794    TextureView(&'a TextureView),
795    /// Binding is backed by an array of textures.
796    ///
797    /// [`Features::SAMPLED_TEXTURE_BINDING_ARRAY`] must be supported to use this feature.
798    ///
799    /// Corresponds to [`BindingType::SampledTexture`] and [`BindingType::StorageTexture`] with
800    /// [`BindGroupLayoutEntry::count`] set to Some.
801    TextureViewArray(&'a [TextureView]),
802}
803
804/// Bindable resource and the slot to bind it to.
805pub struct Binding<'a> {
806    /// Slot for which binding provides resource. Corresponds to an entry of the same
807    /// binding index in the [`BindGroupLayoutDescriptor`].
808    pub binding: u32,
809    /// Resource to attach to the binding
810    pub resource: BindingResource<'a>,
811}
812
813/// Describes a group of bindings and the resources to be bound.
814#[derive(Clone)]
815pub struct BindGroupDescriptor<'a> {
816    /// The [`BindGroupLayout`] that corresponds to this bind group.
817    pub layout: &'a BindGroupLayout,
818
819    /// The resources to bind to this bind group.
820    pub bindings: &'a [Binding<'a>],
821
822    /// Debug label of the bind group. This will show up in graphics debuggers for easy identification.
823    pub label: Option<&'a str>,
824}
825
826/// Describes a pipeline layout.
827///
828/// A `PipelineLayoutDescriptor` can be passed to [`Device::create_pipeline_layout`] to obtain a
829/// [`PipelineLayout`].
830#[derive(Clone)]
831pub struct PipelineLayoutDescriptor<'a> {
832    /// Bind groups that this pipeline uses. The first entry will provide all the bindings for
833    /// "set = 0", second entry will provide all the bindings for "set = 1" etc.
834    pub bind_group_layouts: &'a [&'a BindGroupLayout],
835}
836
837/// Describes a programmable pipeline stage.
838#[derive(Clone)]
839pub struct ProgrammableStageDescriptor<'a> {
840    /// The compiled shader module for this stage.
841    pub module: &'a ShaderModule,
842
843    /// The name of the entry point in the compiled shader. There must be a function that returns
844    /// void with this name in the shader.
845    pub entry_point: &'a str,
846}
847
848/// Describes a render (graphics) pipeline.
849#[derive(Clone)]
850pub struct RenderPipelineDescriptor<'a> {
851    /// The layout of bind groups for this pipeline.
852    pub layout: &'a PipelineLayout,
853
854    /// The compiled vertex stage and its entry point.
855    pub vertex_stage: ProgrammableStageDescriptor<'a>,
856
857    /// The compiled fragment stage and its entry point, if any.
858    pub fragment_stage: Option<ProgrammableStageDescriptor<'a>>,
859
860    /// The rasterization process for this pipeline.
861    pub rasterization_state: Option<RasterizationStateDescriptor>,
862
863    /// The primitive topology used to interpret vertices.
864    pub primitive_topology: PrimitiveTopology,
865
866    /// The effect of draw calls on the color aspect of the output target.
867    pub color_states: &'a [ColorStateDescriptor],
868
869    /// The effect of draw calls on the depth and stencil aspects of the output target, if any.
870    pub depth_stencil_state: Option<DepthStencilStateDescriptor>,
871
872    /// The vertex input state for this pipeline.
873    pub vertex_state: VertexStateDescriptor<'a>,
874
875    /// The number of samples calculated per pixel (for MSAA). For non-multisampled textures,
876    /// this should be `1`
877    pub sample_count: u32,
878
879    /// Bitmask that restricts the samples of a pixel modified by this pipeline. All samples
880    /// can be enabled using the value `!0`
881    pub sample_mask: u32,
882
883    /// When enabled, produces another sample mask per pixel based on the alpha output value, that
884    /// is ANDed with the sample_mask and the primitive coverage to restrict the set of samples
885    /// affected by a primitive.
886    ///
887    /// The implicit mask produced for alpha of zero is guaranteed to be zero, and for alpha of one
888    /// is guaranteed to be all 1-s.
889    pub alpha_to_coverage_enabled: bool,
890}
891
892/// Describes a compute pipeline.
893#[derive(Clone)]
894pub struct ComputePipelineDescriptor<'a> {
895    /// The layout of bind groups for this pipeline.
896    pub layout: &'a PipelineLayout,
897
898    /// The compiled compute stage and its entry point.
899    pub compute_stage: ProgrammableStageDescriptor<'a>,
900}
901
902/// Operation to perform to the output attachment at the start of a renderpass.
903#[derive(Clone, Copy, Debug, Hash, PartialEq)]
904pub enum LoadOp<V> {
905    /// Clear with a specified value.
906    Clear(V),
907    /// Load from memory.
908    Load,
909}
910
911/// Pair of load and store operations for an attachment aspect.
912#[derive(Clone, Debug, Hash, PartialEq)]
913pub struct Operations<V> {
914    /// How data should be read through this attachment.
915    pub load: LoadOp<V>,
916    /// Whether data will be written to through this attachment.
917    pub store: bool,
918}
919
920/// Describes a color attachment to a [`RenderPass`].
921#[derive(Clone)]
922pub struct RenderPassColorAttachmentDescriptor<'a> {
923    /// The view to use as an attachment.
924    pub attachment: &'a TextureView,
925    /// The view that will receive the resolved output if multisampling is used.
926    pub resolve_target: Option<&'a TextureView>,
927    /// What operations will be performed on this color attachment.
928    pub ops: Operations<Color>,
929}
930/// Describes a depth/stencil attachment to a [`RenderPass`].
931#[derive(Clone)]
932pub struct RenderPassDepthStencilAttachmentDescriptor<'a> {
933    /// The view to use as an attachment.
934    pub attachment: &'a TextureView,
935    /// What operations will be performed on the depth part of the attachment.
936    pub depth_ops: Option<Operations<f32>>,
937    /// What operations will be performed on the stencil part of the attachment.
938    pub stencil_ops: Option<Operations<u32>>,
939}
940
941/// Describes the attachments of a [`RenderPass`].
942#[derive(Clone)]
943pub struct RenderPassDescriptor<'a, 'b> {
944    /// The color attachments of the render pass.
945    pub color_attachments: &'b [RenderPassColorAttachmentDescriptor<'a>],
946
947    /// The depth and stencil attachment of the render pass, if any.
948    pub depth_stencil_attachment: Option<RenderPassDepthStencilAttachmentDescriptor<'a>>,
949}
950
951// The underlying types are also exported so that documentation shows up for them
952
953pub use wgt::BufferDescriptor as BufferDescriptorBase;
954/// Describes a [`Buffer`].
955pub type BufferDescriptor<'a> = BufferDescriptorBase<Option<&'a str>>;
956
957pub use wgt::CommandEncoderDescriptor as CommandEncoderDescriptorBase;
958/// Describes a [`CommandEncoder`].
959pub type CommandEncoderDescriptor<'a> = CommandEncoderDescriptorBase<Option<&'a str>>;
960
961pub use wgt::RenderBundleDescriptor as RenderBundleDescriptorBase;
962/// Describes a [`RenderBundle`].
963pub type RenderBundleDescriptor<'a> = RenderBundleDescriptorBase<Option<&'a str>>;
964
965pub use wgt::TextureDescriptor as TextureDescriptorBase;
966/// Describes a [`Texture`].
967pub type TextureDescriptor<'a> = TextureDescriptorBase<Option<&'a str>>;
968
969pub use wgt::TextureViewDescriptor as TextureViewDescriptorBase;
970/// Describes a [`TextureView`].
971pub type TextureViewDescriptor<'a> = TextureViewDescriptorBase<Option<&'a str>>;
972
973pub use wgt::SamplerDescriptor as SamplerDescriptorBase;
974/// Describes a [`Sampler`].
975pub type SamplerDescriptor<'a> = SamplerDescriptorBase<Option<&'a str>>;
976
977/// Swap chain image that can be rendered to.
978pub struct SwapChainTexture {
979    /// Accessible view of the frame.
980    pub view: TextureView,
981    detail: <C as Context>::SwapChainOutputDetail,
982}
983
984/// Result of a successful call to [`SwapChain::get_next_frame`].
985pub struct SwapChainFrame {
986    /// The texture into which the next frame should be rendered.
987    pub output: SwapChainTexture,
988    /// `true` if the acquired buffer can still be used for rendering,
989    /// but should be recreated for maximum performance.
990    pub suboptimal: bool,
991}
992
993/// Result of an unsuccessful call to [`SwapChain::get_next_frame`].
994#[derive(Debug)]
995pub enum SwapChainError {
996    /// A timeout was encountered while trying to acquire the next frame.
997    Timeout,
998    /// The underlying surface has changed, and therefore the swap chain must be updated.
999    Outdated,
1000    /// The swap chain has been lost and needs to be recreated.
1001    Lost,
1002    /// There is no more memory left to allocate a new frame.
1003    OutOfMemory,
1004}
1005
1006/// View of a buffer which can be used to copy to/from a texture.
1007#[derive(Clone)]
1008pub struct BufferCopyView<'a> {
1009    /// The buffer to be copied to/from.
1010    pub buffer: &'a Buffer,
1011
1012    /// The layout of the texture data in this buffer.
1013    pub layout: TextureDataLayout,
1014}
1015
1016/// View of a texture which can be used to copy to/from a buffer/texture.
1017#[derive(Clone)]
1018pub struct TextureCopyView<'a> {
1019    /// The texture to be copied to/from.
1020    pub texture: &'a Texture,
1021
1022    /// The target mip level of the texture.
1023    pub mip_level: u32,
1024
1025    /// The base texel of the texture in the selected `mip_level`.
1026    pub origin: Origin3d,
1027}
1028
1029impl Instance {
1030    /// Create an new instance of wgpu.
1031    ///
1032    /// # Arguments
1033    ///
1034    /// - `backends` - Controls from which [backends][BackendBit] wgpu will choose
1035    ///   during instantiation.
1036    pub fn new(backends: BackendBit) -> Self {
1037        Instance {
1038            context: Arc::new(C::init(backends)),
1039        }
1040    }
1041
1042    /// Retrieves all available [`Adapter`]s that match the given [`BackendBit`].
1043    ///
1044    /// # Arguments
1045    ///
1046    /// - `backends` - Backends from which to enumerate adapters.
1047    #[cfg(not(target_arch = "wasm32"))]
1048    pub fn enumerate_adapters(&self, backends: BackendBit) -> impl Iterator<Item = Adapter> {
1049        let context = Arc::clone(&self.context);
1050        self.context
1051            .enumerate_adapters(wgc::instance::AdapterInputs::Mask(backends, |_| {
1052                PhantomData
1053            }))
1054            .into_iter()
1055            .map(move |id| crate::Adapter {
1056                id,
1057                context: Arc::clone(&context),
1058            })
1059    }
1060
1061    /// Retrieves an [`Adapter`] which matches the given [`RequestAdapterOptions`].
1062    ///
1063    /// Some options are "soft", so treated as non-mandatory. Others are "hard".
1064    ///
1065    /// If no adapters are found that suffice all the "hard" options, `None` is returned.
1066    pub fn request_adapter(
1067        &self,
1068        options: &RequestAdapterOptions<'_>,
1069    ) -> impl Future<Output = Option<Adapter>> + Send {
1070        let context = Arc::clone(&self.context);
1071        self.context
1072            .instance_request_adapter(options)
1073            .map(|option| option.map(|id| Adapter { context, id }))
1074    }
1075
1076    /// Creates a surface from a raw window handle.
1077    ///
1078    /// # Safety
1079    ///
1080    /// - Raw Window Handle must be a valid object to create a surface upon.
1081    pub unsafe fn create_surface<W: raw_window_handle::HasRawWindowHandle>(
1082        &self,
1083        window: &W,
1084    ) -> Surface {
1085        Surface {
1086            id: Context::instance_create_surface(&*self.context, window),
1087        }
1088    }
1089
1090    #[cfg(any(target_os = "ios", target_os = "macos"))]
1091    pub unsafe fn create_surface_from_core_animation_layer(
1092        &self,
1093        layer: *mut std::ffi::c_void,
1094    ) -> Surface {
1095        let surface = wgc::instance::Surface {
1096            #[cfg(feature = "vulkan-portability")]
1097            vulkan: self.context.instance.vulkan.as_ref().map(|inst| {
1098                inst.create_surface_from_layer(layer as *mut _, cfg!(debug_assertions))
1099            }),
1100            metal: self.context.instance.metal.as_ref().map(|inst| {
1101                inst.create_surface_from_layer(layer as *mut _, cfg!(debug_assertions))
1102            }),
1103        };
1104
1105        crate::Surface {
1106            id: self.context.surfaces.register_identity(
1107                PhantomData,
1108                surface,
1109                &mut wgc::hub::Token::root(),
1110            ),
1111        }
1112    }
1113}
1114
1115impl Adapter {
1116    /// Requests a connection to a physical device, creating a logical device.
1117    ///
1118    /// Returns the [`Device`] together with a [`Queue`] that executes command buffers.
1119    ///
1120    /// # Arguments
1121    ///
1122    /// - `desc` - Description of the features and limits requested from the given device.
1123    /// - `trace_path` - Can be used for API call tracing, if that feature is
1124    ///   enabled in `wgpu-core`.
1125    ///
1126    /// # Panics
1127    ///
1128    /// - Features specified by `desc` are not supported by this adapter.
1129    /// - Unsafe features were requested but not enabled when requesting the adapter.
1130    /// - Limits requested exceed the values provided by the adapter.
1131    /// - Adapter does not support all features wgpu requires to safely operate.
1132    pub fn request_device(
1133        &self,
1134        desc: &DeviceDescriptor,
1135        trace_path: Option<&std::path::Path>,
1136    ) -> impl Future<Output = Result<(Device, Queue), RequestDeviceError>> + Send {
1137        let context = Arc::clone(&self.context);
1138        Context::adapter_request_device(&*self.context, &self.id, desc, trace_path).map(|result| {
1139            result.map(|(device_id, queue_id)| {
1140                (
1141                    Device {
1142                        context: Arc::clone(&context),
1143                        id: device_id,
1144                    },
1145                    Queue {
1146                        context,
1147                        id: queue_id,
1148                    },
1149                )
1150            })
1151        })
1152    }
1153
1154    /// List all features that are supported with this adapter.
1155    ///
1156    /// Features must be explicitly requested in [`Adapter::request_device`] in order
1157    /// to use them.
1158    pub fn features(&self) -> Features {
1159        Context::adapter_features(&*self.context, &self.id)
1160    }
1161
1162    /// List the "best" limits that are supported by this adapter.
1163    ///
1164    /// Limits must be explicitly requested in [`Adapter::request_device`] to set
1165    /// the values that you are allowed to use.
1166    pub fn limits(&self) -> Limits {
1167        Context::adapter_limits(&*self.context, &self.id)
1168    }
1169
1170    /// Get info about the adapter itself.
1171    #[cfg(not(target_arch = "wasm32"))]
1172    pub fn get_info(&self) -> AdapterInfo {
1173        let context = &self.context;
1174        wgc::gfx_select!(self.id => context.adapter_get_info(self.id))
1175    }
1176}
1177
1178impl Device {
1179    /// Check for resource cleanups and mapping callbacks.
1180    ///
1181    /// no-op on the web, device is automatically polled.
1182    pub fn poll(&self, maintain: Maintain) {
1183        Context::device_poll(&*self.context, &self.id, maintain);
1184    }
1185
1186    /// List all features that may be used with this device.
1187    ///
1188    /// Functions may panic if you use unsupported features.
1189    pub fn features(&self) -> Features {
1190        Context::device_features(&*self.context, &self.id)
1191    }
1192
1193    /// List all limits that were requested of this device.
1194    ///
1195    /// If any of these limits are exceeded, functions may panic.
1196    pub fn limits(&self) -> Limits {
1197        Context::device_limits(&*self.context, &self.id)
1198    }
1199
1200    /// Creates a shader module from either SPIR-V or WGSL source code.
1201    pub fn create_shader_module(&self, source: ShaderModuleSource) -> ShaderModule {
1202        ShaderModule {
1203            context: Arc::clone(&self.context),
1204            id: Context::device_create_shader_module(&*self.context, &self.id, source),
1205        }
1206    }
1207
1208    /// Creates an empty [`CommandEncoder`].
1209    pub fn create_command_encoder(&self, desc: &CommandEncoderDescriptor) -> CommandEncoder {
1210        CommandEncoder {
1211            context: Arc::clone(&self.context),
1212            id: Context::device_create_command_encoder(&*self.context, &self.id, desc),
1213            _p: Default::default(),
1214        }
1215    }
1216
1217    /// Creates an empty [`RenderBundleEncoder`].
1218    pub fn create_render_bundle_encoder(
1219        &self,
1220        desc: &RenderBundleEncoderDescriptor,
1221    ) -> RenderBundleEncoder {
1222        RenderBundleEncoder {
1223            context: Arc::clone(&self.context),
1224            id: Context::device_create_render_bundle_encoder(&*self.context, &self.id, desc),
1225            _parent: self,
1226            _p: Default::default(),
1227        }
1228    }
1229
1230    /// Creates a new [`BindGroup`].
1231    pub fn create_bind_group(&self, desc: &BindGroupDescriptor) -> BindGroup {
1232        BindGroup {
1233            context: Arc::clone(&self.context),
1234            id: Context::device_create_bind_group(&*self.context, &self.id, desc),
1235        }
1236    }
1237
1238    /// Creates a [`BindGroupLayout`].
1239    pub fn create_bind_group_layout(&self, desc: &BindGroupLayoutDescriptor) -> BindGroupLayout {
1240        BindGroupLayout {
1241            context: Arc::clone(&self.context),
1242            id: Context::device_create_bind_group_layout(&*self.context, &self.id, desc),
1243        }
1244    }
1245
1246    /// Creates a [`PipelineLayout`].
1247    pub fn create_pipeline_layout(&self, desc: &PipelineLayoutDescriptor) -> PipelineLayout {
1248        PipelineLayout {
1249            context: Arc::clone(&self.context),
1250            id: Context::device_create_pipeline_layout(&*self.context, &self.id, desc),
1251        }
1252    }
1253
1254    /// Creates a [`RenderPipeline`].
1255    pub fn create_render_pipeline(&self, desc: &RenderPipelineDescriptor) -> RenderPipeline {
1256        RenderPipeline {
1257            context: Arc::clone(&self.context),
1258            id: Context::device_create_render_pipeline(&*self.context, &self.id, desc),
1259        }
1260    }
1261
1262    /// Creates a [`ComputePipeline`].
1263    pub fn create_compute_pipeline(&self, desc: &ComputePipelineDescriptor) -> ComputePipeline {
1264        ComputePipeline {
1265            context: Arc::clone(&self.context),
1266            id: Context::device_create_compute_pipeline(&*self.context, &self.id, desc),
1267        }
1268    }
1269
1270    /// Creates a [`Buffer`].
1271    pub fn create_buffer(&self, desc: &BufferDescriptor) -> Buffer {
1272        let mut map_context = MapContext::new(desc.size);
1273        if desc.mapped_at_creation {
1274            map_context.initial_range = 0..desc.size;
1275        }
1276        Buffer {
1277            context: Arc::clone(&self.context),
1278            id: Context::device_create_buffer(&*self.context, &self.id, desc),
1279            map_context: Mutex::new(map_context),
1280            usage: desc.usage,
1281        }
1282    }
1283
1284    /// Creates a new buffer, maps it into host-visible memory, copies data from the given slice,
1285    /// and finally unmaps it, returning a [`Buffer`].
1286    pub fn create_buffer_with_data(&self, data: &[u8], usage: BufferUsage) -> Buffer {
1287        let size = data.len() as u64;
1288        let buffer = self.create_buffer(&BufferDescriptor {
1289            label: None,
1290            size,
1291            usage,
1292            mapped_at_creation: true,
1293        });
1294        Context::buffer_get_mapped_range_mut(&*self.context, &buffer.id, 0..size)
1295            .copy_from_slice(data);
1296        buffer.unmap();
1297        buffer
1298    }
1299
1300    /// Creates a new [`Texture`].
1301    ///
1302    /// `desc` specifies the general format of the texture.
1303    pub fn create_texture(&self, desc: &TextureDescriptor) -> Texture {
1304        Texture {
1305            context: Arc::clone(&self.context),
1306            id: Context::device_create_texture(&*self.context, &self.id, desc),
1307            owned: true,
1308        }
1309    }
1310
1311    /// Creates a new [`Sampler`].
1312    ///
1313    /// `desc` specifies the behavior of the sampler.
1314    pub fn create_sampler(&self, desc: &SamplerDescriptor) -> Sampler {
1315        Sampler {
1316            context: Arc::clone(&self.context),
1317            id: Context::device_create_sampler(&*self.context, &self.id, desc),
1318        }
1319    }
1320
1321    /// Create a new [`SwapChain`] which targets `surface`.
1322    ///
1323    /// # Panics
1324    ///
1325    /// - A old [`SwapChainFrame`] is still alive referencing an old swapchain.
1326    /// - Texture format requested is unsupported on the swap chain.
1327    pub fn create_swap_chain(&self, surface: &Surface, desc: &SwapChainDescriptor) -> SwapChain {
1328        SwapChain {
1329            context: Arc::clone(&self.context),
1330            id: Context::device_create_swap_chain(&*self.context, &self.id, &surface.id, desc),
1331        }
1332    }
1333}
1334
1335impl Drop for Device {
1336    fn drop(&mut self) {
1337        if !thread::panicking() {
1338            self.context.device_drop(&self.id);
1339        }
1340    }
1341}
1342
1343/// Requesting a device failed.
1344#[derive(Clone, PartialEq, Eq, Debug)]
1345pub struct RequestDeviceError;
1346
1347/// Error occurred when trying to async map a number.
1348#[derive(Clone, PartialEq, Eq, Debug)]
1349pub struct BufferAsyncError;
1350
1351/// Type of buffer mapping.
1352#[derive(Debug, Clone, Copy, PartialEq)]
1353pub enum MapMode {
1354    /// Map only for reading
1355    Read,
1356    /// Map only for writing
1357    Write,
1358}
1359
1360fn range_to_offset_size<S: RangeBounds<BufferAddress>>(
1361    bounds: S,
1362) -> (BufferAddress, Option<BufferSize>) {
1363    let offset = match bounds.start_bound() {
1364        Bound::Included(&bound) => bound,
1365        Bound::Excluded(&bound) => bound + 1,
1366        Bound::Unbounded => 0,
1367    };
1368    let size = match bounds.end_bound() {
1369        Bound::Included(&bound) => BufferSize::new(bound + 1 - offset),
1370        Bound::Excluded(&bound) => BufferSize::new(bound - offset),
1371        Bound::Unbounded => None,
1372    };
1373
1374    (offset, size)
1375}
1376
1377/// Read only view into a mapped buffer.
1378pub struct BufferView<'a> {
1379    slice: BufferSlice<'a>,
1380    data: &'a [u8],
1381}
1382
1383/// Write only view into mapped buffer.
1384pub struct BufferViewMut<'a> {
1385    slice: BufferSlice<'a>,
1386    data: &'a mut [u8],
1387    readable: bool,
1388}
1389
1390impl std::ops::Deref for BufferView<'_> {
1391    type Target = [u8];
1392
1393    fn deref(&self) -> &[u8] {
1394        self.data
1395    }
1396}
1397
1398impl std::ops::Deref for BufferViewMut<'_> {
1399    type Target = [u8];
1400
1401    fn deref(&self) -> &[u8] {
1402        assert!(
1403            self.readable,
1404            "Attempting to read a write-only mapping for buffer {:?}",
1405            self.slice.buffer.id
1406        );
1407        self.data
1408    }
1409}
1410
1411impl std::ops::DerefMut for BufferViewMut<'_> {
1412    fn deref_mut(&mut self) -> &mut Self::Target {
1413        self.data
1414    }
1415}
1416
1417impl Drop for BufferView<'_> {
1418    fn drop(&mut self) {
1419        self.slice
1420            .buffer
1421            .map_context
1422            .lock()
1423            .remove(self.slice.offset, self.slice.size);
1424    }
1425}
1426
1427impl Drop for BufferViewMut<'_> {
1428    fn drop(&mut self) {
1429        self.slice
1430            .buffer
1431            .map_context
1432            .lock()
1433            .remove(self.slice.offset, self.slice.size);
1434    }
1435}
1436
1437impl Buffer {
1438    /// Use only a portion of this Buffer for a given operation. Choosing a range with no end
1439    /// will use the rest of the buffer. Using a totally unbounded range will use the entire buffer.
1440    pub fn slice<S: RangeBounds<BufferAddress>>(&self, bounds: S) -> BufferSlice {
1441        let (offset, size) = range_to_offset_size(bounds);
1442        BufferSlice {
1443            buffer: self,
1444            offset,
1445            size,
1446        }
1447    }
1448
1449    /// Flushes any pending write operations and unmaps the buffer from host memory.
1450    pub fn unmap(&self) {
1451        self.map_context.lock().reset();
1452        Context::buffer_unmap(&*self.context, &self.id);
1453    }
1454}
1455
1456impl<'a> BufferSlice<'a> {
1457    //TODO: fn slice(&self) -> Self
1458
1459    /// Map the buffer. Buffer is ready to map once the future is resolved.
1460    ///
1461    /// For the future to complete, `device.poll(...)` must be called elsewhere in the runtime, possibly integrated
1462    /// into an event loop, run on a separate thread, or continually polled in the same task runtime that this
1463    /// future will be run on.
1464    ///
1465    /// It's expected that wgpu will eventually supply its own event loop infrastructure that will be easy to integrate
1466    /// into other event loops, like winit's.
1467    pub fn map_async(
1468        &self,
1469        mode: MapMode,
1470    ) -> impl Future<Output = Result<(), BufferAsyncError>> + Send {
1471        let end = {
1472            let mut mc = self.buffer.map_context.lock();
1473            assert_eq!(
1474                mc.initial_range,
1475                0..0,
1476                "Buffer {:?} is already mapped",
1477                self.buffer.id
1478            );
1479            let end = match self.size {
1480                Some(s) => self.offset + s.get(),
1481                None => mc.total_size,
1482            };
1483            mc.initial_range = self.offset..end;
1484            end
1485        };
1486        Context::buffer_map_async(
1487            &*self.buffer.context,
1488            &self.buffer.id,
1489            mode,
1490            self.offset..end,
1491        )
1492    }
1493
1494    /// Synchronously and immediately map a buffer for reading. If the buffer is not immediately mappable
1495    /// through [`BufferDescriptor::mapped_at_creation`] or [`BufferSlice::map_async`], will panic.
1496    pub fn get_mapped_range(&self) -> BufferView<'a> {
1497        let end = self.buffer.map_context.lock().add(self.offset, self.size);
1498        let data = Context::buffer_get_mapped_range(
1499            &*self.buffer.context,
1500            &self.buffer.id,
1501            self.offset..end,
1502        );
1503        BufferView { slice: *self, data }
1504    }
1505
1506    /// Synchronously and immediately map a buffer for writing. If the buffer is not immediately mappable
1507    /// through [`BufferDescriptor::mapped_at_creation`] or [`BufferSlice::map_async`], will panic.
1508    pub fn get_mapped_range_mut(&self) -> BufferViewMut<'a> {
1509        let end = self.buffer.map_context.lock().add(self.offset, self.size);
1510        let data = Context::buffer_get_mapped_range_mut(
1511            &*self.buffer.context,
1512            &self.buffer.id,
1513            self.offset..end,
1514        );
1515        BufferViewMut {
1516            slice: *self,
1517            data,
1518            readable: self.buffer.usage.contains(BufferUsage::MAP_READ),
1519        }
1520    }
1521}
1522
1523impl Drop for Buffer {
1524    fn drop(&mut self) {
1525        if !thread::panicking() {
1526            self.context.buffer_drop(&self.id);
1527        }
1528    }
1529}
1530
1531impl Texture {
1532    /// Creates a view of this texture.
1533    pub fn create_view(&self, desc: &TextureViewDescriptor) -> TextureView {
1534        TextureView {
1535            context: Arc::clone(&self.context),
1536            id: Context::texture_create_view(&*self.context, &self.id, Some(desc)),
1537            owned: true,
1538        }
1539    }
1540
1541    /// Creates the default view of this whole texture. This is likely what you want.
1542    pub fn create_default_view(&self) -> TextureView {
1543        TextureView {
1544            context: Arc::clone(&self.context),
1545            id: Context::texture_create_view(&*self.context, &self.id, None),
1546            owned: true,
1547        }
1548    }
1549}
1550
1551impl Drop for Texture {
1552    fn drop(&mut self) {
1553        if self.owned && !thread::panicking() {
1554            self.context.texture_drop(&self.id);
1555        }
1556    }
1557}
1558
1559impl Drop for TextureView {
1560    fn drop(&mut self) {
1561        if self.owned && !thread::panicking() {
1562            self.context.texture_view_drop(&self.id);
1563        }
1564    }
1565}
1566
1567impl CommandEncoder {
1568    /// Finishes recording and returns a [`CommandBuffer`] that can be submitted for execution.
1569    pub fn finish(self) -> CommandBuffer {
1570        CommandBuffer {
1571            context: Arc::clone(&self.context),
1572            id: Some(Context::command_encoder_finish(&*self.context, &self.id)),
1573        }
1574    }
1575
1576    /// Begins recording of a render pass.
1577    ///
1578    /// This function returns a [`RenderPass`] object which records a single render pass.
1579    pub fn begin_render_pass<'a>(
1580        &'a mut self,
1581        desc: &RenderPassDescriptor<'a, '_>,
1582    ) -> RenderPass<'a> {
1583        RenderPass {
1584            id: Context::command_encoder_begin_render_pass(&*self.context, &self.id, desc),
1585            parent: self,
1586        }
1587    }
1588
1589    /// Begins recording of a compute pass.
1590    ///
1591    /// This function returns a [`ComputePass`] object which records a single compute pass.
1592    pub fn begin_compute_pass(&mut self) -> ComputePass {
1593        ComputePass {
1594            id: Context::command_encoder_begin_compute_pass(&*self.context, &self.id),
1595            parent: self,
1596        }
1597    }
1598
1599    /// Copy data from one buffer to another.
1600    ///
1601    /// # Panics
1602    ///
1603    /// - Buffer offsets or copy size not a multiple of [`COPY_BUFFER_ALIGNMENT`].
1604    /// - Copy would overrun buffer.
1605    pub fn copy_buffer_to_buffer(
1606        &mut self,
1607        source: &Buffer,
1608        source_offset: BufferAddress,
1609        destination: &Buffer,
1610        destination_offset: BufferAddress,
1611        copy_size: BufferAddress,
1612    ) {
1613        Context::command_encoder_copy_buffer_to_buffer(
1614            &*self.context,
1615            &self.id,
1616            &source.id,
1617            source_offset,
1618            &destination.id,
1619            destination_offset,
1620            copy_size,
1621        );
1622    }
1623
1624    /// Copy data from a buffer to a texture.
1625    ///
1626    /// # Panics
1627    ///
1628    /// - Copy would overrun buffer.
1629    /// - Copy would overrun texture.
1630    /// - `source.layout.bytes_per_row` isn't divisible by [`COPY_BYTES_PER_ROW_ALIGNMENT`].
1631    pub fn copy_buffer_to_texture(
1632        &mut self,
1633        source: BufferCopyView,
1634        destination: TextureCopyView,
1635        copy_size: Extent3d,
1636    ) {
1637        Context::command_encoder_copy_buffer_to_texture(
1638            &*self.context,
1639            &self.id,
1640            source,
1641            destination,
1642            copy_size,
1643        );
1644    }
1645
1646    /// Copy data from a texture to a buffer.
1647    ///
1648    /// # Panics
1649    ///
1650    /// - Copy would overrun buffer.
1651    /// - Copy would overrun texture.
1652    /// - `source.layout.bytes_per_row` isn't divisible by [`COPY_BYTES_PER_ROW_ALIGNMENT`].
1653    pub fn copy_texture_to_buffer(
1654        &mut self,
1655        source: TextureCopyView,
1656        destination: BufferCopyView,
1657        copy_size: Extent3d,
1658    ) {
1659        Context::command_encoder_copy_texture_to_buffer(
1660            &*self.context,
1661            &self.id,
1662            source,
1663            destination,
1664            copy_size,
1665        );
1666    }
1667
1668    /// Copy data from one texture to another.
1669    ///
1670    /// # Panics
1671    ///
1672    /// - Textures are not the same type
1673    /// - If a depth texture, or a multisampled texture, the entire texture must be copied
1674    /// - Copy would overrun either texture
1675    pub fn copy_texture_to_texture(
1676        &mut self,
1677        source: TextureCopyView,
1678        destination: TextureCopyView,
1679        copy_size: Extent3d,
1680    ) {
1681        Context::command_encoder_copy_texture_to_texture(
1682            &*self.context,
1683            &self.id,
1684            source,
1685            destination,
1686            copy_size,
1687        );
1688    }
1689}
1690
1691impl<'a> RenderPass<'a> {
1692    /// Sets the active bind group for a given bind group index. The bind group layout
1693    /// in the active pipeline when any `draw()` function is called must match the layout of this bind group.
1694    ///
1695    /// If the bind group have dynamic offsets, provide them in order of their declaration.
1696    pub fn set_bind_group(
1697        &mut self,
1698        index: u32,
1699        bind_group: &'a BindGroup,
1700        offsets: &[DynamicOffset],
1701    ) {
1702        RenderInner::set_bind_group(&mut self.id, index, &bind_group.id, offsets)
1703    }
1704
1705    /// Sets the active render pipeline.
1706    ///
1707    /// Subsequent draw calls will exhibit the behavior defined by `pipeline`.
1708    pub fn set_pipeline(&mut self, pipeline: &'a RenderPipeline) {
1709        RenderInner::set_pipeline(&mut self.id, &pipeline.id)
1710    }
1711
1712    /// Sets the blend color as used by some of the blending modes.
1713    ///
1714    /// Subsequent blending tests will test against this value.
1715    pub fn set_blend_color(&mut self, color: Color) {
1716        self.id.set_blend_color(color)
1717    }
1718
1719    /// Sets the active index buffer.
1720    ///
1721    /// Subsequent calls to [`draw_indexed`](RenderPass::draw_indexed) on this [`RenderPass`] will
1722    /// use `buffer` as the source index buffer.
1723    pub fn set_index_buffer(&mut self, buffer_slice: BufferSlice<'a>) {
1724        RenderInner::set_index_buffer(
1725            &mut self.id,
1726            &buffer_slice.buffer.id,
1727            buffer_slice.offset,
1728            buffer_slice.size,
1729        )
1730    }
1731
1732    /// Assign a vertex buffer to a slot.
1733    ///
1734    /// Subsequent calls to [`draw`] and [`draw_indexed`] on this
1735    /// [`RenderPass`] will use `buffer` as one of the source vertex buffers.
1736    ///
1737    /// The `slot` refers to the index of the matching descriptor in
1738    /// [`VertexStateDescriptor::vertex_buffers`].
1739    ///
1740    /// [`draw`]: RenderPass::draw
1741    /// [`draw_indexed`]: RenderPass::draw_indexed
1742    pub fn set_vertex_buffer(&mut self, slot: u32, buffer_slice: BufferSlice<'a>) {
1743        RenderInner::set_vertex_buffer(
1744            &mut self.id,
1745            slot,
1746            &buffer_slice.buffer.id,
1747            buffer_slice.offset,
1748            buffer_slice.size,
1749        )
1750    }
1751
1752    /// Sets the scissor region.
1753    ///
1754    /// Subsequent draw calls will discard any fragments that fall outside this region.
1755    pub fn set_scissor_rect(&mut self, x: u32, y: u32, width: u32, height: u32) {
1756        self.id.set_scissor_rect(x, y, width, height);
1757    }
1758
1759    /// Sets the viewport region.
1760    ///
1761    /// Subsequent draw calls will draw any fragments in this region.
1762    pub fn set_viewport(&mut self, x: f32, y: f32, w: f32, h: f32, min_depth: f32, max_depth: f32) {
1763        self.id.set_viewport(x, y, w, h, min_depth, max_depth);
1764    }
1765
1766    /// Sets the stencil reference.
1767    ///
1768    /// Subsequent stencil tests will test against this value.
1769    pub fn set_stencil_reference(&mut self, reference: u32) {
1770        self.id.set_stencil_reference(reference);
1771    }
1772
1773    /// Draws primitives from the active vertex buffer(s).
1774    ///
1775    /// The active vertex buffers can be set with [`RenderPass::set_vertex_buffer`].
1776    pub fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>) {
1777        RenderInner::draw(&mut self.id, vertices, instances)
1778    }
1779
1780    /// Inserts debug marker.
1781    pub fn insert_debug_marker(&mut self, label: &str) {
1782        self.id.insert_debug_marker(label);
1783    }
1784
1785    /// Start record commands and group it into debug marker group.
1786    pub fn push_debug_group(&mut self, label: &str) {
1787        self.id.push_debug_group(label);
1788    }
1789
1790    /// Stops command recording and creates debug group.
1791    pub fn pop_debug_group(&mut self) {
1792        self.id.pop_debug_group();
1793    }
1794
1795    /// Draws indexed primitives using the active index buffer and the active vertex buffers.
1796    ///
1797    /// The active index buffer can be set with [`RenderPass::set_index_buffer`], while the active
1798    /// vertex buffers can be set with [`RenderPass::set_vertex_buffer`].
1799    pub fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>) {
1800        RenderInner::draw_indexed(&mut self.id, indices, base_vertex, instances);
1801    }
1802
1803    /// Draws primitives from the active vertex buffer(s) based on the contents of the `indirect_buffer`.
1804    ///
1805    /// The active vertex buffers can be set with [`RenderPass::set_vertex_buffer`].
1806    ///
1807    /// The structure expected in `indirect_buffer` is the following:
1808    ///
1809    /// ```rust
1810    /// #[repr(C)]
1811    /// struct DrawIndirect {
1812    ///     vertex_count: u32, // The number of vertices to draw.
1813    ///     instance_count: u32, // The number of instances to draw.
1814    ///     base_vertex: u32, // The Index of the first vertex to draw.
1815    ///     base_instance: u32, // The instance ID of the first instance to draw.
1816    /// }
1817    /// ```
1818    pub fn draw_indirect(&mut self, indirect_buffer: &'a Buffer, indirect_offset: BufferAddress) {
1819        self.id.draw_indirect(&indirect_buffer.id, indirect_offset);
1820    }
1821
1822    /// Draws indexed primitives using the active index buffer and the active vertex buffers,
1823    /// based on the contents of the `indirect_buffer`.
1824    ///
1825    /// The active index buffer can be set with [`RenderPass::set_index_buffer`], while the active
1826    /// vertex buffers can be set with [`RenderPass::set_vertex_buffer`].
1827    ///
1828    /// The structure expected in `indirect_buffer` is the following:
1829    ///
1830    /// ```rust
1831    /// #[repr(C)]
1832    /// struct DrawIndexedIndirect {
1833    ///     vertex_count: u32, // The number of vertices to draw.
1834    ///     instance_count: u32, // The number of instances to draw.
1835    ///     base_index: u32, // The base index within the index buffer.
1836    ///     vertex_offset: i32, // The value added to the vertex index before indexing into the vertex buffer.
1837    ///     base_instance: u32, // The instance ID of the first instance to draw.
1838    /// }
1839    /// ```
1840    pub fn draw_indexed_indirect(
1841        &mut self,
1842        indirect_buffer: &'a Buffer,
1843        indirect_offset: BufferAddress,
1844    ) {
1845        self.id
1846            .draw_indexed_indirect(&indirect_buffer.id, indirect_offset);
1847    }
1848
1849    /// Execute a [render bundle][RenderBundle], which is a set of pre-recorded commands
1850    /// that can be run together.
1851    pub fn execute_bundles<I: Iterator<Item = &'a RenderBundle>>(&mut self, render_bundles: I) {
1852        self.id
1853            .execute_bundles(render_bundles.into_iter().map(|rb| &rb.id))
1854    }
1855}
1856
1857/// [`Features::MULTI_DRAW_INDIRECT`] must be enabled on the device in order to call these functions.
1858impl<'a> RenderPass<'a> {
1859    /// Disptaches multiple draw calls from the active vertex buffer(s) based on the contents of the `indirect_buffer`.
1860    /// `count` draw calls are issued.
1861    ///
1862    /// The active vertex buffers can be set with [`RenderPass::set_vertex_buffer`].
1863    ///
1864    /// The structure expected in `indirect_buffer` is the following:
1865    ///
1866    /// ```rust
1867    /// #[repr(C)]
1868    /// struct DrawIndirect {
1869    ///     vertex_count: u32, // The number of vertices to draw.
1870    ///     instance_count: u32, // The number of instances to draw.
1871    ///     base_vertex: u32, // The Index of the first vertex to draw.
1872    ///     base_instance: u32, // The instance ID of the first instance to draw.
1873    /// }
1874    /// ```
1875    ///
1876    /// These draw structures are expected to be tightly packed.
1877    pub fn multi_draw_indirect(
1878        &mut self,
1879        indirect_buffer: &'a Buffer,
1880        indirect_offset: BufferAddress,
1881        count: u32,
1882    ) {
1883        self.id
1884            .multi_draw_indirect(&indirect_buffer.id, indirect_offset, count);
1885    }
1886
1887    /// Disptaches multiple draw calls from the active index buffer and the active vertex buffers,
1888    /// based on the contents of the `indirect_buffer`. `count` draw calls are issued.
1889    ///
1890    /// The active index buffer can be set with [`RenderPass::set_index_buffer`], while the active
1891    /// vertex buffers can be set with [`RenderPass::set_vertex_buffer`].
1892    ///
1893    /// The structure expected in `indirect_buffer` is the following:
1894    ///
1895    /// ```rust
1896    /// #[repr(C)]
1897    /// struct DrawIndexedIndirect {
1898    ///     vertex_count: u32, // The number of vertices to draw.
1899    ///     instance_count: u32, // The number of instances to draw.
1900    ///     base_index: u32, // The base index within the index buffer.
1901    ///     vertex_offset: i32, // The value added to the vertex index before indexing into the vertex buffer.
1902    ///     base_instance: u32, // The instance ID of the first instance to draw.
1903    /// }
1904    /// ```
1905    ///
1906    /// These draw structures are expected to be tightly packed.
1907    pub fn multi_draw_indexed_indirect(
1908        &mut self,
1909        indirect_buffer: &'a Buffer,
1910        indirect_offset: BufferAddress,
1911        count: u32,
1912    ) {
1913        self.id
1914            .multi_draw_indexed_indirect(&indirect_buffer.id, indirect_offset, count);
1915    }
1916}
1917
1918/// [`Features::MULTI_DRAW_INDIRECT_COUNT`] must be enabled on the device in order to call these functions.
1919impl<'a> RenderPass<'a> {
1920    /// Disptaches multiple draw calls from the active vertex buffer(s) based on the contents of the `indirect_buffer`.
1921    /// The count buffer is read to determine how many draws to issue.
1922    ///
1923    /// The indirect buffer must be long enough to account for `max_count` draws, however only `count` will
1924    /// draws will be read. If `count` is greater than `max_count`, `max_count` will be used.
1925    ///
1926    /// The active vertex buffers can be set with [`RenderPass::set_vertex_buffer`].
1927    ///
1928    /// The structure expected in `indirect_buffer` is the following:
1929    ///
1930    /// ```rust
1931    /// #[repr(C)]
1932    /// struct DrawIndirect {
1933    ///     vertex_count: u32, // The number of vertices to draw.
1934    ///     instance_count: u32, // The number of instances to draw.
1935    ///     base_vertex: u32, // The Index of the first vertex to draw.
1936    ///     base_instance: u32, // The instance ID of the first instance to draw.
1937    /// }
1938    /// ```
1939    ///
1940    /// These draw structures are expected to be tightly packed.
1941    ///
1942    /// The structure expected in `count_buffer` is the following:
1943    ///
1944    /// ```rust
1945    /// #[repr(C)]
1946    /// struct DrawIndirectCount {
1947    ///     count: u32, // Number of draw calls to issue.
1948    /// }
1949    /// ```
1950    pub fn multi_draw_indirect_count(
1951        &mut self,
1952        indirect_buffer: &'a Buffer,
1953        indirect_offset: BufferAddress,
1954        count_buffer: &'a Buffer,
1955        count_offset: BufferAddress,
1956        max_count: u32,
1957    ) {
1958        self.id.multi_draw_indirect_count(
1959            &indirect_buffer.id,
1960            indirect_offset,
1961            &count_buffer.id,
1962            count_offset,
1963            max_count,
1964        );
1965    }
1966
1967    /// Disptaches multiple draw calls from the active index buffer and the active vertex buffers,
1968    /// based on the contents of the `indirect_buffer`. The count buffer is read to determine how many draws to issue.
1969    ///
1970    /// The indirect buffer must be long enough to account for `max_count` draws, however only `count` will
1971    /// draws will be read. If `count` is greater than `max_count`, `max_count` will be used.
1972    ///
1973    /// The active index buffer can be set with [`RenderPass::set_index_buffer`], while the active
1974    /// vertex buffers can be set with [`RenderPass::set_vertex_buffer`].
1975    ///
1976    /// The structure expected in `indirect_buffer` is the following:
1977    ///
1978    /// ```rust
1979    /// #[repr(C)]
1980    /// struct DrawIndexedIndirect {
1981    ///     vertex_count: u32, // The number of vertices to draw.
1982    ///     instance_count: u32, // The number of instances to draw.
1983    ///     base_index: u32, // The base index within the index buffer.
1984    ///     vertex_offset: i32, // The value added to the vertex index before indexing into the vertex buffer.
1985    ///     base_instance: u32, // The instance ID of the first instance to draw.
1986    /// }
1987    /// ```
1988    ///
1989    /// These draw structures are expected to be tightly packed.
1990    ///
1991    /// The structure expected in `count_buffer` is the following:
1992    ///
1993    /// ```rust
1994    /// #[repr(C)]
1995    /// struct DrawIndexedIndirectCount {
1996    ///     count: u32, // Number of draw calls to issue.
1997    /// }
1998    /// ```
1999    pub fn multi_draw_indexed_indirect_count(
2000        &mut self,
2001        indirect_buffer: &'a Buffer,
2002        indirect_offset: BufferAddress,
2003        count_buffer: &'a Buffer,
2004        count_offset: BufferAddress,
2005        max_count: u32,
2006    ) {
2007        self.id.multi_draw_indexed_indirect_count(
2008            &indirect_buffer.id,
2009            indirect_offset,
2010            &count_buffer.id,
2011            count_offset,
2012            max_count,
2013        );
2014    }
2015}
2016
2017impl<'a> Drop for RenderPass<'a> {
2018    fn drop(&mut self) {
2019        if !thread::panicking() {
2020            self.parent
2021                .context
2022                .command_encoder_end_render_pass(&self.parent.id, &mut self.id);
2023        }
2024    }
2025}
2026
2027impl<'a> ComputePass<'a> {
2028    /// Sets the active bind group for a given bind group index. The bind group layout
2029    /// in the active pipeline when the `dispatch()` function is called must match the layout of this bind group.
2030    ///
2031    /// If the bind group have dynamic offsets, provide them in order of their declaration.
2032    pub fn set_bind_group(
2033        &mut self,
2034        index: u32,
2035        bind_group: &'a BindGroup,
2036        offsets: &[DynamicOffset],
2037    ) {
2038        ComputePassInner::set_bind_group(&mut self.id, index, &bind_group.id, offsets);
2039    }
2040
2041    /// Sets the active compute pipeline.
2042    pub fn set_pipeline(&mut self, pipeline: &'a ComputePipeline) {
2043        ComputePassInner::set_pipeline(&mut self.id, &pipeline.id);
2044    }
2045
2046    /// Dispatches compute work operations.
2047    ///
2048    /// `x`, `y` and `z` denote the number of work groups to dispatch in each dimension.
2049    pub fn dispatch(&mut self, x: u32, y: u32, z: u32) {
2050        ComputePassInner::dispatch(&mut self.id, x, y, z);
2051    }
2052
2053    /// Dispatches compute work operations, based on the contents of the `indirect_buffer`.
2054    pub fn dispatch_indirect(
2055        &mut self,
2056        indirect_buffer: &'a Buffer,
2057        indirect_offset: BufferAddress,
2058    ) {
2059        ComputePassInner::dispatch_indirect(&mut self.id, &indirect_buffer.id, indirect_offset);
2060    }
2061}
2062
2063impl<'a> Drop for ComputePass<'a> {
2064    fn drop(&mut self) {
2065        if !thread::panicking() {
2066            self.parent
2067                .context
2068                .command_encoder_end_compute_pass(&self.parent.id, &mut self.id);
2069        }
2070    }
2071}
2072
2073impl<'a> RenderBundleEncoder<'a> {
2074    /// Finishes recording and returns a [`RenderBundle`] that can be executed in other render passes.
2075    pub fn finish(self, desc: &RenderBundleDescriptor) -> RenderBundle {
2076        RenderBundle {
2077            context: Arc::clone(&self.context),
2078            id: Context::render_bundle_encoder_finish(&*self.context, self.id, desc),
2079        }
2080    }
2081
2082    /// Sets the active bind group for a given bind group index. The bind group layout
2083    /// in the active pipeline when any `draw()` function is called must match the layout of this bind group.
2084    ///
2085    /// If the bind group have dynamic offsets, provide them in order of their declaration.
2086    pub fn set_bind_group(
2087        &mut self,
2088        index: u32,
2089        bind_group: &'a BindGroup,
2090        offsets: &[DynamicOffset],
2091    ) {
2092        RenderInner::set_bind_group(&mut self.id, index, &bind_group.id, offsets)
2093    }
2094
2095    /// Sets the active render pipeline.
2096    ///
2097    /// Subsequent draw calls will exhibit the behavior defined by `pipeline`.
2098    pub fn set_pipeline(&mut self, pipeline: &'a RenderPipeline) {
2099        RenderInner::set_pipeline(&mut self.id, &pipeline.id)
2100    }
2101
2102    /// Sets the active index buffer.
2103    ///
2104    /// Subsequent calls to [`draw_indexed`](RenderBundleEncoder::draw_indexed) on this [`RenderBundleEncoder`] will
2105    /// use `buffer` as the source index buffer.
2106    pub fn set_index_buffer(&mut self, buffer_slice: BufferSlice<'a>) {
2107        RenderInner::set_index_buffer(
2108            &mut self.id,
2109            &buffer_slice.buffer.id,
2110            buffer_slice.offset,
2111            buffer_slice.size,
2112        )
2113    }
2114
2115    /// Assign a vertex buffer to a slot.
2116    ///
2117    /// Subsequent calls to [`draw`] and [`draw_indexed`] on this
2118    /// [`RenderBundleEncoder`] will use `buffer` as one of the source vertex buffers.
2119    ///
2120    /// The `slot` refers to the index of the matching descriptor in
2121    /// [`VertexStateDescriptor::vertex_buffers`].
2122    ///
2123    /// [`draw`]: RenderBundleEncoder::draw
2124    /// [`draw_indexed`]: RenderBundleEncoder::draw_indexed
2125    pub fn set_vertex_buffer(&mut self, slot: u32, buffer_slice: BufferSlice<'a>) {
2126        RenderInner::set_vertex_buffer(
2127            &mut self.id,
2128            slot,
2129            &buffer_slice.buffer.id,
2130            buffer_slice.offset,
2131            buffer_slice.size,
2132        )
2133    }
2134
2135    /// Draws primitives from the active vertex buffer(s).
2136    ///
2137    /// The active vertex buffers can be set with [`RenderBundleEncoder::set_vertex_buffer`].
2138    pub fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>) {
2139        RenderInner::draw(&mut self.id, vertices, instances)
2140    }
2141
2142    /// Draws indexed primitives using the active index buffer and the active vertex buffers.
2143    ///
2144    /// The active index buffer can be set with [`RenderBundleEncoder::set_index_buffer`], while the active
2145    /// vertex buffers can be set with [`RenderBundleEncoder::set_vertex_buffer`].
2146    pub fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>) {
2147        RenderInner::draw_indexed(&mut self.id, indices, base_vertex, instances);
2148    }
2149
2150    /// Draws primitives from the active vertex buffer(s) based on the contents of the `indirect_buffer`.
2151    ///
2152    /// The active vertex buffers can be set with [`RenderBundleEncoder::set_vertex_buffer`].
2153    ///
2154    /// The structure expected in `indirect_buffer` is the following:
2155    ///
2156    /// ```rust
2157    /// #[repr(C)]
2158    /// struct DrawIndirect {
2159    ///     vertex_count: u32, // The number of vertices to draw.
2160    ///     instance_count: u32, // The number of instances to draw.
2161    ///     base_vertex: u32, // The Index of the first vertex to draw.
2162    ///     base_instance: u32, // The instance ID of the first instance to draw.
2163    /// }
2164    /// ```
2165    pub fn draw_indirect(&mut self, indirect_buffer: &'a Buffer, indirect_offset: BufferAddress) {
2166        self.id.draw_indirect(&indirect_buffer.id, indirect_offset);
2167    }
2168
2169    /// Draws indexed primitives using the active index buffer and the active vertex buffers,
2170    /// based on the contents of the `indirect_buffer`.
2171    ///
2172    /// The active index buffer can be set with [`RenderBundleEncoder::set_index_buffer`], while the active
2173    /// vertex buffers can be set with [`RenderBundleEncoder::set_vertex_buffer`].
2174    ///
2175    /// The structure expected in `indirect_buffer` is the following:
2176    ///
2177    /// ```rust
2178    /// #[repr(C)]
2179    /// struct DrawIndexedIndirect {
2180    ///     vertex_count: u32, // The number of vertices to draw.
2181    ///     instance_count: u32, // The number of instances to draw.
2182    ///     base_index: u32, // The base index within the index buffer.
2183    ///     vertex_offset: i32, // The value added to the vertex index before indexing into the vertex buffer.
2184    ///     base_instance: u32, // The instance ID of the first instance to draw.
2185    /// }
2186    /// ```
2187    pub fn draw_indexed_indirect(
2188        &mut self,
2189        indirect_buffer: &'a Buffer,
2190        indirect_offset: BufferAddress,
2191    ) {
2192        self.id
2193            .draw_indexed_indirect(&indirect_buffer.id, indirect_offset);
2194    }
2195}
2196
2197impl Queue {
2198    /// Schedule a data write into `buffer` starting at `offset`.
2199    pub fn write_buffer(&self, buffer: &Buffer, offset: BufferAddress, data: &[u8]) {
2200        Context::queue_write_buffer(&*self.context, &self.id, &buffer.id, offset, data)
2201    }
2202
2203    /// Schedule a data write into `texture`.
2204    pub fn write_texture(
2205        &self,
2206        texture: TextureCopyView,
2207        data: &[u8],
2208        data_layout: TextureDataLayout,
2209        size: Extent3d,
2210    ) {
2211        Context::queue_write_texture(&*self.context, &self.id, texture, data, data_layout, size)
2212    }
2213
2214    /// Submits a series of finished command buffers for execution.
2215    pub fn submit<I: IntoIterator<Item = CommandBuffer>>(&self, command_buffers: I) {
2216        Context::queue_submit(
2217            &*self.context,
2218            &self.id,
2219            command_buffers
2220                .into_iter()
2221                .map(|mut comb| comb.id.take().unwrap()),
2222        );
2223    }
2224}
2225
2226impl Drop for SwapChainTexture {
2227    fn drop(&mut self) {
2228        if !thread::panicking() {
2229            Context::swap_chain_present(&*self.view.context, &self.view.id, &self.detail);
2230        }
2231    }
2232}
2233
2234impl SwapChain {
2235    /// Returns the next texture to be presented by the swapchain for drawing.
2236    ///
2237    /// When the [`SwapChainFrame`] returned by this method is dropped, the swapchain will present
2238    /// the texture to the associated [`Surface`].
2239    ///
2240    /// If a SwapChainFrame referencing this surface is alive when the swapchain is recreated,
2241    /// recreating the swapchain will panic.
2242    pub fn get_next_frame(&mut self) -> Result<SwapChainFrame, SwapChainError> {
2243        let (view_id, status, detail) =
2244            Context::swap_chain_get_next_texture(&*self.context, &self.id);
2245        let output = view_id.map(|id| SwapChainTexture {
2246            view: TextureView {
2247                context: Arc::clone(&self.context),
2248                id: id,
2249                owned: false,
2250            },
2251            detail,
2252        });
2253
2254        match status {
2255            SwapChainStatus::Good => Ok(SwapChainFrame {
2256                output: output.unwrap(),
2257                suboptimal: false,
2258            }),
2259            SwapChainStatus::Suboptimal => Ok(SwapChainFrame {
2260                output: output.unwrap(),
2261                suboptimal: true,
2262            }),
2263            SwapChainStatus::Timeout => Err(SwapChainError::Timeout),
2264            SwapChainStatus::Outdated => Err(SwapChainError::Outdated),
2265            SwapChainStatus::Lost => Err(SwapChainError::Lost),
2266            SwapChainStatus::OutOfMemory => Err(SwapChainError::OutOfMemory),
2267        }
2268    }
2269}