Skip to main content

wgpu/backend/
wgpu_core.rs

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