Skip to main content

wgpu/backend/
wgpu_core.rs

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