wgpu/backend/
wgpu_core.rs

1use alloc::borrow::ToOwned;
2use alloc::{
3    borrow::Cow::{self, Borrowed},
4    boxed::Box,
5    string::{String, ToString as _},
6    sync::Arc,
7    vec,
8    vec::Vec,
9};
10use core::{
11    error::Error,
12    fmt,
13    future::ready,
14    ops::{Deref, Range},
15    pin::Pin,
16    ptr::NonNull,
17    slice,
18};
19use wgc::resource::ParentDevice as _;
20use wgt::error::WebGpuError;
21
22use arrayvec::ArrayVec;
23use smallvec::SmallVec;
24use wgc::{pipeline::CreateShaderModuleError, resource::BlasPrepareCompactResult};
25use wgt::WasmNotSendSync;
26
27use crate::{
28    api,
29    dispatch::{self, BlasCompactCallback, BufferMappedRangeInterface},
30    BindingResource, Blas, BufferBinding, BufferDescriptor, CompilationInfo, CompilationMessage,
31    CompilationMessageType, Features, LoadOp, MapMode, Operations, ShaderSource,
32    SurfaceTargetUnsafe, TextureDescriptor, Tlas, WriteOnly,
33};
34use crate::{dispatch::DispatchAdapter, util::Mutex};
35
36use wgc::error::format_error;
37
38#[derive(Clone)]
39pub struct ContextWgpuCore(Arc<wgc::instance::Instance>);
40
41impl fmt::Debug for ContextWgpuCore {
42    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43        f.debug_struct("ContextWgpuCore")
44            .field("type", &"Native")
45            .finish()
46    }
47}
48
49#[track_caller]
50#[cold]
51fn handle_error_fatal(cause: impl Error + WasmNotSendSync + 'static, operation: &'static str) -> ! {
52    panic!("Error in {operation}: {f}", f = format_error(&cause));
53}
54
55impl ContextWgpuCore {
56    pub unsafe fn from_hal_instance<A: hal::Api>(hal_instance: A::Instance) -> Self {
57        Self(wgc::instance::Instance::from_hal_instance::<A>(
58            "wgpu".to_owned(),
59            hal_instance,
60        ))
61    }
62
63    /// # Safety
64    ///
65    /// - The raw instance handle returned must not be manually destroyed.
66    pub unsafe fn instance_as_hal<A: hal::Api>(&self) -> Option<&A::Instance> {
67        unsafe { self.0.as_hal::<A>() }
68    }
69
70    pub fn from_core_instance(core_instance: Arc<wgc::instance::Instance>) -> Self {
71        Self(core_instance)
72    }
73
74    #[cfg(wgpu_core)]
75    pub fn enumerate_adapters(&self, backends: wgt::Backends) -> Vec<Arc<wgc::instance::Adapter>> {
76        self.0
77            .enumerate_adapters(backends, false /* no limit bucketing */)
78    }
79
80    pub unsafe fn create_adapter_from_hal<A: hal::Api>(
81        &self,
82        hal_adapter: hal::ExposedAdapter<A>,
83    ) -> Arc<wgc::instance::Adapter> {
84        unsafe { self.0.create_adapter_from_hal(hal_adapter.into()) }
85    }
86}
87
88fn map_buffer_copy_view(
89    view: crate::TexelCopyBufferInfo<'_>,
90) -> wgt::TexelCopyBufferInfo<Arc<wgc::resource::Buffer>> {
91    wgt::TexelCopyBufferInfo {
92        buffer: view.buffer.inner.as_core().wgpu_buffer.clone(),
93        layout: view.layout,
94    }
95}
96
97fn map_texture_copy_view(
98    view: crate::TexelCopyTextureInfo<'_>,
99) -> wgt::TexelCopyTextureInfo<Arc<wgc::resource::Texture>> {
100    wgt::TexelCopyTextureInfo {
101        texture: view.texture.inner.as_core().wgpu_texture.clone(),
102        mip_level: view.mip_level,
103        origin: view.origin,
104        aspect: view.aspect,
105    }
106}
107
108#[cfg_attr(not(webgl), expect(unused))]
109fn map_texture_tagged_copy_view(
110    view: crate::CopyExternalImageDestInfo<&api::Texture>,
111) -> wgt::CopyExternalImageDestInfo<Arc<wgc::resource::Texture>> {
112    wgt::CopyExternalImageDestInfo {
113        texture: view.texture.inner.as_core().wgpu_texture.clone(),
114        mip_level: view.mip_level,
115        origin: view.origin,
116        aspect: view.aspect,
117        color_space: view.color_space,
118        premultiplied_alpha: view.premultiplied_alpha,
119    }
120}
121
122fn map_load_op<V: Copy>(load: &LoadOp<V>) -> LoadOp<Option<V>> {
123    match *load {
124        LoadOp::Clear(clear_value) => LoadOp::Clear(Some(clear_value)),
125        LoadOp::DontCare(token) => LoadOp::DontCare(token),
126        LoadOp::Load => LoadOp::Load,
127    }
128}
129
130fn map_pass_channel<V: Copy>(ops: Option<&Operations<V>>) -> wgc::command::PassChannel<Option<V>> {
131    match ops {
132        Some(&Operations { load, store }) => wgc::command::PassChannel {
133            load_op: Some(map_load_op(&load)),
134            store_op: Some(store),
135            read_only: false,
136        },
137        None => wgc::command::PassChannel {
138            load_op: None,
139            store_op: None,
140            read_only: true,
141        },
142    }
143}
144
145#[derive(Clone)]
146pub struct CoreSurface {
147    pub(crate) wgpu_surface: Arc<wgc::instance::Surface>,
148    /// Configured device is needed to know which backend
149    /// code to execute when acquiring a new frame.
150    configured_device: Arc<Mutex<Option<Arc<wgc::device::Device>>>>,
151}
152
153impl fmt::Debug for CoreSurface {
154    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
155        f.debug_struct("CoreSurface")
156            .field("wgpu_surface", &Arc::as_ptr(&self.wgpu_surface))
157            .field("configured_device", &self.configured_device)
158            .finish()
159    }
160}
161
162impl CoreSurface {
163    pub unsafe fn as_hal<A: hal::Api>(&self) -> Option<impl Deref<Target = A::Surface>> {
164        unsafe { self.wgpu_surface.clone().as_hal::<A>() }
165    }
166}
167
168#[derive(Clone)]
169pub struct CoreAdapter {
170    pub(crate) wgpu_adapter: Arc<wgc::instance::Adapter>,
171}
172
173impl fmt::Debug for CoreAdapter {
174    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
175        f.debug_struct("CoreAdapter")
176            .field("wgpu_adapter", &Arc::as_ptr(&self.wgpu_adapter))
177            .finish()
178    }
179}
180
181impl CoreAdapter {
182    pub unsafe fn as_hal<A: hal::Api>(
183        &self,
184    ) -> Option<impl Deref<Target = A::Adapter> + WasmNotSendSync> {
185        unsafe { self.wgpu_adapter.clone().as_hal::<A>() }
186    }
187
188    pub unsafe fn create_device_from_hal<A: hal::Api>(
189        &self,
190        hal_device: hal::OpenDevice<A>,
191        desc: &crate::DeviceDescriptor<'_>,
192    ) -> Result<(CoreDevice, CoreQueue), crate::RequestDeviceError> {
193        let (device, queue) = unsafe {
194            self.wgpu_adapter.create_device_and_queue_from_hal(
195                hal_device.into(),
196                &desc.map_label(|l| l.map(Borrowed)),
197            )
198        }?;
199        let device = CoreDevice {
200            wgpu_device: device.clone(),
201        };
202        let queue = CoreQueue { wgpu_queue: queue };
203        Ok((device, queue))
204    }
205}
206
207#[derive(Debug, Clone)]
208pub struct CoreDevice {
209    pub(crate) wgpu_device: Arc<wgc::device::Device>,
210}
211
212impl CoreDevice {
213    pub unsafe fn as_hal<A: hal::Api>(&self) -> Option<impl Deref<Target = A::Device>> {
214        unsafe { self.wgpu_device.clone().as_hal::<A>() }
215    }
216
217    pub unsafe fn create_texture_from_hal<A: hal::Api>(
218        &self,
219        hal_texture: A::Texture,
220        desc: &TextureDescriptor<'_>,
221        initial_state: wgt::TextureUses,
222        cleared: bool,
223    ) -> CoreTexture {
224        let descriptor = desc.map_label_and_view_formats(|l| l.map(Borrowed), |v| v.to_vec());
225        let (wgpu_texture, error) = unsafe {
226            self.wgpu_device.create_texture_from_hal(
227                Box::new(hal_texture),
228                &descriptor,
229                initial_state,
230                cleared,
231            )
232        };
233        if let Some(cause) = error {
234            self.wgpu_device
235                .handle_error(cause, desc.label, "Device::create_texture_from_hal");
236        }
237        CoreTexture { wgpu_texture }
238    }
239
240    /// # Safety
241    ///
242    /// - `hal_buffer` must be created from `device`.
243    /// - `hal_buffer` must be created respecting `desc`
244    /// - `hal_buffer` must be initialized
245    /// - `hal_buffer` must not have zero size.
246    pub unsafe fn create_buffer_from_hal<A: hal::Api>(
247        &self,
248        hal_buffer: A::Buffer,
249        desc: &BufferDescriptor<'_>,
250    ) -> CoreBuffer {
251        let (wgpu_buffer, error) = unsafe {
252            self.wgpu_device
253                .create_buffer_from_hal(Box::new(hal_buffer), &desc.map_label(|l| l.map(Borrowed)))
254        };
255        if let Some(cause) = error {
256            self.wgpu_device
257                .handle_error(cause, desc.label, "Device::create_buffer_from_hal");
258        }
259        CoreBuffer { wgpu_buffer }
260    }
261
262    /// Returns `true` if `texture` was created on `device`.
263    #[cfg(webgl)]
264    pub fn texture_belongs_to_device(&self, texture: &CoreTexture) -> bool {
265        use wgc::resource::ParentDevice as _;
266        texture.wgpu_texture.same_device(&self.wgpu_device).is_ok()
267    }
268}
269
270#[derive(Debug, Clone)]
271pub struct CoreBuffer {
272    pub(crate) wgpu_buffer: Arc<wgc::resource::Buffer>,
273}
274
275impl CoreBuffer {
276    pub unsafe fn as_hal<A: hal::Api>(&self) -> Option<impl Deref<Target = A::Buffer>> {
277        unsafe { self.wgpu_buffer.clone().as_hal::<A>() }
278    }
279}
280
281#[derive(Debug, Clone)]
282pub struct CoreShaderModule {
283    pub(crate) wgpu_shader_module: Arc<wgc::pipeline::ShaderModule>,
284    compilation_info: CompilationInfo,
285}
286
287#[derive(Debug, Clone)]
288pub struct CoreBindGroupLayout {
289    pub(crate) wgpu_bind_group_layout: Arc<wgc::binding_model::BindGroupLayout>,
290}
291
292#[derive(Debug, Clone)]
293pub struct CoreBindGroup {
294    pub(crate) wgpu_bind_group: Arc<wgc::binding_model::BindGroup>,
295}
296
297#[derive(Debug, Clone)]
298pub struct CoreTexture {
299    pub(crate) wgpu_texture: Arc<wgc::resource::Texture>,
300}
301
302impl CoreTexture {
303    pub unsafe fn as_hal<A: hal::Api>(&self) -> Option<impl Deref<Target = A::Texture>> {
304        unsafe { self.wgpu_texture.clone().as_hal::<A>() }
305    }
306}
307
308#[derive(Debug, Clone)]
309pub struct CoreTextureView {
310    pub(crate) wgpu_texture_view: Arc<wgc::resource::TextureView>,
311}
312
313impl CoreTextureView {
314    pub unsafe fn as_hal<A: hal::Api>(&self) -> Option<impl Deref<Target = A::TextureView>> {
315        unsafe { self.wgpu_texture_view.clone().as_hal::<A>() }
316    }
317}
318
319#[derive(Debug, Clone)]
320pub struct CoreExternalTexture {
321    pub(crate) wgpu_external_texture: Arc<wgc::resource::ExternalTexture>,
322}
323
324#[derive(Debug, Clone)]
325pub struct CoreSampler {
326    pub(crate) wgpu_sampler: Arc<wgc::resource::Sampler>,
327}
328
329#[derive(Debug, Clone)]
330pub struct CoreQuerySet {
331    pub(crate) wgpu_query_set: Arc<wgc::resource::QuerySet>,
332}
333
334#[derive(Debug, Clone)]
335pub struct CorePipelineLayout {
336    pub(crate) wgpu_pipeline_layout: Arc<wgc::binding_model::PipelineLayout>,
337}
338
339#[derive(Debug, Clone)]
340pub struct CorePipelineCache {
341    pub(crate) wgpu_pipeline_cache: Arc<wgc::pipeline::PipelineCache>,
342}
343
344pub struct CoreCommandBuffer {
345    pub(crate) wgpu_command_buffer: Arc<wgc::command::CommandBuffer>,
346}
347
348impl fmt::Debug for CoreCommandBuffer {
349    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
350        f.debug_struct("CoreCommandBuffer")
351            .field(
352                "wgpu_command_buffer",
353                &Arc::as_ptr(&self.wgpu_command_buffer),
354            )
355            .finish()
356    }
357}
358
359#[derive(Debug)]
360pub struct CoreRenderBundleEncoder {
361    encoder: Box<wgc::command::RenderBundleEncoder>,
362}
363
364#[derive(Debug, Clone)]
365pub struct CoreRenderBundle {
366    pub(crate) wgpu_render_bundle: Arc<wgc::command::RenderBundle>,
367}
368
369#[derive(Clone)]
370pub struct CoreQueue {
371    pub(crate) wgpu_queue: Arc<wgc::device::queue::Queue>,
372}
373
374impl fmt::Debug for CoreQueue {
375    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
376        f.debug_struct("CoreQueue")
377            .field("wgpu_queue", &Arc::as_ptr(&self.wgpu_queue))
378            .finish()
379    }
380}
381
382impl CoreQueue {
383    pub unsafe fn as_hal<A: hal::Api>(
384        &self,
385    ) -> Option<impl Deref<Target = A::Queue> + WasmNotSendSync> {
386        unsafe { self.wgpu_queue.clone().as_hal::<A>() }
387    }
388}
389
390#[derive(Debug, Clone)]
391pub struct CoreComputePipeline {
392    pub(crate) wgpu_compute_pipeline: Arc<wgc::pipeline::ComputePipeline>,
393}
394
395#[derive(Debug, Clone)]
396pub struct CoreRenderPipeline {
397    pub(crate) wgpu_render_pipeline: Arc<wgc::pipeline::RenderPipeline>,
398}
399
400#[derive(Debug)]
401pub struct CoreComputePass {
402    pass: wgc::command::ComputePass,
403
404    id: crate::cmp::Identifier,
405}
406
407#[derive(Debug)]
408pub struct CoreRenderPass {
409    pass: wgc::command::RenderPass,
410
411    id: crate::cmp::Identifier,
412}
413
414pub struct CoreCommandEncoder {
415    pub(crate) wgpu_command_encoder: Arc<wgc::command::CommandEncoder>,
416}
417
418impl fmt::Debug for CoreCommandEncoder {
419    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
420        f.debug_struct("CoreCommandEncoder")
421            .field(
422                "wgpu_command_encoder",
423                &Arc::as_ptr(&self.wgpu_command_encoder),
424            )
425            .finish()
426    }
427}
428
429impl CoreCommandEncoder {
430    /// This method will start the wgpu_core level command recording.
431    pub unsafe fn as_hal_mut<A: hal::Api, F: FnOnce(Option<&mut A::CommandEncoder>) -> R, R>(
432        &self,
433        hal_command_encoder_callback: F,
434    ) -> R {
435        unsafe {
436            self.wgpu_command_encoder
437                .as_hal_mut::<A, F, R>(hal_command_encoder_callback)
438        }
439    }
440}
441
442#[derive(Debug, Clone)]
443pub struct CoreBlas {
444    pub(crate) wgpu_blas: Arc<wgc::resource::Blas>,
445}
446
447impl CoreBlas {
448    pub unsafe fn as_hal<A: hal::Api>(
449        &self,
450    ) -> Option<impl Deref<Target = A::AccelerationStructure>> {
451        unsafe { self.wgpu_blas.clone().as_hal::<A>() }
452    }
453}
454
455#[derive(Debug, Clone)]
456pub struct CoreTlas {
457    pub(crate) wgpu_tlas: Arc<wgc::resource::Tlas>,
458}
459
460impl CoreTlas {
461    pub unsafe fn as_hal<A: hal::Api>(
462        &self,
463    ) -> Option<impl Deref<Target = A::AccelerationStructure>> {
464        unsafe { self.wgpu_tlas.clone().as_hal::<A>() }
465    }
466}
467
468#[derive(Clone)]
469pub struct CoreSurfaceOutputDetail {
470    wgpu_surface: Arc<wgc::instance::Surface>,
471    error_sink: ErrorSink,
472}
473
474impl fmt::Debug for CoreSurfaceOutputDetail {
475    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
476        f.debug_struct("CoreSurfaceOutputDetail")
477            .field("wgpu_surface", &Arc::as_ptr(&self.wgpu_surface))
478            .finish()
479    }
480}
481
482impl From<CreateShaderModuleError> for CompilationInfo {
483    fn from(value: CreateShaderModuleError) -> Self {
484        match value {
485            #[cfg(feature = "wgsl")]
486            CreateShaderModuleError::Parsing(v) => v.into(),
487            #[cfg(feature = "glsl")]
488            CreateShaderModuleError::ParsingGlsl(v) => v.into(),
489            #[cfg(feature = "spirv")]
490            CreateShaderModuleError::ParsingSpirV(v) => v.into(),
491            CreateShaderModuleError::Validation(v) => v.into(),
492            // Device errors are reported through the error sink, and are not compilation errors.
493            // Same goes for native shader module generation errors.
494            CreateShaderModuleError::Device(_) | CreateShaderModuleError::Generation => {
495                CompilationInfo {
496                    messages: Vec::new(),
497                }
498            }
499            // Everything else is an error message without location information.
500            _ => CompilationInfo {
501                messages: vec![CompilationMessage {
502                    message: value.to_string(),
503                    message_type: CompilationMessageType::Error,
504                    location: None,
505                }],
506            },
507        }
508    }
509}
510
511#[derive(Debug)]
512pub struct CoreQueueWriteBuffer {
513    wgpu_staging_buffer: wgc::resource::StagingBuffer,
514    mapping: CoreBufferMappedRange,
515}
516
517#[derive(Debug)]
518pub struct CoreBufferMappedRange {
519    ptr: NonNull<u8>,
520    size: usize,
521}
522
523#[cfg(send_sync)]
524unsafe impl Send for CoreBufferMappedRange {}
525#[cfg(send_sync)]
526unsafe impl Sync for CoreBufferMappedRange {}
527
528impl Drop for CoreBufferMappedRange {
529    fn drop(&mut self) {
530        // Intentionally left blank so that `BufferMappedRange` still
531        // implements `Drop`, to match the web backend
532    }
533}
534
535crate::cmp::impl_eq_ord_hash_arc_address!(ContextWgpuCore => .0);
536crate::cmp::impl_eq_ord_hash_arc_address!(CoreAdapter => .wgpu_adapter);
537crate::cmp::impl_eq_ord_hash_arc_address!(CoreDevice => .wgpu_device);
538crate::cmp::impl_eq_ord_hash_arc_address!(CoreQueue => .wgpu_queue);
539crate::cmp::impl_eq_ord_hash_arc_address!(CoreShaderModule => .wgpu_shader_module);
540crate::cmp::impl_eq_ord_hash_arc_address!(CoreBindGroupLayout => .wgpu_bind_group_layout);
541crate::cmp::impl_eq_ord_hash_arc_address!(CoreBindGroup => .wgpu_bind_group);
542crate::cmp::impl_eq_ord_hash_arc_address!(CoreTextureView => .wgpu_texture_view);
543crate::cmp::impl_eq_ord_hash_arc_address!(CoreSampler => .wgpu_sampler);
544crate::cmp::impl_eq_ord_hash_arc_address!(CoreBuffer => .wgpu_buffer);
545crate::cmp::impl_eq_ord_hash_arc_address!(CoreTexture => .wgpu_texture);
546crate::cmp::impl_eq_ord_hash_arc_address!(CoreExternalTexture => .wgpu_external_texture);
547crate::cmp::impl_eq_ord_hash_arc_address!(CoreBlas => .wgpu_blas);
548crate::cmp::impl_eq_ord_hash_arc_address!(CoreTlas => .wgpu_tlas);
549crate::cmp::impl_eq_ord_hash_arc_address!(CoreQuerySet => .wgpu_query_set);
550crate::cmp::impl_eq_ord_hash_arc_address!(CorePipelineLayout => .wgpu_pipeline_layout);
551crate::cmp::impl_eq_ord_hash_arc_address!(CoreRenderPipeline => .wgpu_render_pipeline);
552crate::cmp::impl_eq_ord_hash_arc_address!(CoreComputePipeline => .wgpu_compute_pipeline);
553crate::cmp::impl_eq_ord_hash_arc_address!(CorePipelineCache => .wgpu_pipeline_cache);
554crate::cmp::impl_eq_ord_hash_arc_address!(CoreCommandEncoder => .wgpu_command_encoder);
555crate::cmp::impl_eq_ord_hash_proxy!(CoreComputePass => .id);
556crate::cmp::impl_eq_ord_hash_proxy!(CoreRenderPass => .id);
557crate::cmp::impl_eq_ord_hash_arc_address!(CoreCommandBuffer => .wgpu_command_buffer);
558crate::cmp::impl_eq_ord_hash_box_address!(CoreRenderBundleEncoder => .encoder);
559crate::cmp::impl_eq_ord_hash_arc_address!(CoreRenderBundle => .wgpu_render_bundle);
560crate::cmp::impl_eq_ord_hash_arc_address!(CoreSurface => .wgpu_surface);
561crate::cmp::impl_eq_ord_hash_arc_address!(CoreSurfaceOutputDetail => .wgpu_surface);
562crate::cmp::impl_eq_ord_hash_proxy!(CoreQueueWriteBuffer => .mapping.ptr);
563crate::cmp::impl_eq_ord_hash_proxy!(CoreBufferMappedRange => .ptr);
564
565impl dispatch::InstanceInterface for ContextWgpuCore {
566    fn new(desc: wgt::InstanceDescriptor) -> Self
567    where
568        Self: Sized,
569    {
570        Self(wgc::instance::Instance::new("wgpu", desc, None))
571    }
572
573    unsafe fn create_surface(
574        &self,
575        target: crate::api::SurfaceTargetUnsafe,
576    ) -> Result<dispatch::DispatchSurface, crate::CreateSurfaceError> {
577        let wgpu_surface = match target {
578            SurfaceTargetUnsafe::RawHandle {
579                raw_display_handle,
580                raw_window_handle,
581            } => unsafe { self.0.create_surface(raw_display_handle, raw_window_handle) },
582
583            #[cfg(all(drm, not(target_os = "netbsd")))]
584            SurfaceTargetUnsafe::Drm {
585                fd,
586                plane,
587                connector_id,
588                width,
589                height,
590                refresh_rate,
591            } => unsafe {
592                self.0
593                    .create_surface_from_drm(fd, plane, connector_id, width, height, refresh_rate)
594            },
595
596            #[cfg(metal)]
597            SurfaceTargetUnsafe::CoreAnimationLayer(layer) => unsafe {
598                self.0.create_surface_metal(layer)
599            },
600
601            #[cfg(all(drm, target_os = "netbsd"))]
602            SurfaceTargetUnsafe::Drm { .. } => Err(
603                wgc::instance::CreateSurfaceError::BackendNotEnabled(wgt::Backend::Vulkan),
604            ),
605
606            #[cfg(dx12)]
607            SurfaceTargetUnsafe::CompositionVisual(visual) => unsafe {
608                self.0.create_surface_from_visual(visual)
609            },
610
611            #[cfg(dx12)]
612            SurfaceTargetUnsafe::SurfaceHandle(surface_handle) => unsafe {
613                self.0.create_surface_from_surface_handle(surface_handle)
614            },
615
616            #[cfg(dx12)]
617            SurfaceTargetUnsafe::SwapChainPanel(swap_chain_panel) => unsafe {
618                self.0
619                    .create_surface_from_swap_chain_panel(swap_chain_panel)
620            },
621        }?;
622
623        Ok(CoreSurface {
624            wgpu_surface,
625            configured_device: Arc::new(Mutex::default()),
626        }
627        .into())
628    }
629
630    fn request_adapter(
631        &self,
632        options: &crate::api::RequestAdapterOptions<'_, '_>,
633    ) -> Pin<Box<dyn dispatch::RequestAdapterFuture>> {
634        let adapter = self.0.request_adapter(
635            &wgt::RequestAdapterOptions {
636                power_preference: options.power_preference,
637                force_fallback_adapter: options.force_fallback_adapter,
638                compatible_surface: options
639                    .compatible_surface
640                    .map(|surface| &*surface.inner.as_core().wgpu_surface),
641                apply_limit_buckets: false,
642            },
643            wgt::Backends::all(),
644        );
645        let adapter = adapter.map(|wgpu_adapter| {
646            let core = CoreAdapter { wgpu_adapter };
647            let generic: dispatch::DispatchAdapter = core.into();
648            generic
649        });
650        Box::pin(ready(adapter))
651    }
652
653    fn poll_all_devices(&self, force_wait: bool) -> bool {
654        match self.0.poll_all_devices(force_wait) {
655            Ok(all_queue_empty) => all_queue_empty,
656            Err(err) => handle_error_fatal(err, "Instance::poll_all_devices"),
657        }
658    }
659
660    #[cfg(feature = "wgsl")]
661    fn wgsl_language_features(&self) -> crate::WgslLanguageFeatures {
662        use wgc::naga::front::wgsl::ImplementedLanguageExtension;
663        ImplementedLanguageExtension::all().iter().copied().fold(
664            crate::WgslLanguageFeatures::empty(),
665            |acc, wle| {
666                acc | match wle {
667                    ImplementedLanguageExtension::ReadOnlyAndReadWriteStorageTextures => {
668                        crate::WgslLanguageFeatures::ReadOnlyAndReadWriteStorageTextures
669                    }
670                    ImplementedLanguageExtension::Packed4x8IntegerDotProduct => {
671                        crate::WgslLanguageFeatures::Packed4x8IntegerDotProduct
672                    }
673                    ImplementedLanguageExtension::PointerCompositeAccess => {
674                        crate::WgslLanguageFeatures::PointerCompositeAccess
675                    }
676                    ImplementedLanguageExtension::ImmediateAddressSpace => {
677                        crate::WgslLanguageFeatures::ImmediateAddressSpace
678                    }
679                }
680            },
681        )
682    }
683
684    fn enumerate_adapters(
685        &self,
686        backends: crate::Backends,
687    ) -> Pin<Box<dyn dispatch::EnumerateAdapterFuture>> {
688        let adapters: Vec<DispatchAdapter> = self
689            .enumerate_adapters(backends)
690            .into_iter()
691            .map(|adapter| {
692                let core = crate::backend::wgpu_core::CoreAdapter {
693                    wgpu_adapter: adapter,
694                };
695                core.into()
696            })
697            .collect();
698        Box::pin(ready(adapters))
699    }
700}
701
702impl dispatch::AdapterInterface for CoreAdapter {
703    fn request_device(
704        &self,
705        desc: &crate::DeviceDescriptor<'_>,
706    ) -> Pin<Box<dyn dispatch::RequestDeviceFuture>> {
707        let res = self
708            .wgpu_adapter
709            .request_device(&desc.map_label(|l| l.map(Borrowed)));
710        let (device, queue) = match res {
711            Ok(ids) => ids,
712            Err(err) => {
713                return Box::pin(ready(Err(err.into())));
714            }
715        };
716        let device = CoreDevice {
717            wgpu_device: device,
718        };
719        let queue = CoreQueue { wgpu_queue: queue };
720        Box::pin(ready(Ok((device.into(), queue.into()))))
721    }
722
723    fn is_surface_supported(&self, surface: &dispatch::DispatchSurface) -> bool {
724        let surface = surface.as_core();
725
726        self.wgpu_adapter
727            .is_surface_supported(&surface.wgpu_surface)
728    }
729
730    fn features(&self) -> crate::Features {
731        self.wgpu_adapter.features()
732    }
733
734    fn limits(&self) -> crate::Limits {
735        self.wgpu_adapter.limits()
736    }
737
738    fn downlevel_capabilities(&self) -> crate::DownlevelCapabilities {
739        self.wgpu_adapter.downlevel_capabilities()
740    }
741
742    fn get_info(&self) -> crate::AdapterInfo {
743        self.wgpu_adapter.get_info()
744    }
745
746    fn get_texture_format_features(
747        &self,
748        format: crate::TextureFormat,
749    ) -> crate::TextureFormatFeatures {
750        self.wgpu_adapter.get_texture_format_features(format)
751    }
752
753    fn get_presentation_timestamp(&self) -> crate::PresentationTimestamp {
754        self.wgpu_adapter.get_presentation_timestamp()
755    }
756
757    fn cooperative_matrix_properties(&self) -> Vec<crate::wgt::CooperativeMatrixProperties> {
758        self.wgpu_adapter.cooperative_matrix_properties()
759    }
760}
761
762impl Drop for CoreAdapter {
763    fn drop(&mut self) {}
764}
765
766impl dispatch::DeviceInterface for CoreDevice {
767    fn features(&self) -> crate::Features {
768        *self.wgpu_device.features()
769    }
770
771    fn limits(&self) -> crate::Limits {
772        self.wgpu_device.limits().clone()
773    }
774
775    fn adapter_info(&self) -> crate::AdapterInfo {
776        self.wgpu_device.adapter_info()
777    }
778
779    // If we have no way to create a shader module, we can't return one, and so most of the function is unreachable.
780    #[cfg_attr(
781        not(any(
782            feature = "spirv",
783            feature = "glsl",
784            feature = "wgsl",
785            feature = "naga-ir"
786        )),
787        expect(unused)
788    )]
789    fn create_shader_module(
790        &self,
791        desc: crate::ShaderModuleDescriptor<'_>,
792        shader_bound_checks: wgt::ShaderRuntimeChecks,
793    ) -> dispatch::DispatchShaderModule {
794        let descriptor = wgc::pipeline::ShaderModuleDescriptor {
795            label: desc.label.map(Borrowed),
796            runtime_checks: shader_bound_checks,
797        };
798        let source = match desc.source {
799            #[cfg(feature = "spirv")]
800            ShaderSource::SpirV(ref spv) => {
801                // Parse the given shader code and store its representation.
802                let options = naga::front::spv::Options {
803                    adjust_coordinate_space: false, // we require NDC_Y_UP feature
804                    strict_capabilities: true,
805                    block_ctx_dump_prefix: None,
806                };
807                wgc::pipeline::ShaderModuleSource::SpirV(Borrowed(spv), options)
808            }
809            #[cfg(feature = "glsl")]
810            ShaderSource::Glsl {
811                ref shader,
812                stage,
813                defines,
814            } => {
815                let options = naga::front::glsl::Options {
816                    stage,
817                    defines: defines
818                        .iter()
819                        .map(|&(key, value)| (String::from(key), String::from(value)))
820                        .collect(),
821                };
822                wgc::pipeline::ShaderModuleSource::Glsl(Borrowed(shader), options)
823            }
824            #[cfg(feature = "wgsl")]
825            ShaderSource::Wgsl(ref code) => wgc::pipeline::ShaderModuleSource::Wgsl(Borrowed(code)),
826            #[cfg(feature = "naga-ir")]
827            ShaderSource::Naga(module) => wgc::pipeline::ShaderModuleSource::Naga(module),
828            ShaderSource::Dummy(_) => panic!("found `ShaderSource::Dummy`"),
829        };
830        let (wgpu_shader_module, error) =
831            self.wgpu_device.create_shader_module(&descriptor, source);
832        let compilation_info = match error {
833            Some(cause) => {
834                self.wgpu_device.handle_error(
835                    cause.clone(),
836                    desc.label,
837                    "Device::create_shader_module",
838                );
839                CompilationInfo::from(cause)
840            }
841            None => CompilationInfo { messages: vec![] },
842        };
843
844        CoreShaderModule {
845            wgpu_shader_module,
846            compilation_info,
847        }
848        .into()
849    }
850
851    unsafe fn create_shader_module_passthrough(
852        &self,
853        desc: &crate::ShaderModuleDescriptorPassthrough<'_>,
854    ) -> dispatch::DispatchShaderModule {
855        let desc = desc.map_label(|l| l.map(Cow::from));
856        let (wgpu_shader_module, error) =
857            unsafe { self.wgpu_device.create_shader_module_passthrough(&desc) };
858
859        let compilation_info = match error {
860            Some(cause) => {
861                self.wgpu_device.handle_error(
862                    cause.clone(),
863                    desc.label.as_deref(),
864                    "Device::create_shader_module_passthrough",
865                );
866                CompilationInfo::from(cause)
867            }
868            None => CompilationInfo { messages: vec![] },
869        };
870
871        CoreShaderModule {
872            wgpu_shader_module,
873            compilation_info,
874        }
875        .into()
876    }
877
878    fn create_bind_group_layout(
879        &self,
880        desc: &crate::BindGroupLayoutDescriptor<'_>,
881    ) -> dispatch::DispatchBindGroupLayout {
882        let descriptor = wgc::binding_model::BindGroupLayoutDescriptor {
883            label: desc.label.map(Borrowed),
884            entries: Borrowed(desc.entries),
885        };
886        let wgpu_bind_group_layout = self.wgpu_device.create_bind_group_layout(&descriptor);
887        CoreBindGroupLayout {
888            wgpu_bind_group_layout,
889        }
890        .into()
891    }
892
893    fn create_bind_group(
894        &self,
895        desc: &crate::BindGroupDescriptor<'_>,
896    ) -> dispatch::DispatchBindGroup {
897        use wgc::binding_model as bm;
898
899        let mut arrayed_texture_views = Vec::new();
900        let mut arrayed_samplers = Vec::new();
901        if self
902            .wgpu_device
903            .features()
904            .contains(Features::TEXTURE_BINDING_ARRAY)
905        {
906            // gather all the array view first
907            for entry in desc.entries.iter() {
908                if let BindingResource::TextureViewArray(array) = entry.resource {
909                    arrayed_texture_views.extend(
910                        array
911                            .iter()
912                            .map(|view| view.inner.as_core().wgpu_texture_view.clone()),
913                    );
914                }
915                if let BindingResource::SamplerArray(array) = entry.resource {
916                    arrayed_samplers.extend(
917                        array
918                            .iter()
919                            .map(|sampler| sampler.inner.as_core().wgpu_sampler.clone()),
920                    );
921                }
922            }
923        }
924        let mut remaining_arrayed_texture_views = &arrayed_texture_views[..];
925        let mut remaining_arrayed_samplers = &arrayed_samplers[..];
926
927        let mut arrayed_buffer_bindings = Vec::new();
928        if self
929            .wgpu_device
930            .features()
931            .contains(Features::BUFFER_BINDING_ARRAY)
932        {
933            // gather all the buffers first
934            for entry in desc.entries.iter() {
935                if let BindingResource::BufferArray(array) = entry.resource {
936                    arrayed_buffer_bindings.extend(array.iter().map(|binding| bm::BufferBinding {
937                        buffer: binding.buffer.inner.as_core().wgpu_buffer.clone(),
938                        offset: binding.offset,
939                        size: binding.size.map(wgt::BufferSize::get),
940                    }));
941                }
942            }
943        }
944        let mut remaining_arrayed_buffer_bindings = &arrayed_buffer_bindings[..];
945
946        let mut arrayed_acceleration_structures = Vec::new();
947        if self
948            .wgpu_device
949            .features()
950            .contains(Features::ACCELERATION_STRUCTURE_BINDING_ARRAY)
951        {
952            // Gather all the TLAS IDs used by TLAS arrays first (same pattern as other arrayed resources).
953            for entry in desc.entries.iter() {
954                if let BindingResource::AccelerationStructureArray(array) = entry.resource {
955                    arrayed_acceleration_structures.extend(
956                        array
957                            .iter()
958                            .map(|tlas| tlas.inner.as_core().wgpu_tlas.clone()),
959                    );
960                }
961            }
962        }
963        let mut remaining_arrayed_acceleration_structures = &arrayed_acceleration_structures[..];
964
965        let entries = desc
966            .entries
967            .iter()
968            .map(|entry| bm::BindGroupEntry {
969                binding: entry.binding,
970                resource: match entry.resource {
971                    BindingResource::Buffer(BufferBinding {
972                        buffer,
973                        offset,
974                        size,
975                    }) => bm::BindingResource::Buffer(bm::BufferBinding {
976                        buffer: buffer.inner.as_core().wgpu_buffer.clone(),
977                        offset,
978                        size: size.map(wgt::BufferSize::get),
979                    }),
980                    BindingResource::BufferArray(array) => {
981                        let slice = &remaining_arrayed_buffer_bindings[..array.len()];
982                        remaining_arrayed_buffer_bindings =
983                            &remaining_arrayed_buffer_bindings[array.len()..];
984                        bm::BindingResource::BufferArray(Borrowed(slice))
985                    }
986                    BindingResource::Sampler(sampler) => {
987                        bm::BindingResource::Sampler(sampler.inner.as_core().wgpu_sampler.clone())
988                    }
989                    BindingResource::SamplerArray(array) => {
990                        let slice = &remaining_arrayed_samplers[..array.len()];
991                        remaining_arrayed_samplers = &remaining_arrayed_samplers[array.len()..];
992                        bm::BindingResource::SamplerArray(Borrowed(slice))
993                    }
994                    BindingResource::TextureView(texture_view) => bm::BindingResource::TextureView(
995                        texture_view.inner.as_core().wgpu_texture_view.clone(),
996                    ),
997                    BindingResource::TextureViewArray(array) => {
998                        let slice = &remaining_arrayed_texture_views[..array.len()];
999                        remaining_arrayed_texture_views =
1000                            &remaining_arrayed_texture_views[array.len()..];
1001                        bm::BindingResource::TextureViewArray(Borrowed(slice))
1002                    }
1003                    BindingResource::AccelerationStructure(acceleration_structure) => {
1004                        bm::BindingResource::AccelerationStructure(
1005                            acceleration_structure.inner.as_core().wgpu_tlas.clone(),
1006                        )
1007                    }
1008                    BindingResource::AccelerationStructureArray(array) => {
1009                        let slice = &remaining_arrayed_acceleration_structures[..array.len()];
1010                        remaining_arrayed_acceleration_structures =
1011                            &remaining_arrayed_acceleration_structures[array.len()..];
1012                        bm::BindingResource::AccelerationStructureArray(Borrowed(slice))
1013                    }
1014                    BindingResource::ExternalTexture(external_texture) => {
1015                        bm::BindingResource::ExternalTexture(
1016                            external_texture
1017                                .inner
1018                                .as_core()
1019                                .wgpu_external_texture
1020                                .clone(),
1021                        )
1022                    }
1023                },
1024            })
1025            .collect::<Vec<_>>();
1026        let descriptor = bm::BindGroupDescriptor {
1027            label: desc.label.as_ref().map(|label| Borrowed(&label[..])),
1028            layout: desc.layout.inner.as_core().wgpu_bind_group_layout.clone(),
1029            entries: Borrowed(&entries),
1030        };
1031
1032        let wgpu_bind_group = self.wgpu_device.create_bind_group(&descriptor);
1033        CoreBindGroup { wgpu_bind_group }.into()
1034    }
1035
1036    fn create_pipeline_layout(
1037        &self,
1038        desc: &crate::PipelineLayoutDescriptor<'_>,
1039    ) -> dispatch::DispatchPipelineLayout {
1040        // Limit is always less or equal to hal::MAX_BIND_GROUPS, so this is always right
1041        // Guards following ArrayVec
1042        assert!(
1043            desc.bind_group_layouts.len() <= wgc::MAX_BIND_GROUPS,
1044            "Bind group layout count {} exceeds device bind group limit {}",
1045            desc.bind_group_layouts.len(),
1046            wgc::MAX_BIND_GROUPS
1047        );
1048
1049        let temp_layouts = desc
1050            .bind_group_layouts
1051            .iter()
1052            .map(|bgl| bgl.map(|bgl| bgl.inner.as_core().wgpu_bind_group_layout.clone()))
1053            .collect::<ArrayVec<_, { wgc::MAX_BIND_GROUPS }>>();
1054        let descriptor = wgc::binding_model::PipelineLayoutDescriptor {
1055            label: desc.label.map(Borrowed),
1056            bind_group_layouts: Borrowed(&temp_layouts),
1057            immediate_size: desc.immediate_size,
1058        };
1059
1060        let wgpu_pipeline_layout = self.wgpu_device.create_pipeline_layout(&descriptor);
1061
1062        CorePipelineLayout {
1063            wgpu_pipeline_layout,
1064        }
1065        .into()
1066    }
1067
1068    fn create_render_pipeline(
1069        &self,
1070        desc: &crate::RenderPipelineDescriptor<'_>,
1071    ) -> dispatch::DispatchRenderPipeline {
1072        use wgc::pipeline as pipe;
1073
1074        let vertex_buffers: ArrayVec<_, { wgc::MAX_VERTEX_BUFFERS }> = desc
1075            .vertex
1076            .buffers
1077            .iter()
1078            .map(|vbuf| {
1079                vbuf.as_ref().map(|vbuf| pipe::VertexBufferLayout {
1080                    array_stride: vbuf.array_stride,
1081                    step_mode: vbuf.step_mode,
1082                    attributes: Borrowed(vbuf.attributes),
1083                })
1084            })
1085            .collect();
1086
1087        let vert_constants = desc
1088            .vertex
1089            .compilation_options
1090            .constants
1091            .iter()
1092            .map(|&(key, value)| (String::from(key), value))
1093            .collect();
1094
1095        let descriptor = pipe::ResolvedGeneralRenderPipelineDescriptor {
1096            label: desc.label.map(Borrowed),
1097            layout: desc
1098                .layout
1099                .map(|layout| layout.inner.as_core().wgpu_pipeline_layout.clone()),
1100            vertex: wgc::pipeline::RenderPipelineVertexProcessor::Vertex(pipe::VertexState {
1101                stage: pipe::ProgrammableStageDescriptor {
1102                    module: desc
1103                        .vertex
1104                        .module
1105                        .inner
1106                        .as_core()
1107                        .wgpu_shader_module
1108                        .clone(),
1109                    entry_point: desc.vertex.entry_point.map(Borrowed),
1110                    constants: vert_constants,
1111                    zero_initialize_workgroup_memory: desc
1112                        .vertex
1113                        .compilation_options
1114                        .zero_initialize_workgroup_memory,
1115                },
1116                buffers: Borrowed(&vertex_buffers),
1117            }),
1118            primitive: desc.primitive,
1119            depth_stencil: desc.depth_stencil.clone(),
1120            multisample: desc.multisample,
1121            fragment: desc.fragment.as_ref().map(|frag| {
1122                let frag_constants = frag
1123                    .compilation_options
1124                    .constants
1125                    .iter()
1126                    .map(|&(key, value)| (String::from(key), value))
1127                    .collect();
1128                pipe::FragmentState {
1129                    stage: pipe::ProgrammableStageDescriptor {
1130                        module: frag.module.inner.as_core().wgpu_shader_module.clone(),
1131                        entry_point: frag.entry_point.map(Borrowed),
1132                        constants: frag_constants,
1133                        zero_initialize_workgroup_memory: frag
1134                            .compilation_options
1135                            .zero_initialize_workgroup_memory,
1136                    },
1137                    targets: Borrowed(frag.targets),
1138                }
1139            }),
1140            multiview_mask: desc.multiview_mask,
1141            cache: desc
1142                .cache
1143                .map(|cache| cache.inner.as_core().wgpu_pipeline_cache.clone()),
1144        };
1145
1146        let wgpu_render_pipeline = self.wgpu_device.create_render_pipeline(descriptor);
1147        CoreRenderPipeline {
1148            wgpu_render_pipeline,
1149        }
1150        .into()
1151    }
1152
1153    fn create_mesh_pipeline(
1154        &self,
1155        desc: &crate::MeshPipelineDescriptor<'_>,
1156    ) -> dispatch::DispatchRenderPipeline {
1157        use wgc::pipeline as pipe;
1158
1159        let mesh_constants = desc
1160            .mesh
1161            .compilation_options
1162            .constants
1163            .iter()
1164            .map(|&(key, value)| (String::from(key), value))
1165            .collect();
1166        let descriptor = pipe::MeshPipelineDescriptor {
1167            label: desc.label.map(Borrowed),
1168            task: desc.task.as_ref().map(|task| {
1169                let task_constants = task
1170                    .compilation_options
1171                    .constants
1172                    .iter()
1173                    .map(|&(key, value)| (String::from(key), value))
1174                    .collect();
1175                pipe::TaskState {
1176                    stage: pipe::ProgrammableStageDescriptor {
1177                        module: task.module.inner.as_core().wgpu_shader_module.clone(),
1178                        entry_point: task.entry_point.map(Borrowed),
1179                        constants: task_constants,
1180                        zero_initialize_workgroup_memory: desc
1181                            .mesh
1182                            .compilation_options
1183                            .zero_initialize_workgroup_memory,
1184                    },
1185                }
1186            }),
1187            mesh: pipe::MeshState {
1188                stage: pipe::ProgrammableStageDescriptor {
1189                    module: desc.mesh.module.inner.as_core().wgpu_shader_module.clone(),
1190                    entry_point: desc.mesh.entry_point.map(Borrowed),
1191                    constants: mesh_constants,
1192                    zero_initialize_workgroup_memory: desc
1193                        .mesh
1194                        .compilation_options
1195                        .zero_initialize_workgroup_memory,
1196                },
1197            },
1198            layout: desc
1199                .layout
1200                .map(|layout| layout.inner.as_core().wgpu_pipeline_layout.clone()),
1201            primitive: desc.primitive,
1202            depth_stencil: desc.depth_stencil.clone(),
1203            multisample: desc.multisample,
1204            fragment: desc.fragment.as_ref().map(|frag| {
1205                let frag_constants = frag
1206                    .compilation_options
1207                    .constants
1208                    .iter()
1209                    .map(|&(key, value)| (String::from(key), value))
1210                    .collect();
1211                pipe::FragmentState {
1212                    stage: pipe::ProgrammableStageDescriptor {
1213                        module: frag.module.inner.as_core().wgpu_shader_module.clone(),
1214                        entry_point: frag.entry_point.map(Borrowed),
1215                        constants: frag_constants,
1216                        zero_initialize_workgroup_memory: frag
1217                            .compilation_options
1218                            .zero_initialize_workgroup_memory,
1219                    },
1220                    targets: Borrowed(frag.targets),
1221                }
1222            }),
1223            multiview: desc.multiview,
1224            cache: desc
1225                .cache
1226                .map(|cache| cache.inner.as_core().wgpu_pipeline_cache.clone()),
1227        };
1228
1229        let wgpu_render_pipeline = self.wgpu_device.create_render_pipeline(descriptor.into());
1230        CoreRenderPipeline {
1231            wgpu_render_pipeline,
1232        }
1233        .into()
1234    }
1235
1236    fn create_compute_pipeline(
1237        &self,
1238        desc: &crate::ComputePipelineDescriptor<'_>,
1239    ) -> dispatch::DispatchComputePipeline {
1240        use wgc::pipeline as pipe;
1241
1242        let constants = desc
1243            .compilation_options
1244            .constants
1245            .iter()
1246            .map(|&(key, value)| (String::from(key), value))
1247            .collect();
1248
1249        let descriptor = pipe::ComputePipelineDescriptor {
1250            label: desc.label.map(Borrowed),
1251            layout: desc
1252                .layout
1253                .map(|pll| pll.inner.as_core().wgpu_pipeline_layout.clone()),
1254            stage: pipe::ProgrammableStageDescriptor {
1255                module: desc.module.inner.as_core().wgpu_shader_module.clone(),
1256                entry_point: desc.entry_point.map(Borrowed),
1257                constants,
1258                zero_initialize_workgroup_memory: desc
1259                    .compilation_options
1260                    .zero_initialize_workgroup_memory,
1261            },
1262            cache: desc
1263                .cache
1264                .map(|cache| cache.inner.as_core().wgpu_pipeline_cache.clone()),
1265        };
1266
1267        let wgpu_compute_pipeline = self.wgpu_device.create_compute_pipeline(descriptor);
1268        CoreComputePipeline {
1269            wgpu_compute_pipeline,
1270        }
1271        .into()
1272    }
1273
1274    unsafe fn create_pipeline_cache(
1275        &self,
1276        desc: &crate::PipelineCacheDescriptor<'_>,
1277    ) -> dispatch::DispatchPipelineCache {
1278        use wgc::pipeline as pipe;
1279
1280        let descriptor = pipe::PipelineCacheDescriptor {
1281            label: desc.label.map(Borrowed),
1282            data: desc.data.map(Borrowed),
1283            fallback: desc.fallback,
1284        };
1285        let (wgpu_pipeline_cache, error) =
1286            unsafe { self.wgpu_device.create_pipeline_cache(&descriptor) };
1287        if let Some(cause) = error {
1288            self.wgpu_device.handle_error(
1289                cause,
1290                desc.label,
1291                "Device::device_create_pipeline_cache_init",
1292            );
1293        }
1294        CorePipelineCache {
1295            wgpu_pipeline_cache,
1296        }
1297        .into()
1298    }
1299
1300    fn create_buffer(&self, desc: &crate::BufferDescriptor<'_>) -> dispatch::DispatchBuffer {
1301        let wgpu_buffer = self
1302            .wgpu_device
1303            .create_buffer(&desc.map_label(|l| l.map(Borrowed)));
1304
1305        CoreBuffer { wgpu_buffer }.into()
1306    }
1307
1308    fn create_texture(&self, desc: &crate::TextureDescriptor<'_>) -> dispatch::DispatchTexture {
1309        let wgt_desc = desc.map_label_and_view_formats(|l| l.map(Borrowed), |v| v.to_vec());
1310        let wgpu_texture = self.wgpu_device.create_texture(&wgt_desc);
1311
1312        CoreTexture { wgpu_texture }.into()
1313    }
1314
1315    fn create_external_texture(
1316        &self,
1317        desc: &crate::ExternalTextureDescriptor<'_>,
1318        planes: &[&crate::TextureView],
1319    ) -> dispatch::DispatchExternalTexture {
1320        let wgt_desc = desc.map_label(|l| l.map(Borrowed));
1321        let planes = planes
1322            .iter()
1323            .map(|plane| plane.inner.as_core().wgpu_texture_view.clone())
1324            .collect::<Vec<_>>();
1325        let wgpu_external_texture = self.wgpu_device.create_external_texture(&wgt_desc, &planes);
1326
1327        CoreExternalTexture {
1328            wgpu_external_texture,
1329        }
1330        .into()
1331    }
1332
1333    fn create_blas(
1334        &self,
1335        desc: &crate::CreateBlasDescriptor<'_>,
1336        sizes: crate::BlasGeometrySizeDescriptors,
1337    ) -> (Option<u64>, dispatch::DispatchBlas) {
1338        let (wgpu_blas, error) = self
1339            .wgpu_device
1340            .create_blas(&desc.map_label(|l| l.map(Borrowed)), sizes);
1341        if let Some(cause) = error {
1342            self.wgpu_device
1343                .handle_error(cause, desc.label, "Device::create_blas");
1344        }
1345        (wgpu_blas.handle(), CoreBlas { wgpu_blas }.into())
1346    }
1347
1348    fn create_tlas(&self, desc: &crate::CreateTlasDescriptor<'_>) -> dispatch::DispatchTlas {
1349        let (wgpu_tlas, error) = self
1350            .wgpu_device
1351            .create_tlas(&desc.map_label(|l| l.map(Borrowed)));
1352        if let Some(cause) = error {
1353            self.wgpu_device
1354                .handle_error(cause, desc.label, "Device::create_tlas");
1355        }
1356        CoreTlas { wgpu_tlas }.into()
1357    }
1358
1359    fn create_sampler(&self, desc: &crate::SamplerDescriptor<'_>) -> dispatch::DispatchSampler {
1360        let descriptor = wgc::resource::SamplerDescriptor {
1361            label: desc.label.map(Borrowed),
1362            address_modes: [
1363                desc.address_mode_u,
1364                desc.address_mode_v,
1365                desc.address_mode_w,
1366            ],
1367            mag_filter: desc.mag_filter,
1368            min_filter: desc.min_filter,
1369            mipmap_filter: desc.mipmap_filter,
1370            lod_min_clamp: desc.lod_min_clamp,
1371            lod_max_clamp: desc.lod_max_clamp,
1372            compare: desc.compare,
1373            anisotropy_clamp: desc.anisotropy_clamp,
1374            border_color: desc.border_color,
1375        };
1376
1377        let wgpu_sampler = self.wgpu_device.create_sampler(&descriptor);
1378        CoreSampler { wgpu_sampler }.into()
1379    }
1380
1381    fn create_query_set(&self, desc: &crate::QuerySetDescriptor<'_>) -> dispatch::DispatchQuerySet {
1382        let wgpu_query_set = self
1383            .wgpu_device
1384            .create_query_set(&desc.map_label(|l| l.map(Borrowed)));
1385        CoreQuerySet { wgpu_query_set }.into()
1386    }
1387
1388    fn create_command_encoder(
1389        &self,
1390        desc: &crate::CommandEncoderDescriptor<'_>,
1391    ) -> dispatch::DispatchCommandEncoder {
1392        let wgpu_command_encoder = self
1393            .wgpu_device
1394            .create_command_encoder(&desc.map_label(|l| l.map(Borrowed)));
1395
1396        CoreCommandEncoder {
1397            wgpu_command_encoder,
1398        }
1399        .into()
1400    }
1401
1402    fn create_render_bundle_encoder(
1403        &self,
1404        desc: &crate::RenderBundleEncoderDescriptor<'_>,
1405    ) -> dispatch::DispatchRenderBundleEncoder {
1406        let descriptor = wgc::command::RenderBundleEncoderDescriptor {
1407            label: desc.label.map(Borrowed),
1408            color_formats: Borrowed(desc.color_formats),
1409            depth_stencil: desc.depth_stencil,
1410            sample_count: desc.sample_count,
1411            multiview: desc.multiview,
1412        };
1413        let encoder = self.wgpu_device.create_render_bundle_encoder(&descriptor);
1414
1415        CoreRenderBundleEncoder { encoder }.into()
1416    }
1417
1418    fn set_device_lost_callback(&self, device_lost_callback: dispatch::BoxDeviceLostCallback) {
1419        self.wgpu_device
1420            .set_device_lost_closure(device_lost_callback);
1421    }
1422
1423    fn on_uncaptured_error(&self, handler: Arc<dyn crate::UncapturedErrorHandler>) {
1424        self.wgpu_device.on_uncaptured_error(handler);
1425    }
1426
1427    fn push_error_scope(&self, filter: crate::ErrorFilter) -> u32 {
1428        self.wgpu_device.push_error_scope_with_index(filter)
1429    }
1430
1431    fn pop_error_scope(&self, index: u32) -> Pin<Box<dyn dispatch::PopErrorScopeFuture>> {
1432        Box::pin(ready(self.wgpu_device.pop_error_scope_checked(index)))
1433    }
1434
1435    unsafe fn start_graphics_debugger_capture(&self) {
1436        unsafe { self.wgpu_device.start_graphics_debugger_capture() };
1437    }
1438
1439    unsafe fn stop_graphics_debugger_capture(&self) {
1440        unsafe { self.wgpu_device.stop_graphics_debugger_capture() };
1441    }
1442
1443    fn poll(&self, poll_type: wgt::PollType<u64>) -> Result<crate::PollStatus, crate::PollError> {
1444        match self.wgpu_device.poll(poll_type) {
1445            Ok(status) => Ok(status),
1446            Err(err) => {
1447                if let Some(poll_error) = err.to_poll_error() {
1448                    return Err(poll_error);
1449                }
1450
1451                handle_error_fatal(err, "Device::poll")
1452            }
1453        }
1454    }
1455
1456    fn get_internal_counters(&self) -> crate::InternalCounters {
1457        self.wgpu_device.get_internal_counters()
1458    }
1459
1460    fn generate_allocator_report(&self) -> Option<wgt::AllocatorReport> {
1461        self.wgpu_device.generate_allocator_report()
1462    }
1463
1464    fn destroy(&self) {
1465        self.wgpu_device.destroy();
1466    }
1467}
1468
1469impl Drop for CoreDevice {
1470    fn drop(&mut self) {}
1471}
1472
1473impl dispatch::QueueInterface for CoreQueue {
1474    fn write_buffer(
1475        &self,
1476        buffer: &dispatch::DispatchBuffer,
1477        offset: crate::BufferAddress,
1478        data: &[u8],
1479    ) {
1480        let buffer = buffer.as_core();
1481
1482        self.wgpu_queue
1483            .write_buffer(buffer.wgpu_buffer.clone(), offset, data)
1484    }
1485
1486    fn create_staging_buffer(
1487        &self,
1488        size: crate::BufferSize,
1489    ) -> Option<dispatch::DispatchQueueWriteBuffer> {
1490        match self.wgpu_queue.create_staging_buffer(size) {
1491            Ok((wgpu_staging_buffer, ptr)) => Some(
1492                CoreQueueWriteBuffer {
1493                    wgpu_staging_buffer,
1494                    mapping: CoreBufferMappedRange {
1495                        ptr,
1496                        size: size.get() as usize,
1497                    },
1498                }
1499                .into(),
1500            ),
1501            Err(err) => {
1502                self.wgpu_queue
1503                    .device()
1504                    .handle_error_nolabel(err, "Queue::write_buffer_with");
1505                None
1506            }
1507        }
1508    }
1509
1510    fn validate_write_buffer(
1511        &self,
1512        buffer: &dispatch::DispatchBuffer,
1513        offset: wgt::BufferAddress,
1514        size: wgt::BufferSize,
1515    ) -> Option<()> {
1516        let buffer = buffer.as_core();
1517
1518        match self
1519            .wgpu_queue
1520            .validate_write_buffer(buffer.wgpu_buffer.clone(), offset, size)
1521        {
1522            Ok(()) => Some(()),
1523            Err(err) => {
1524                self.wgpu_queue
1525                    .device()
1526                    .handle_error_nolabel(err, "Queue::write_buffer_with");
1527                None
1528            }
1529        }
1530    }
1531
1532    fn write_staging_buffer(
1533        &self,
1534        buffer: &dispatch::DispatchBuffer,
1535        offset: crate::BufferAddress,
1536        staging_buffer: dispatch::DispatchQueueWriteBuffer,
1537    ) {
1538        let buffer = buffer.as_core();
1539        let staging_buffer = {
1540            #[allow(
1541                clippy::allow_attributes,
1542                unreachable_patterns,
1543                reason = "features may be disabled"
1544            )]
1545            match staging_buffer {
1546                dispatch::DispatchQueueWriteBuffer::Core(value) => value,
1547                _ => panic!(concat!(
1548                    stringify!(DispatchQueueWriteBuffer),
1549                    " is not core"
1550                )),
1551            }
1552        };
1553
1554        match self.wgpu_queue.write_staging_buffer(
1555            buffer.wgpu_buffer.clone(),
1556            offset,
1557            staging_buffer.wgpu_staging_buffer,
1558        ) {
1559            Ok(()) => (),
1560            Err(err) => {
1561                self.wgpu_queue
1562                    .device()
1563                    .handle_error_nolabel(err, "Queue::write_buffer_with");
1564            }
1565        }
1566    }
1567
1568    fn write_texture(
1569        &self,
1570        texture: crate::TexelCopyTextureInfo<'_>,
1571        data: &[u8],
1572        data_layout: crate::TexelCopyBufferLayout,
1573        size: crate::Extent3d,
1574    ) {
1575        self.wgpu_queue
1576            .write_texture(map_texture_copy_view(texture), data, &data_layout, &size);
1577    }
1578
1579    // This method needs to exist if either webgpu or webgl is enabled,
1580    // but we only actually have an implementation if webgl is enabled.
1581    #[cfg(web)]
1582    #[cfg_attr(not(webgl), expect(unused_variables))]
1583    fn copy_external_image_to_texture(
1584        &self,
1585        source: &crate::CopyExternalImageSourceInfo,
1586        dest: crate::CopyExternalImageDestInfo<&crate::api::Texture>,
1587        size: crate::Extent3d,
1588    ) {
1589        #[cfg(webgl)]
1590        match self.wgpu_queue.copy_external_image_to_texture(
1591            source,
1592            map_texture_tagged_copy_view(dest),
1593            size,
1594        ) {
1595            Ok(()) => (),
1596            Err(err) => self
1597                .wgpu_queue
1598                .device()
1599                .handle_error_nolabel(err, "Queue::copy_external_image_to_texture"),
1600        }
1601    }
1602
1603    fn submit(
1604        &self,
1605        command_buffers: &mut dyn Iterator<Item = dispatch::DispatchCommandBuffer>,
1606    ) -> u64 {
1607        let temp_command_buffers = command_buffers.collect::<SmallVec<[_; 4]>>();
1608        let command_buffers = temp_command_buffers
1609            .iter()
1610            .map(|cmdbuf| cmdbuf.as_core().wgpu_command_buffer.clone())
1611            .collect::<SmallVec<[_; 4]>>();
1612
1613        let index = self.wgpu_queue.submit(&command_buffers);
1614
1615        drop(temp_command_buffers);
1616
1617        index
1618    }
1619
1620    fn get_timestamp_period(&self) -> f32 {
1621        self.wgpu_queue.get_timestamp_period()
1622    }
1623
1624    fn on_submitted_work_done(&self, callback: dispatch::BoxSubmittedWorkDoneCallback) {
1625        self.wgpu_queue.on_submitted_work_done(callback);
1626    }
1627
1628    fn compact_blas(&self, blas: &dispatch::DispatchBlas) -> (Option<u64>, dispatch::DispatchBlas) {
1629        let (wgpu_blas, error) = self.wgpu_queue.compact_blas(&blas.as_core().wgpu_blas);
1630
1631        if let Some(cause) = error {
1632            self.wgpu_queue
1633                .device()
1634                .handle_error_nolabel(cause, "Queue::compact_blas");
1635        }
1636        (wgpu_blas.handle(), CoreBlas { wgpu_blas }.into())
1637    }
1638
1639    fn present(&self, detail: &dispatch::DispatchSurfaceOutputDetail) {
1640        let detail = detail.as_core();
1641        match detail.wgpu_surface.present() {
1642            Ok(_status) => (),
1643            Err(err) => {
1644                self.wgpu_queue
1645                    .device()
1646                    .handle_error_nolabel(err, "Queue::present");
1647            }
1648        }
1649    }
1650}
1651
1652impl dispatch::ShaderModuleInterface for CoreShaderModule {
1653    fn get_compilation_info(&self) -> Pin<Box<dyn dispatch::ShaderCompilationInfoFuture>> {
1654        Box::pin(ready(self.compilation_info.clone()))
1655    }
1656}
1657
1658impl dispatch::BindGroupLayoutInterface for CoreBindGroupLayout {}
1659
1660impl dispatch::BindGroupInterface for CoreBindGroup {}
1661
1662impl dispatch::TextureViewInterface for CoreTextureView {}
1663
1664impl dispatch::ExternalTextureInterface for CoreExternalTexture {
1665    fn destroy(&self) {
1666        self.wgpu_external_texture.destroy();
1667    }
1668}
1669
1670impl dispatch::SamplerInterface for CoreSampler {}
1671
1672impl dispatch::BufferInterface for CoreBuffer {
1673    fn map_async(
1674        &self,
1675        mode: crate::MapMode,
1676        range: Range<crate::BufferAddress>,
1677        callback: dispatch::BufferMapCallback,
1678    ) {
1679        let operation = wgc::resource::BufferMapOperation {
1680            host: match mode {
1681                MapMode::Read => wgc::device::HostMap::Read,
1682                MapMode::Write => wgc::device::HostMap::Write,
1683            },
1684            callback: Some(Box::new(|status| {
1685                let res = status.map_err(|_| crate::BufferAsyncError);
1686                callback(res);
1687            })),
1688        };
1689
1690        self.wgpu_buffer
1691            .map_async(range.start, Some(range.end - range.start), operation);
1692    }
1693
1694    fn get_mapped_range(
1695        &self,
1696        sub_range: Range<crate::BufferAddress>,
1697    ) -> Result<dispatch::DispatchBufferMappedRange, crate::MapRangeError> {
1698        let size = sub_range.end - sub_range.start;
1699        self.wgpu_buffer
1700            .get_mapped_range(sub_range.start, Some(size))
1701            .map(|(ptr, size)| {
1702                CoreBufferMappedRange {
1703                    ptr,
1704                    size: size as usize,
1705                }
1706                .into()
1707            })
1708            .map_err(|err| crate::MapRangeError(format_error(&err)))
1709    }
1710
1711    fn unmap(&self) {
1712        self.wgpu_buffer.unmap();
1713    }
1714
1715    fn destroy(&self) {
1716        self.wgpu_buffer.destroy();
1717    }
1718
1719    fn size(&self) -> crate::BufferAddress {
1720        self.wgpu_buffer.size()
1721    }
1722
1723    fn usage(&self) -> crate::BufferUsages {
1724        self.wgpu_buffer.usage()
1725    }
1726}
1727
1728impl dispatch::TextureInterface for CoreTexture {
1729    fn create_view(
1730        &self,
1731        desc: &crate::TextureViewDescriptor<'_>,
1732    ) -> dispatch::DispatchTextureView {
1733        let descriptor = wgc::resource::TextureViewDescriptor {
1734            label: desc.label.map(Borrowed),
1735            format: desc.format,
1736            dimension: desc.dimension,
1737            usage: desc.usage,
1738            range: wgt::ImageSubresourceRange {
1739                aspect: desc.aspect,
1740                base_mip_level: desc.base_mip_level,
1741                mip_level_count: desc.mip_level_count,
1742                base_array_layer: desc.base_array_layer,
1743                array_layer_count: desc.array_layer_count,
1744            },
1745            swizzle: desc.swizzle,
1746        };
1747        let wgpu_texture_view = self.wgpu_texture.create_view(&descriptor);
1748        CoreTextureView { wgpu_texture_view }.into()
1749    }
1750
1751    fn destroy(&self) {
1752        self.wgpu_texture.destroy();
1753    }
1754
1755    fn size(&self) -> wgt::Extent3d {
1756        self.wgpu_texture.descriptor().size
1757    }
1758
1759    fn mip_level_count(&self) -> u32 {
1760        self.wgpu_texture.descriptor().mip_level_count
1761    }
1762
1763    fn sample_count(&self) -> u32 {
1764        self.wgpu_texture.descriptor().sample_count
1765    }
1766
1767    fn dimension(&self) -> wgt::TextureDimension {
1768        self.wgpu_texture.descriptor().dimension
1769    }
1770
1771    fn format(&self) -> wgt::TextureFormat {
1772        self.wgpu_texture.descriptor().format
1773    }
1774
1775    fn usage(&self) -> wgt::TextureUsages {
1776        self.wgpu_texture.descriptor().usage
1777    }
1778
1779    unsafe fn mark_externally_initialized(&self) {
1780        unsafe { self.wgpu_texture.mark_externally_initialized() }
1781    }
1782}
1783
1784impl dispatch::BlasInterface for CoreBlas {
1785    fn prepare_compact_async(&self, callback: BlasCompactCallback) {
1786        let callback: Option<wgc::resource::BlasCompactCallback> =
1787            Some(Box::new(|status: BlasPrepareCompactResult| {
1788                let res = status.map_err(|_| crate::BlasAsyncError);
1789                callback(res);
1790            }));
1791
1792        match self.wgpu_blas.prepare_compact_async(callback) {
1793            Ok(_) => (),
1794            Err(cause) => self
1795                .wgpu_blas
1796                .device()
1797                .handle_error_nolabel(cause, "Blas::prepare_compact_async"),
1798        }
1799    }
1800
1801    fn ready_for_compaction(&self) -> bool {
1802        match self.wgpu_blas.ready_for_compaction() {
1803            Ok(ready) => ready,
1804            Err(cause) => {
1805                self.wgpu_blas
1806                    .device()
1807                    .handle_error_nolabel(cause, "Blas::ready_for_compaction");
1808                // A BLAS is definitely not ready for compaction if it's not valid
1809                false
1810            }
1811        }
1812    }
1813}
1814
1815impl dispatch::TlasInterface for CoreTlas {}
1816
1817impl dispatch::QuerySetInterface for CoreQuerySet {
1818    fn destroy(&self) {
1819        self.wgpu_query_set.destroy();
1820    }
1821
1822    fn ty(&self) -> crate::QueryType {
1823        self.wgpu_query_set.descriptor().ty
1824    }
1825
1826    fn count(&self) -> u32 {
1827        self.wgpu_query_set.descriptor().count
1828    }
1829}
1830
1831impl dispatch::PipelineLayoutInterface for CorePipelineLayout {}
1832
1833impl dispatch::RenderPipelineInterface for CoreRenderPipeline {
1834    fn get_bind_group_layout(&self, index: u32) -> dispatch::DispatchBindGroupLayout {
1835        let wgpu_bind_group_layout = self.wgpu_render_pipeline.get_bind_group_layout(index);
1836        CoreBindGroupLayout {
1837            wgpu_bind_group_layout,
1838        }
1839        .into()
1840    }
1841}
1842
1843impl dispatch::ComputePipelineInterface for CoreComputePipeline {
1844    fn get_bind_group_layout(&self, index: u32) -> dispatch::DispatchBindGroupLayout {
1845        let wgpu_bind_group_layout = self.wgpu_compute_pipeline.get_bind_group_layout(index);
1846        CoreBindGroupLayout {
1847            wgpu_bind_group_layout,
1848        }
1849        .into()
1850    }
1851}
1852
1853impl dispatch::PipelineCacheInterface for CorePipelineCache {
1854    fn get_data(&self) -> Option<Vec<u8>> {
1855        self.wgpu_pipeline_cache.get_data()
1856    }
1857}
1858
1859impl dispatch::CommandEncoderInterface for CoreCommandEncoder {
1860    fn copy_buffer_to_buffer(
1861        &self,
1862        source: &dispatch::DispatchBuffer,
1863        source_offset: crate::BufferAddress,
1864        destination: &dispatch::DispatchBuffer,
1865        destination_offset: crate::BufferAddress,
1866        copy_size: Option<crate::BufferAddress>,
1867    ) {
1868        let source = source.as_core();
1869        let destination = destination.as_core();
1870
1871        self.wgpu_command_encoder.copy_buffer_to_buffer(
1872            source.wgpu_buffer.clone(),
1873            source_offset,
1874            destination.wgpu_buffer.clone(),
1875            destination_offset,
1876            copy_size,
1877        )
1878    }
1879
1880    fn copy_buffer_to_texture(
1881        &self,
1882        source: crate::TexelCopyBufferInfo<'_>,
1883        destination: crate::TexelCopyTextureInfo<'_>,
1884        copy_size: crate::Extent3d,
1885    ) {
1886        self.wgpu_command_encoder.copy_buffer_to_texture(
1887            &map_buffer_copy_view(source),
1888            &map_texture_copy_view(destination),
1889            &copy_size,
1890        )
1891    }
1892
1893    fn copy_texture_to_buffer(
1894        &self,
1895        source: crate::TexelCopyTextureInfo<'_>,
1896        destination: crate::TexelCopyBufferInfo<'_>,
1897        copy_size: crate::Extent3d,
1898    ) {
1899        self.wgpu_command_encoder.copy_texture_to_buffer(
1900            &map_texture_copy_view(source),
1901            &map_buffer_copy_view(destination),
1902            &copy_size,
1903        );
1904    }
1905
1906    fn copy_texture_to_texture(
1907        &self,
1908        source: crate::TexelCopyTextureInfo<'_>,
1909        destination: crate::TexelCopyTextureInfo<'_>,
1910        copy_size: crate::Extent3d,
1911    ) {
1912        self.wgpu_command_encoder.copy_texture_to_texture(
1913            &map_texture_copy_view(source),
1914            &map_texture_copy_view(destination),
1915            &copy_size,
1916        );
1917    }
1918
1919    fn begin_compute_pass(
1920        &self,
1921        desc: &crate::ComputePassDescriptor<'_>,
1922    ) -> dispatch::DispatchComputePass {
1923        let timestamp_writes =
1924            desc.timestamp_writes
1925                .as_ref()
1926                .map(|tw| wgc::command::PassTimestampWrites {
1927                    query_set: tw.query_set.inner.as_core().wgpu_query_set.clone(),
1928                    beginning_of_pass_write_index: tw.beginning_of_pass_write_index,
1929                    end_of_pass_write_index: tw.end_of_pass_write_index,
1930                });
1931
1932        let pass =
1933            self.wgpu_command_encoder
1934                .begin_compute_pass(&wgc::command::ComputePassDescriptor {
1935                    label: desc.label.map(Borrowed),
1936                    timestamp_writes,
1937                });
1938
1939        CoreComputePass {
1940            pass,
1941            id: crate::cmp::Identifier::create(),
1942        }
1943        .into()
1944    }
1945
1946    fn begin_render_pass(
1947        &self,
1948        desc: &crate::RenderPassDescriptor<'_>,
1949    ) -> dispatch::DispatchRenderPass {
1950        let colors = desc
1951            .color_attachments
1952            .iter()
1953            .map(|ca| {
1954                ca.as_ref()
1955                    .map(|at| wgc::command::RenderPassColorAttachment {
1956                        view: at.view.inner.as_core().wgpu_texture_view.clone(),
1957                        depth_slice: at.depth_slice,
1958                        resolve_target: at
1959                            .resolve_target
1960                            .map(|view| view.inner.as_core().wgpu_texture_view.clone()),
1961                        load_op: at.ops.load,
1962                        store_op: at.ops.store,
1963                    })
1964            })
1965            .collect::<Vec<_>>();
1966
1967        let depth_stencil = desc.depth_stencil_attachment.as_ref().map(|dsa| {
1968            wgc::command::RenderPassDepthStencilAttachment {
1969                view: dsa.view.inner.as_core().wgpu_texture_view.clone(),
1970                depth: map_pass_channel(dsa.depth_ops.as_ref()),
1971                stencil: map_pass_channel(dsa.stencil_ops.as_ref()),
1972            }
1973        });
1974
1975        let timestamp_writes =
1976            desc.timestamp_writes
1977                .as_ref()
1978                .map(|tw| wgc::command::PassTimestampWrites {
1979                    query_set: tw.query_set.inner.as_core().wgpu_query_set.clone(),
1980                    beginning_of_pass_write_index: tw.beginning_of_pass_write_index,
1981                    end_of_pass_write_index: tw.end_of_pass_write_index,
1982                });
1983
1984        let pass = self.wgpu_command_encoder.begin_render_pass(
1985            wgc::command::ResolvedRenderPassDescriptor {
1986                label: desc.label.map(Borrowed),
1987                timestamp_writes,
1988                color_attachments: Borrowed(&colors),
1989                depth_stencil_attachment: depth_stencil,
1990                occlusion_query_set: desc
1991                    .occlusion_query_set
1992                    .map(|qs| qs.inner.as_core().wgpu_query_set.clone()),
1993                multiview_mask: desc.multiview_mask,
1994            },
1995        );
1996
1997        CoreRenderPass {
1998            pass,
1999            id: crate::cmp::Identifier::create(),
2000        }
2001        .into()
2002    }
2003
2004    fn finish(&mut self) -> dispatch::DispatchCommandBuffer {
2005        let descriptor = wgt::CommandBufferDescriptor::default();
2006        let wgpu_command_buffer = self.wgpu_command_encoder.finish(&descriptor);
2007        CoreCommandBuffer {
2008            wgpu_command_buffer,
2009        }
2010        .into()
2011    }
2012
2013    fn clear_texture(
2014        &self,
2015        texture: &dispatch::DispatchTexture,
2016        subresource_range: &crate::ImageSubresourceRange,
2017    ) {
2018        let texture = texture.as_core();
2019
2020        self.wgpu_command_encoder
2021            .clear_texture(texture.wgpu_texture.clone(), subresource_range)
2022    }
2023
2024    fn clear_buffer(
2025        &self,
2026        buffer: &dispatch::DispatchBuffer,
2027        offset: crate::BufferAddress,
2028        size: Option<crate::BufferAddress>,
2029    ) {
2030        let buffer = buffer.as_core();
2031
2032        self.wgpu_command_encoder
2033            .clear_buffer(buffer.wgpu_buffer.clone(), offset, size)
2034    }
2035
2036    fn insert_debug_marker(&self, label: &str) {
2037        self.wgpu_command_encoder.insert_debug_marker(label)
2038    }
2039
2040    fn push_debug_group(&self, label: &str) {
2041        self.wgpu_command_encoder.push_debug_group(label)
2042    }
2043
2044    fn pop_debug_group(&self) {
2045        self.wgpu_command_encoder.pop_debug_group()
2046    }
2047
2048    fn write_timestamp(&self, query_set: &dispatch::DispatchQuerySet, query_index: u32) {
2049        let query_set = query_set.as_core();
2050
2051        self.wgpu_command_encoder
2052            .write_timestamp(query_set.wgpu_query_set.clone(), query_index)
2053    }
2054
2055    fn resolve_query_set(
2056        &self,
2057        query_set: &dispatch::DispatchQuerySet,
2058        first_query: u32,
2059        query_count: u32,
2060        destination: &dispatch::DispatchBuffer,
2061        destination_offset: crate::BufferAddress,
2062    ) {
2063        let query_set = query_set.as_core();
2064        let destination = destination.as_core();
2065
2066        self.wgpu_command_encoder.resolve_query_set(
2067            query_set.wgpu_query_set.clone(),
2068            first_query,
2069            query_count,
2070            destination.wgpu_buffer.clone(),
2071            destination_offset,
2072        );
2073    }
2074
2075    fn mark_acceleration_structures_built<'a>(
2076        &self,
2077        blas: &mut dyn Iterator<Item = &'a Blas>,
2078        tlas: &mut dyn Iterator<Item = &'a Tlas>,
2079    ) {
2080        let blas = blas
2081            .map(|b| b.inner.as_core().wgpu_blas.clone())
2082            .collect::<SmallVec<[_; 4]>>();
2083        let tlas = tlas
2084            .map(|t| t.inner.as_core().wgpu_tlas.clone())
2085            .collect::<SmallVec<[_; 4]>>();
2086        self.wgpu_command_encoder
2087            .mark_acceleration_structures_built(&blas, &tlas)
2088    }
2089
2090    fn build_acceleration_structures<'a>(
2091        &self,
2092        blas: &mut dyn Iterator<Item = &'a crate::BlasBuildEntry<'a>>,
2093        tlas: &mut dyn Iterator<Item = &'a crate::Tlas>,
2094    ) {
2095        let blas = blas.map(|e: &crate::BlasBuildEntry<'_>| {
2096            let geometries = match e.geometry {
2097                crate::BlasGeometries::TriangleGeometries(ref triangle_geometries) => {
2098                    let iter = triangle_geometries.iter().map(|tg| {
2099                        wgc::ray_tracing::BlasTriangleGeometry {
2100                            vertex_buffer: tg.vertex_buffer.inner.as_core().wgpu_buffer.clone(),
2101                            index_buffer: tg
2102                                .index_buffer
2103                                .map(|buf| buf.inner.as_core().wgpu_buffer.clone()),
2104                            transform_buffer: tg
2105                                .transform_buffer
2106                                .map(|buf| buf.inner.as_core().wgpu_buffer.clone()),
2107                            size: tg.size,
2108                            transform_buffer_offset: tg.transform_buffer_offset,
2109                            first_vertex: tg.first_vertex,
2110                            vertex_stride: tg.vertex_stride,
2111                            first_index: tg.first_index,
2112                        }
2113                    });
2114                    wgc::ray_tracing::BlasGeometries::TriangleGeometries(Box::new(iter))
2115                }
2116                crate::BlasGeometries::AabbGeometries(ref aabb_geometries) => {
2117                    let iter =
2118                        aabb_geometries
2119                            .iter()
2120                            .map(|ag| wgc::ray_tracing::BlasAabbGeometry {
2121                                aabb_buffer: ag.aabb_buffer.inner.as_core().wgpu_buffer.clone(),
2122                                stride: ag.stride,
2123                                size: ag.size,
2124                                primitive_offset: ag.primitive_offset,
2125                            });
2126                    wgc::ray_tracing::BlasGeometries::AabbGeometries(Box::new(iter))
2127                }
2128            };
2129            wgc::ray_tracing::BlasBuildEntry {
2130                blas: e.blas.inner.as_core().wgpu_blas.clone(),
2131                geometries,
2132            }
2133        });
2134
2135        let tlas = tlas.into_iter().map(|e| {
2136            let instances = e
2137                .instances
2138                .iter()
2139                .map(|instance: &Option<crate::TlasInstance>| {
2140                    instance
2141                        .as_ref()
2142                        .map(|instance| wgc::ray_tracing::ArcTlasInstance {
2143                            blas: instance.blas.as_core().wgpu_blas.clone(),
2144                            transform: instance.transform,
2145                            custom_data: instance.custom_data,
2146                            mask: instance.mask,
2147                        })
2148                })
2149                .collect();
2150            wgc::ray_tracing::ArcTlasPackage {
2151                tlas: e.inner.as_core().wgpu_tlas.clone(),
2152                instances,
2153                lowest_unmodified: e.lowest_unmodified,
2154            }
2155        });
2156
2157        self.wgpu_command_encoder
2158            .build_acceleration_structures(blas, tlas.collect())
2159    }
2160
2161    fn transition_resources<'a>(
2162        &mut self,
2163        buffer_transitions: &mut dyn Iterator<
2164            Item = wgt::BufferTransition<&'a dispatch::DispatchBuffer>,
2165        >,
2166        texture_transitions: &mut dyn Iterator<
2167            Item = wgt::TextureTransition<&'a dispatch::DispatchTexture>,
2168        >,
2169    ) {
2170        self.wgpu_command_encoder.transition_resources(
2171            buffer_transitions.map(|t| wgt::BufferTransition {
2172                buffer: t.buffer.as_core().wgpu_buffer.clone(),
2173                state: t.state,
2174            }),
2175            texture_transitions.map(|t| wgt::TextureTransition {
2176                texture: t.texture.as_core().wgpu_texture.clone(),
2177                selector: t.selector.clone(),
2178                state: t.state,
2179            }),
2180        );
2181    }
2182}
2183
2184impl dispatch::CommandBufferInterface for CoreCommandBuffer {}
2185
2186impl dispatch::ComputePassInterface for CoreComputePass {
2187    fn set_pipeline(&mut self, pipeline: &dispatch::DispatchComputePipeline) {
2188        let pipeline = pipeline.as_core();
2189
2190        self.pass
2191            .set_pipeline(pipeline.wgpu_compute_pipeline.clone());
2192    }
2193
2194    fn set_bind_group(
2195        &mut self,
2196        index: u32,
2197        bind_group: Option<&dispatch::DispatchBindGroup>,
2198        offsets: &[crate::DynamicOffset],
2199    ) {
2200        let bg = bind_group.map(|bg| bg.as_core().wgpu_bind_group.clone());
2201
2202        self.pass.set_bind_group(index, bg, offsets);
2203    }
2204
2205    fn set_immediates(&mut self, offset: u32, data: &[u8]) {
2206        self.pass.set_immediates(offset, data);
2207    }
2208
2209    fn insert_debug_marker(&mut self, label: &str) {
2210        self.pass.insert_debug_marker(label, 0);
2211    }
2212
2213    fn push_debug_group(&mut self, group_label: &str) {
2214        self.pass.push_debug_group(group_label, 0);
2215    }
2216
2217    fn pop_debug_group(&mut self) {
2218        self.pass.pop_debug_group();
2219    }
2220
2221    fn write_timestamp(&mut self, query_set: &dispatch::DispatchQuerySet, query_index: u32) {
2222        let query_set = query_set.as_core();
2223
2224        self.pass
2225            .write_timestamp(query_set.wgpu_query_set.clone(), query_index);
2226    }
2227
2228    fn begin_pipeline_statistics_query(
2229        &mut self,
2230        query_set: &dispatch::DispatchQuerySet,
2231        query_index: u32,
2232    ) {
2233        let query_set = query_set.as_core();
2234
2235        self.pass
2236            .begin_pipeline_statistics_query(query_set.wgpu_query_set.clone(), query_index);
2237    }
2238
2239    fn end_pipeline_statistics_query(&mut self) {
2240        self.pass.end_pipeline_statistics_query();
2241    }
2242
2243    fn dispatch_workgroups(&mut self, x: u32, y: u32, z: u32) {
2244        self.pass.dispatch_workgroups(x, y, z);
2245    }
2246
2247    fn dispatch_workgroups_indirect(
2248        &mut self,
2249        indirect_buffer: &dispatch::DispatchBuffer,
2250        indirect_offset: crate::BufferAddress,
2251    ) {
2252        let indirect_buffer = indirect_buffer.as_core();
2253
2254        self.pass
2255            .dispatch_workgroups_indirect(indirect_buffer.wgpu_buffer.clone(), indirect_offset);
2256    }
2257
2258    fn transition_resources<'a>(
2259        &mut self,
2260        buffer_transitions: &mut dyn Iterator<
2261            Item = wgt::BufferTransition<&'a dispatch::DispatchBuffer>,
2262        >,
2263        texture_transitions: &mut dyn Iterator<
2264            Item = wgt::TextureTransition<&'a dispatch::DispatchTextureView>,
2265        >,
2266    ) {
2267        self.pass.transition_resources(
2268            buffer_transitions.map(|t| wgt::BufferTransition {
2269                buffer: t.buffer.as_core().wgpu_buffer.clone(),
2270                state: t.state,
2271            }),
2272            texture_transitions.map(|t| wgt::TextureTransition {
2273                texture: t.texture.as_core().wgpu_texture_view.clone(),
2274                selector: t.selector.clone(),
2275                state: t.state,
2276            }),
2277        );
2278    }
2279}
2280
2281impl Drop for CoreComputePass {
2282    fn drop(&mut self) {
2283        self.pass.end();
2284    }
2285}
2286
2287impl dispatch::RenderPassInterface for CoreRenderPass {
2288    fn set_pipeline(&mut self, pipeline: &dispatch::DispatchRenderPipeline) {
2289        let pipeline = pipeline.as_core();
2290
2291        self.pass
2292            .set_pipeline(pipeline.wgpu_render_pipeline.clone());
2293    }
2294
2295    fn set_bind_group(
2296        &mut self,
2297        index: u32,
2298        bind_group: Option<&dispatch::DispatchBindGroup>,
2299        offsets: &[crate::DynamicOffset],
2300    ) {
2301        let bg = bind_group.map(|bg| bg.as_core().wgpu_bind_group.clone());
2302
2303        self.pass.set_bind_group(index, bg, offsets);
2304    }
2305
2306    fn set_index_buffer(
2307        &mut self,
2308        buffer: &dispatch::DispatchBuffer,
2309        index_format: crate::IndexFormat,
2310        offset: crate::BufferAddress,
2311        size: Option<crate::BufferSize>,
2312    ) {
2313        let buffer = buffer.as_core();
2314
2315        self.pass
2316            .set_index_buffer(buffer.wgpu_buffer.clone(), index_format, offset, size)
2317    }
2318
2319    fn set_vertex_buffer(
2320        &mut self,
2321        slot: u32,
2322        buffer: Option<&dispatch::DispatchBuffer>,
2323        offset: crate::BufferAddress,
2324        size: Option<crate::BufferSize>,
2325    ) {
2326        let buffer = buffer.map(|buffer| buffer.as_core().wgpu_buffer.clone());
2327
2328        self.pass.set_vertex_buffer(slot, buffer, offset, size);
2329    }
2330
2331    fn set_immediates(&mut self, offset: u32, data: &[u8]) {
2332        self.pass.set_immediates(offset, data);
2333    }
2334
2335    fn set_blend_constant(&mut self, color: crate::Color) {
2336        self.pass.set_blend_constant(color);
2337    }
2338
2339    fn set_scissor_rect(&mut self, x: u32, y: u32, width: u32, height: u32) {
2340        self.pass.set_scissor_rect(x, y, width, height);
2341    }
2342
2343    fn set_viewport(
2344        &mut self,
2345        x: f32,
2346        y: f32,
2347        width: f32,
2348        height: f32,
2349        min_depth: f32,
2350        max_depth: f32,
2351    ) {
2352        self.pass
2353            .set_viewport(x, y, width, height, min_depth, max_depth);
2354    }
2355
2356    fn set_stencil_reference(&mut self, reference: u32) {
2357        self.pass.set_stencil_reference(reference);
2358    }
2359
2360    fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>) {
2361        self.pass.draw(
2362            vertices.end - vertices.start,
2363            instances.end - instances.start,
2364            vertices.start,
2365            instances.start,
2366        );
2367    }
2368
2369    fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>) {
2370        self.pass.draw_indexed(
2371            indices.end - indices.start,
2372            instances.end - instances.start,
2373            indices.start,
2374            base_vertex,
2375            instances.start,
2376        );
2377    }
2378
2379    fn draw_mesh_tasks(&mut self, group_count_x: u32, group_count_y: u32, group_count_z: u32) {
2380        self.pass
2381            .draw_mesh_tasks(group_count_x, group_count_y, group_count_z);
2382    }
2383
2384    fn draw_indirect(
2385        &mut self,
2386        indirect_buffer: &dispatch::DispatchBuffer,
2387        indirect_offset: crate::BufferAddress,
2388    ) {
2389        let indirect_buffer = indirect_buffer.as_core();
2390
2391        self.pass
2392            .draw_indirect(indirect_buffer.wgpu_buffer.clone(), indirect_offset);
2393    }
2394
2395    fn draw_indexed_indirect(
2396        &mut self,
2397        indirect_buffer: &dispatch::DispatchBuffer,
2398        indirect_offset: crate::BufferAddress,
2399    ) {
2400        let indirect_buffer = indirect_buffer.as_core();
2401
2402        self.pass
2403            .draw_indexed_indirect(indirect_buffer.wgpu_buffer.clone(), indirect_offset);
2404    }
2405
2406    fn draw_mesh_tasks_indirect(
2407        &mut self,
2408        indirect_buffer: &dispatch::DispatchBuffer,
2409        indirect_offset: crate::BufferAddress,
2410    ) {
2411        let indirect_buffer = indirect_buffer.as_core();
2412
2413        self.pass
2414            .draw_mesh_tasks_indirect(indirect_buffer.wgpu_buffer.clone(), indirect_offset);
2415    }
2416
2417    fn multi_draw_indirect(
2418        &mut self,
2419        indirect_buffer: &dispatch::DispatchBuffer,
2420        indirect_offset: crate::BufferAddress,
2421        count: u32,
2422    ) {
2423        let indirect_buffer = indirect_buffer.as_core();
2424
2425        self.pass
2426            .multi_draw_indirect(indirect_buffer.wgpu_buffer.clone(), indirect_offset, count);
2427    }
2428
2429    fn multi_draw_indexed_indirect(
2430        &mut self,
2431        indirect_buffer: &dispatch::DispatchBuffer,
2432        indirect_offset: crate::BufferAddress,
2433        count: u32,
2434    ) {
2435        let indirect_buffer = indirect_buffer.as_core();
2436
2437        self.pass.multi_draw_indexed_indirect(
2438            indirect_buffer.wgpu_buffer.clone(),
2439            indirect_offset,
2440            count,
2441        );
2442    }
2443
2444    fn multi_draw_mesh_tasks_indirect(
2445        &mut self,
2446        indirect_buffer: &dispatch::DispatchBuffer,
2447        indirect_offset: crate::BufferAddress,
2448        count: u32,
2449    ) {
2450        let indirect_buffer = indirect_buffer.as_core();
2451
2452        self.pass.multi_draw_mesh_tasks_indirect(
2453            indirect_buffer.wgpu_buffer.clone(),
2454            indirect_offset,
2455            count,
2456        );
2457    }
2458
2459    fn multi_draw_indirect_count(
2460        &mut self,
2461        indirect_buffer: &dispatch::DispatchBuffer,
2462        indirect_offset: crate::BufferAddress,
2463        count_buffer: &dispatch::DispatchBuffer,
2464        count_buffer_offset: crate::BufferAddress,
2465        max_count: u32,
2466    ) {
2467        let indirect_buffer = indirect_buffer.as_core();
2468        let count_buffer = count_buffer.as_core();
2469
2470        self.pass.multi_draw_indirect_count(
2471            indirect_buffer.wgpu_buffer.clone(),
2472            indirect_offset,
2473            count_buffer.wgpu_buffer.clone(),
2474            count_buffer_offset,
2475            max_count,
2476        );
2477    }
2478
2479    fn multi_draw_indexed_indirect_count(
2480        &mut self,
2481        indirect_buffer: &dispatch::DispatchBuffer,
2482        indirect_offset: crate::BufferAddress,
2483        count_buffer: &dispatch::DispatchBuffer,
2484        count_buffer_offset: crate::BufferAddress,
2485        max_count: u32,
2486    ) {
2487        let indirect_buffer = indirect_buffer.as_core();
2488        let count_buffer = count_buffer.as_core();
2489
2490        self.pass.multi_draw_indexed_indirect_count(
2491            indirect_buffer.wgpu_buffer.clone(),
2492            indirect_offset,
2493            count_buffer.wgpu_buffer.clone(),
2494            count_buffer_offset,
2495            max_count,
2496        );
2497    }
2498
2499    fn multi_draw_mesh_tasks_indirect_count(
2500        &mut self,
2501        indirect_buffer: &dispatch::DispatchBuffer,
2502        indirect_offset: crate::BufferAddress,
2503        count_buffer: &dispatch::DispatchBuffer,
2504        count_buffer_offset: crate::BufferAddress,
2505        max_count: u32,
2506    ) {
2507        let indirect_buffer = indirect_buffer.as_core();
2508        let count_buffer = count_buffer.as_core();
2509
2510        self.pass.multi_draw_mesh_tasks_indirect_count(
2511            indirect_buffer.wgpu_buffer.clone(),
2512            indirect_offset,
2513            count_buffer.wgpu_buffer.clone(),
2514            count_buffer_offset,
2515            max_count,
2516        );
2517    }
2518
2519    fn insert_debug_marker(&mut self, label: &str) {
2520        self.pass.insert_debug_marker(label, 0);
2521    }
2522
2523    fn push_debug_group(&mut self, group_label: &str) {
2524        self.pass.push_debug_group(group_label, 0);
2525    }
2526
2527    fn pop_debug_group(&mut self) {
2528        self.pass.pop_debug_group();
2529    }
2530
2531    fn write_timestamp(&mut self, query_set: &dispatch::DispatchQuerySet, query_index: u32) {
2532        let query_set = query_set.as_core();
2533
2534        self.pass
2535            .write_timestamp(query_set.wgpu_query_set.clone(), query_index);
2536    }
2537
2538    fn begin_occlusion_query(&mut self, query_index: u32) {
2539        self.pass.begin_occlusion_query(query_index);
2540    }
2541
2542    fn end_occlusion_query(&mut self) {
2543        self.pass.end_occlusion_query();
2544    }
2545
2546    fn begin_pipeline_statistics_query(
2547        &mut self,
2548        query_set: &dispatch::DispatchQuerySet,
2549        query_index: u32,
2550    ) {
2551        let query_set = query_set.as_core();
2552
2553        self.pass
2554            .begin_pipeline_statistics_query(query_set.wgpu_query_set.clone(), query_index);
2555    }
2556
2557    fn end_pipeline_statistics_query(&mut self) {
2558        self.pass.end_pipeline_statistics_query();
2559    }
2560
2561    fn execute_bundles(
2562        &mut self,
2563        render_bundles: &mut dyn Iterator<Item = &dispatch::DispatchRenderBundle>,
2564    ) {
2565        let temp_render_bundles = render_bundles
2566            .map(|rb| rb.as_core().wgpu_render_bundle.clone())
2567            .collect::<SmallVec<[_; 4]>>();
2568        self.pass.execute_bundles(&temp_render_bundles);
2569    }
2570}
2571
2572impl Drop for CoreRenderPass {
2573    fn drop(&mut self) {
2574        self.pass.end()
2575    }
2576}
2577
2578impl dispatch::RenderBundleEncoderInterface for CoreRenderBundleEncoder {
2579    fn set_pipeline(&mut self, pipeline: &dispatch::DispatchRenderPipeline) {
2580        let pipeline = pipeline.as_core();
2581
2582        self.encoder
2583            .set_pipeline(pipeline.wgpu_render_pipeline.clone())
2584    }
2585
2586    fn set_bind_group(
2587        &mut self,
2588        index: u32,
2589        bind_group: Option<&dispatch::DispatchBindGroup>,
2590        offsets: &[crate::DynamicOffset],
2591    ) {
2592        let bg = bind_group.map(|bg| bg.as_core().wgpu_bind_group.clone());
2593
2594        self.encoder.set_bind_group(index, bg, offsets);
2595    }
2596
2597    fn set_index_buffer(
2598        &mut self,
2599        buffer: &dispatch::DispatchBuffer,
2600        index_format: crate::IndexFormat,
2601        offset: crate::BufferAddress,
2602        size: Option<crate::BufferSize>,
2603    ) {
2604        let buffer = buffer.as_core();
2605
2606        self.encoder
2607            .set_index_buffer(buffer.wgpu_buffer.clone(), index_format, offset, size);
2608    }
2609
2610    fn set_vertex_buffer(
2611        &mut self,
2612        slot: u32,
2613        buffer: Option<&dispatch::DispatchBuffer>,
2614        offset: crate::BufferAddress,
2615        size: Option<crate::BufferSize>,
2616    ) {
2617        let buffer = buffer.map(|buffer| buffer.as_core().wgpu_buffer.clone());
2618
2619        self.encoder.set_vertex_buffer(slot, buffer, offset, size);
2620    }
2621
2622    fn set_immediates(&mut self, offset: u32, data: &[u8]) {
2623        if !data
2624            .len()
2625            .is_multiple_of(wgt::IMMEDIATE_DATA_ALIGNMENT as usize)
2626        {
2627            self.encoder.device().handle_error(
2628                wgc::binding_model::ImmediateUploadError::SizeUnaligned(data.len()),
2629                self.encoder.label(),
2630                "RenderBundleEncoder::set_immediates",
2631            );
2632            return;
2633        }
2634
2635        self.encoder.set_immediates(offset, data);
2636    }
2637
2638    fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>) {
2639        self.encoder.draw(
2640            vertices.end - vertices.start,
2641            instances.end - instances.start,
2642            vertices.start,
2643            instances.start,
2644        );
2645    }
2646
2647    fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>) {
2648        self.encoder.draw_indexed(
2649            indices.end - indices.start,
2650            instances.end - instances.start,
2651            indices.start,
2652            base_vertex,
2653            instances.start,
2654        );
2655    }
2656
2657    fn draw_indirect(
2658        &mut self,
2659        indirect_buffer: &dispatch::DispatchBuffer,
2660        indirect_offset: crate::BufferAddress,
2661    ) {
2662        let indirect_buffer = indirect_buffer.as_core();
2663
2664        self.encoder
2665            .draw_indirect(indirect_buffer.wgpu_buffer.clone(), indirect_offset);
2666    }
2667
2668    fn draw_indexed_indirect(
2669        &mut self,
2670        indirect_buffer: &dispatch::DispatchBuffer,
2671        indirect_offset: crate::BufferAddress,
2672    ) {
2673        let indirect_buffer = indirect_buffer.as_core();
2674
2675        self.encoder
2676            .draw_indexed_indirect(indirect_buffer.wgpu_buffer.clone(), indirect_offset);
2677    }
2678
2679    fn finish(mut self, desc: &crate::RenderBundleDescriptor<'_>) -> dispatch::DispatchRenderBundle
2680    where
2681        Self: Sized,
2682    {
2683        let wgpu_render_bundle = self.encoder.finish(&desc.map_label(|l| l.map(Borrowed)));
2684        CoreRenderBundle { wgpu_render_bundle }.into()
2685    }
2686
2687    #[cfg(custom)]
2688    fn finish_boxed(
2689        self: Box<Self>,
2690        desc: &crate::RenderBundleDescriptor<'_>,
2691    ) -> dispatch::DispatchRenderBundle {
2692        (*self).finish(desc)
2693    }
2694}
2695
2696impl dispatch::RenderBundleInterface for CoreRenderBundle {}
2697
2698#[derive(Clone)]
2699enum ErrorSink {
2700    Actual(Arc<wgc::device::Device>),
2701    Dummy(Arc<Mutex<wgc::error::ErrorSink>>),
2702}
2703
2704impl ErrorSink {
2705    fn new() -> Self {
2706        Self::Dummy(Arc::new(Mutex::new(wgc::error::ErrorSink::new())))
2707    }
2708
2709    fn handle_error_nolabel(
2710        &self,
2711        source: impl WebGpuError + WasmNotSendSync + 'static,
2712        fn_ident: &'static str,
2713    ) {
2714        match self {
2715            ErrorSink::Actual(device) => device.handle_error_nolabel(source, fn_ident),
2716            ErrorSink::Dummy(sink) => sink.lock().handle_error_nolabel(source, fn_ident),
2717        }
2718    }
2719}
2720
2721impl dispatch::SurfaceInterface for CoreSurface {
2722    fn get_capabilities(&self, adapter: &dispatch::DispatchAdapter) -> wgt::SurfaceCapabilities {
2723        let adapter = adapter.as_core();
2724
2725        self.wgpu_surface
2726            .get_capabilities(&adapter.wgpu_adapter)
2727            .unwrap_or_default()
2728    }
2729
2730    fn display_hdr_info(&self, adapter: &dispatch::DispatchAdapter) -> wgt::DisplayHdrInfo {
2731        let adapter = adapter.as_core();
2732
2733        self.wgpu_surface.display_hdr_info(&adapter.wgpu_adapter)
2734    }
2735
2736    fn configure(&self, device: &dispatch::DispatchDevice, config: &crate::SurfaceConfiguration) {
2737        let device = device.as_core();
2738
2739        let error = self.wgpu_surface.configure(&device.wgpu_device, config);
2740        if let Some(e) = error {
2741            device
2742                .wgpu_device
2743                .handle_error_nolabel(e, "Surface::configure");
2744        } else {
2745            *self.configured_device.lock() = Some(device.wgpu_device.clone());
2746        }
2747    }
2748
2749    fn get_current_texture(
2750        &self,
2751        _desc: Option<crate::TextureDescriptor<'static>>,
2752    ) -> (
2753        Option<dispatch::DispatchTexture>,
2754        crate::SurfaceStatus,
2755        dispatch::DispatchSurfaceOutputDetail,
2756    ) {
2757        let error_sink = if let Some(error_sink) = self.configured_device.lock().as_ref() {
2758            ErrorSink::Actual(error_sink.clone())
2759        } else {
2760            ErrorSink::new()
2761        };
2762
2763        let output_detail = CoreSurfaceOutputDetail {
2764            wgpu_surface: self.wgpu_surface.clone(),
2765            error_sink,
2766        }
2767        .into();
2768
2769        match self.wgpu_surface.get_current_texture() {
2770            Ok(wgc::present::SurfaceOutput {
2771                status,
2772                texture: texture_id,
2773            }) => {
2774                let data = texture_id
2775                    .map(|wgpu_texture| CoreTexture { wgpu_texture })
2776                    .map(Into::into);
2777
2778                (data, status, output_detail)
2779            }
2780            Err(err) => {
2781                let error_sink = self.configured_device.lock();
2782                match error_sink.as_ref() {
2783                    Some(error_sink) => {
2784                        error_sink.handle_error_nolabel(err, "Surface::get_current_texture_view");
2785                        (None, crate::SurfaceStatus::Validation, output_detail)
2786                    }
2787                    None => handle_error_fatal(err, "Surface::get_current_texture_view"),
2788                }
2789            }
2790        }
2791    }
2792}
2793
2794impl dispatch::SurfaceOutputDetailInterface for CoreSurfaceOutputDetail {
2795    fn texture_discard(&self) {
2796        match self.wgpu_surface.discard() {
2797            Ok(_status) => (),
2798            Err(err) => self
2799                .error_sink
2800                .handle_error_nolabel(err, "Surface::discard_texture"),
2801        }
2802    }
2803
2804    fn texture_release(&self) {
2805        match self.wgpu_surface.release() {
2806            Ok(_status) => (),
2807            Err(err) => self
2808                .error_sink
2809                .handle_error_nolabel(err, "Surface::release_texture"),
2810        }
2811    }
2812}
2813
2814impl dispatch::QueueWriteBufferInterface for CoreQueueWriteBuffer {
2815    #[inline]
2816    fn len(&self) -> usize {
2817        self.mapping.len()
2818    }
2819
2820    #[inline]
2821    unsafe fn write_slice(&mut self) -> WriteOnly<'_, [u8]> {
2822        unsafe { self.mapping.write_slice() }
2823    }
2824}
2825
2826impl dispatch::BufferMappedRangeInterface for CoreBufferMappedRange {
2827    #[inline]
2828    fn len(&self) -> usize {
2829        self.size
2830    }
2831
2832    #[inline]
2833    unsafe fn read_slice(&self) -> &[u8] {
2834        unsafe { slice::from_raw_parts(self.ptr.as_ptr(), self.size) }
2835    }
2836
2837    #[inline]
2838    unsafe fn write_slice(&mut self) -> WriteOnly<'_, [u8]> {
2839        unsafe { WriteOnly::new(NonNull::slice_from_raw_parts(self.ptr, self.size)) }
2840    }
2841
2842    #[cfg(webgpu)]
2843    fn as_uint8array(&self) -> &js_sys::Uint8Array {
2844        panic!("Only available on WebGPU")
2845    }
2846}