wgpu/backend/
wgpu_core.rs

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