Skip to main content

wgpu/backend/
wgpu_core.rs

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