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