wgpu/backend/
wgpu_core.rs

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