wgpu/backend/
wgpu_core.rs

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