wgpu/backend/
wgpu_core.rs

1use alloc::{
2    borrow::Cow::{self, Borrowed},
3    boxed::Box,
4    format,
5    string::{String, ToString as _},
6    sync::Arc,
7    vec,
8    vec::Vec,
9};
10use core::{
11    error::Error,
12    fmt,
13    future::ready,
14    ops::{Deref, Range},
15    pin::Pin,
16    ptr::NonNull,
17    slice,
18};
19use hashbrown::HashMap;
20
21use arrayvec::ArrayVec;
22use smallvec::SmallVec;
23use wgc::{
24    error::ContextErrorSource, pipeline::CreateShaderModuleError,
25    resource::BlasPrepareCompactResult,
26};
27use wgt::{
28    error::{ErrorType, WebGpuError},
29    WasmNotSendSync,
30};
31
32use crate::{
33    api,
34    dispatch::{self, BlasCompactCallback, BufferMappedRangeInterface},
35    BindingResource, Blas, BufferBinding, BufferDescriptor, CompilationInfo, CompilationMessage,
36    CompilationMessageType, ErrorSource, Features, Label, LoadOp, MapMode, Operations,
37    ShaderSource, SurfaceTargetUnsafe, TextureDescriptor, Tlas, WriteOnly,
38};
39use crate::{dispatch::DispatchAdapter, util::Mutex};
40
41mod thread_id;
42
43#[derive(Clone)]
44pub struct ContextWgpuCore(Arc<wgc::global::Global>);
45
46impl Drop for ContextWgpuCore {
47    fn drop(&mut self) {
48        //nothing
49    }
50}
51
52impl fmt::Debug for ContextWgpuCore {
53    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54        f.debug_struct("ContextWgpuCore")
55            .field("type", &"Native")
56            .finish()
57    }
58}
59
60impl ContextWgpuCore {
61    pub unsafe fn from_hal_instance<A: hal::Api>(hal_instance: A::Instance) -> Self {
62        Self(unsafe {
63            Arc::new(wgc::global::Global::from_hal_instance::<A>(
64                "wgpu",
65                hal_instance,
66            ))
67        })
68    }
69
70    /// # Safety
71    ///
72    /// - The raw instance handle returned must not be manually destroyed.
73    pub unsafe fn instance_as_hal<A: hal::Api>(&self) -> Option<&A::Instance> {
74        unsafe { self.0.instance_as_hal::<A>() }
75    }
76
77    pub unsafe fn from_core_instance(core_instance: wgc::instance::Instance) -> Self {
78        Self(unsafe { Arc::new(wgc::global::Global::from_instance(core_instance)) })
79    }
80
81    #[cfg(wgpu_core)]
82    pub fn enumerate_adapters(&self, backends: wgt::Backends) -> Vec<wgc::id::AdapterId> {
83        self.0
84            .enumerate_adapters(backends, false /* no limit bucketing */)
85    }
86
87    pub unsafe fn create_adapter_from_hal<A: hal::Api>(
88        &self,
89        hal_adapter: hal::ExposedAdapter<A>,
90    ) -> wgc::id::AdapterId {
91        unsafe { self.0.create_adapter_from_hal(hal_adapter.into(), None) }
92    }
93
94    pub unsafe fn adapter_as_hal<A: hal::Api>(
95        &self,
96        adapter: &CoreAdapter,
97    ) -> Option<impl Deref<Target = A::Adapter> + WasmNotSendSync> {
98        unsafe { self.0.adapter_as_hal::<A>(adapter.id) }
99    }
100
101    pub unsafe fn buffer_as_hal<A: hal::Api>(
102        &self,
103        buffer: &CoreBuffer,
104    ) -> Option<impl Deref<Target = A::Buffer>> {
105        unsafe { self.0.buffer_as_hal::<A>(buffer.id) }
106    }
107
108    pub unsafe fn create_device_from_hal<A: hal::Api>(
109        &self,
110        adapter: &CoreAdapter,
111        hal_device: hal::OpenDevice<A>,
112        desc: &crate::DeviceDescriptor<'_>,
113    ) -> Result<(CoreDevice, CoreQueue), crate::RequestDeviceError> {
114        let (device_id, queue_id) = unsafe {
115            self.0.create_device_from_hal(
116                adapter.id,
117                hal_device.into(),
118                &desc.map_label(|l| l.map(Borrowed)),
119                None,
120                None,
121            )
122        }?;
123        let error_sink = Arc::new(Mutex::new(ErrorSinkRaw::new()));
124        let device = CoreDevice {
125            context: self.clone(),
126            id: device_id,
127            error_sink: error_sink.clone(),
128            features: desc.required_features,
129        };
130        let queue = CoreQueue {
131            context: self.clone(),
132            id: queue_id,
133            error_sink,
134        };
135        Ok((device, queue))
136    }
137
138    pub unsafe fn create_texture_from_hal<A: hal::Api>(
139        &self,
140        hal_texture: A::Texture,
141        device: &CoreDevice,
142        desc: &TextureDescriptor<'_>,
143        initial_state: wgt::TextureUses,
144    ) -> CoreTexture {
145        let descriptor = desc.map_label_and_view_formats(|l| l.map(Borrowed), |v| v.to_vec());
146        let (id, error) = unsafe {
147            self.0.create_texture_from_hal(
148                Box::new(hal_texture),
149                device.id,
150                &descriptor,
151                initial_state,
152                None,
153            )
154        };
155        if let Some(cause) = error {
156            self.handle_error(
157                &device.error_sink,
158                cause,
159                desc.label,
160                "Device::create_texture_from_hal",
161            );
162        }
163        CoreTexture {
164            context: self.clone(),
165            id,
166            error_sink: Arc::clone(&device.error_sink),
167        }
168    }
169
170    /// # Safety
171    ///
172    /// - `hal_buffer` must be created from `device`.
173    /// - `hal_buffer` must be created respecting `desc`
174    /// - `hal_buffer` must be initialized
175    /// - `hal_buffer` must not have zero size.
176    pub unsafe fn create_buffer_from_hal<A: hal::Api>(
177        &self,
178        hal_buffer: A::Buffer,
179        device: &CoreDevice,
180        desc: &BufferDescriptor<'_>,
181    ) -> CoreBuffer {
182        let (id, error) = unsafe {
183            self.0.create_buffer_from_hal::<A>(
184                hal_buffer,
185                device.id,
186                &desc.map_label(|l| l.map(Borrowed)),
187                None,
188            )
189        };
190        if let Some(cause) = error {
191            self.handle_error(
192                &device.error_sink,
193                cause,
194                desc.label,
195                "Device::create_buffer_from_hal",
196            );
197        }
198        CoreBuffer {
199            context: self.clone(),
200            id,
201            error_sink: Arc::clone(&device.error_sink),
202        }
203    }
204
205    pub unsafe fn device_as_hal<A: hal::Api>(
206        &self,
207        device: &CoreDevice,
208    ) -> Option<impl Deref<Target = A::Device>> {
209        unsafe { self.0.device_as_hal::<A>(device.id) }
210    }
211
212    pub unsafe fn surface_as_hal<A: hal::Api>(
213        &self,
214        surface: &CoreSurface,
215    ) -> Option<impl Deref<Target = A::Surface>> {
216        unsafe { self.0.surface_as_hal::<A>(surface.id) }
217    }
218
219    pub unsafe fn texture_as_hal<A: hal::Api>(
220        &self,
221        texture: &CoreTexture,
222    ) -> Option<impl Deref<Target = A::Texture>> {
223        unsafe { self.0.texture_as_hal::<A>(texture.id) }
224    }
225
226    pub unsafe fn texture_view_as_hal<A: hal::Api>(
227        &self,
228        texture_view: &CoreTextureView,
229    ) -> Option<impl Deref<Target = A::TextureView>> {
230        unsafe { self.0.texture_view_as_hal::<A>(texture_view.id) }
231    }
232
233    /// This method will start the wgpu_core level command recording.
234    pub unsafe fn command_encoder_as_hal_mut<
235        A: hal::Api,
236        F: FnOnce(Option<&mut A::CommandEncoder>) -> R,
237        R,
238    >(
239        &self,
240        command_encoder: &CoreCommandEncoder,
241        hal_command_encoder_callback: F,
242    ) -> R {
243        unsafe {
244            self.0.command_encoder_as_hal_mut::<A, F, R>(
245                command_encoder.id,
246                hal_command_encoder_callback,
247            )
248        }
249    }
250
251    pub unsafe fn blas_as_hal<A: hal::Api>(
252        &self,
253        blas: &CoreBlas,
254    ) -> Option<impl Deref<Target = A::AccelerationStructure>> {
255        unsafe { self.0.blas_as_hal::<A>(blas.id) }
256    }
257
258    pub unsafe fn tlas_as_hal<A: hal::Api>(
259        &self,
260        tlas: &CoreTlas,
261    ) -> Option<impl Deref<Target = A::AccelerationStructure>> {
262        unsafe { self.0.tlas_as_hal::<A>(tlas.id) }
263    }
264
265    pub fn generate_report(&self) -> wgc::global::GlobalReport {
266        self.0.generate_report()
267    }
268
269    #[cold]
270    #[track_caller]
271    #[inline(never)]
272    fn handle_error_inner(
273        &self,
274        sink_mutex: &Mutex<ErrorSinkRaw>,
275        error_type: ErrorType,
276        source: ContextErrorSource,
277        label: Label<'_>,
278        fn_ident: &'static str,
279    ) {
280        let source: ErrorSource = Box::new(wgc::error::ContextError {
281            fn_ident,
282            source,
283            label: label.unwrap_or_default().to_string(),
284        });
285        let final_error_handling = {
286            let mut sink = sink_mutex.lock();
287            let description = || self.format_error(&*source);
288            let error = match error_type {
289                ErrorType::Internal => {
290                    let description = description();
291                    crate::Error::Internal {
292                        source,
293                        description,
294                    }
295                }
296                ErrorType::OutOfMemory => crate::Error::OutOfMemory { source },
297                ErrorType::Validation => {
298                    let description = description();
299                    crate::Error::Validation {
300                        source,
301                        description,
302                    }
303                }
304                ErrorType::DeviceLost => return, // will be surfaced via callback
305            };
306            sink.handle_error_or_return_handler(error)
307        };
308
309        if let Some(f) = final_error_handling {
310            // If the user has provided their own `uncaptured_handler` callback, invoke it now,
311            // having released our lock on `sink_mutex`. See the comments on
312            // `handle_error_or_return_handler` for details.
313            f();
314        }
315    }
316
317    #[inline]
318    #[track_caller]
319    fn handle_error(
320        &self,
321        sink_mutex: &Mutex<ErrorSinkRaw>,
322        source: impl WebGpuError + WasmNotSendSync + 'static,
323        label: Label<'_>,
324        fn_ident: &'static str,
325    ) {
326        let error_type = source.webgpu_error_type();
327        self.handle_error_inner(sink_mutex, error_type, Box::new(source), label, fn_ident)
328    }
329
330    #[inline]
331    #[track_caller]
332    fn handle_error_nolabel(
333        &self,
334        sink_mutex: &Mutex<ErrorSinkRaw>,
335        source: impl WebGpuError + WasmNotSendSync + 'static,
336        fn_ident: &'static str,
337    ) {
338        let error_type = source.webgpu_error_type();
339        self.handle_error_inner(sink_mutex, error_type, Box::new(source), None, fn_ident)
340    }
341
342    #[track_caller]
343    #[cold]
344    fn handle_error_fatal(
345        &self,
346        cause: impl Error + WasmNotSendSync + 'static,
347        operation: &'static str,
348    ) -> ! {
349        panic!("Error in {operation}: {f}", f = self.format_error(&cause));
350    }
351
352    #[inline(never)]
353    fn format_error(&self, err: &(dyn Error + 'static)) -> String {
354        let mut output = String::new();
355        let mut level = 1;
356
357        fn print_tree(output: &mut String, level: &mut usize, e: &(dyn Error + 'static)) {
358            let mut print = |e: &(dyn Error + 'static)| {
359                use core::fmt::Write;
360                writeln!(output, "{}{}", " ".repeat(*level * 2), e).unwrap();
361
362                if let Some(e) = e.source() {
363                    *level += 1;
364                    print_tree(output, level, e);
365                    *level -= 1;
366                }
367            };
368            if let Some(multi) = e.downcast_ref::<wgc::error::MultiError>() {
369                for e in multi.errors() {
370                    print(e);
371                }
372            } else {
373                print(e);
374            }
375        }
376
377        print_tree(&mut output, &mut level, err);
378
379        format!("Validation Error\n\nCaused by:\n{output}")
380    }
381
382    pub unsafe fn queue_as_hal<A: hal::Api>(
383        &self,
384        queue: &CoreQueue,
385    ) -> Option<impl Deref<Target = A::Queue> + WasmNotSendSync> {
386        unsafe { self.0.queue_as_hal::<A>(queue.id) }
387    }
388}
389
390fn map_buffer_copy_view(
391    view: crate::TexelCopyBufferInfo<'_>,
392) -> wgt::TexelCopyBufferInfo<wgc::id::BufferId> {
393    wgt::TexelCopyBufferInfo {
394        buffer: view.buffer.inner.as_core().id,
395        layout: view.layout,
396    }
397}
398
399fn map_texture_copy_view(
400    view: crate::TexelCopyTextureInfo<'_>,
401) -> wgt::TexelCopyTextureInfo<wgc::id::TextureId> {
402    wgt::TexelCopyTextureInfo {
403        texture: view.texture.inner.as_core().id,
404        mip_level: view.mip_level,
405        origin: view.origin,
406        aspect: view.aspect,
407    }
408}
409
410#[cfg_attr(not(webgl), expect(unused))]
411fn map_texture_tagged_copy_view(
412    view: crate::CopyExternalImageDestInfo<&api::Texture>,
413) -> wgt::CopyExternalImageDestInfo<wgc::id::TextureId> {
414    wgt::CopyExternalImageDestInfo {
415        texture: view.texture.inner.as_core().id,
416        mip_level: view.mip_level,
417        origin: view.origin,
418        aspect: view.aspect,
419        color_space: view.color_space,
420        premultiplied_alpha: view.premultiplied_alpha,
421    }
422}
423
424fn map_load_op<V: Copy>(load: &LoadOp<V>) -> LoadOp<Option<V>> {
425    match *load {
426        LoadOp::Clear(clear_value) => LoadOp::Clear(Some(clear_value)),
427        LoadOp::DontCare(token) => LoadOp::DontCare(token),
428        LoadOp::Load => LoadOp::Load,
429    }
430}
431
432fn map_pass_channel<V: Copy>(ops: Option<&Operations<V>>) -> wgc::command::PassChannel<Option<V>> {
433    match ops {
434        Some(&Operations { load, store }) => wgc::command::PassChannel {
435            load_op: Some(map_load_op(&load)),
436            store_op: Some(store),
437            read_only: false,
438        },
439        None => wgc::command::PassChannel {
440            load_op: None,
441            store_op: None,
442            read_only: true,
443        },
444    }
445}
446
447#[derive(Debug)]
448pub struct CoreSurface {
449    pub(crate) context: ContextWgpuCore,
450    id: wgc::id::SurfaceId,
451    /// Configured device is needed to know which backend
452    /// code to execute when acquiring a new frame.
453    configured_device: Mutex<Option<wgc::id::DeviceId>>,
454    /// The error sink with which to report errors.
455    /// `None` if the surface has not been configured.
456    error_sink: Mutex<Option<ErrorSink>>,
457}
458
459#[derive(Debug)]
460pub struct CoreAdapter {
461    pub(crate) context: ContextWgpuCore,
462    pub(crate) id: wgc::id::AdapterId,
463}
464
465#[derive(Debug)]
466pub struct CoreDevice {
467    pub(crate) context: ContextWgpuCore,
468    id: wgc::id::DeviceId,
469    error_sink: ErrorSink,
470    features: Features,
471}
472
473#[derive(Debug)]
474pub struct CoreBuffer {
475    pub(crate) context: ContextWgpuCore,
476    id: wgc::id::BufferId,
477    error_sink: ErrorSink,
478}
479
480#[derive(Debug)]
481pub struct CoreShaderModule {
482    pub(crate) context: ContextWgpuCore,
483    id: wgc::id::ShaderModuleId,
484    compilation_info: CompilationInfo,
485}
486
487#[derive(Debug)]
488pub struct CoreBindGroupLayout {
489    pub(crate) context: ContextWgpuCore,
490    id: wgc::id::BindGroupLayoutId,
491}
492
493#[derive(Debug)]
494pub struct CoreBindGroup {
495    pub(crate) context: ContextWgpuCore,
496    id: wgc::id::BindGroupId,
497}
498
499#[derive(Debug)]
500pub struct CoreTexture {
501    pub(crate) context: ContextWgpuCore,
502    id: wgc::id::TextureId,
503    error_sink: ErrorSink,
504}
505
506#[derive(Debug)]
507pub struct CoreTextureView {
508    pub(crate) context: ContextWgpuCore,
509    id: wgc::id::TextureViewId,
510}
511
512#[derive(Debug)]
513pub struct CoreExternalTexture {
514    pub(crate) context: ContextWgpuCore,
515    id: wgc::id::ExternalTextureId,
516}
517
518#[derive(Debug)]
519pub struct CoreSampler {
520    pub(crate) context: ContextWgpuCore,
521    id: wgc::id::SamplerId,
522}
523
524#[derive(Debug)]
525pub struct CoreQuerySet {
526    pub(crate) context: ContextWgpuCore,
527    id: wgc::id::QuerySetId,
528}
529
530#[derive(Debug)]
531pub struct CorePipelineLayout {
532    pub(crate) context: ContextWgpuCore,
533    id: wgc::id::PipelineLayoutId,
534}
535
536#[derive(Debug)]
537pub struct CorePipelineCache {
538    pub(crate) context: ContextWgpuCore,
539    id: wgc::id::PipelineCacheId,
540}
541
542#[derive(Debug)]
543pub struct CoreCommandBuffer {
544    pub(crate) context: ContextWgpuCore,
545    id: wgc::id::CommandBufferId,
546}
547
548#[derive(Debug)]
549pub struct CoreRenderBundleEncoder {
550    pub(crate) context: ContextWgpuCore,
551    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    fn destroy(&self) {
2393        self.context.0.query_set_destroy(self.id);
2394    }
2395}
2396
2397impl Drop for CoreQuerySet {
2398    fn drop(&mut self) {
2399        self.context.0.query_set_drop(self.id)
2400    }
2401}
2402
2403impl dispatch::PipelineLayoutInterface for CorePipelineLayout {}
2404
2405impl Drop for CorePipelineLayout {
2406    fn drop(&mut self) {
2407        self.context.0.pipeline_layout_drop(self.id)
2408    }
2409}
2410
2411impl dispatch::RenderPipelineInterface for CoreRenderPipeline {
2412    fn get_bind_group_layout(&self, index: u32) -> dispatch::DispatchBindGroupLayout {
2413        let (id, error) = self
2414            .context
2415            .0
2416            .render_pipeline_get_bind_group_layout(self.id, index, None);
2417        if let Some(err) = error {
2418            self.context.handle_error_nolabel(
2419                &self.error_sink,
2420                err,
2421                "RenderPipeline::get_bind_group_layout",
2422            )
2423        }
2424        CoreBindGroupLayout {
2425            context: self.context.clone(),
2426            id,
2427        }
2428        .into()
2429    }
2430}
2431
2432impl Drop for CoreRenderPipeline {
2433    fn drop(&mut self) {
2434        self.context.0.render_pipeline_drop(self.id)
2435    }
2436}
2437
2438impl dispatch::ComputePipelineInterface for CoreComputePipeline {
2439    fn get_bind_group_layout(&self, index: u32) -> dispatch::DispatchBindGroupLayout {
2440        let (id, error) = self
2441            .context
2442            .0
2443            .compute_pipeline_get_bind_group_layout(self.id, index, None);
2444        if let Some(err) = error {
2445            self.context.handle_error_nolabel(
2446                &self.error_sink,
2447                err,
2448                "ComputePipeline::get_bind_group_layout",
2449            )
2450        }
2451        CoreBindGroupLayout {
2452            context: self.context.clone(),
2453            id,
2454        }
2455        .into()
2456    }
2457}
2458
2459impl Drop for CoreComputePipeline {
2460    fn drop(&mut self) {
2461        self.context.0.compute_pipeline_drop(self.id)
2462    }
2463}
2464
2465impl dispatch::PipelineCacheInterface for CorePipelineCache {
2466    fn get_data(&self) -> Option<Vec<u8>> {
2467        self.context.0.pipeline_cache_get_data(self.id)
2468    }
2469}
2470
2471impl Drop for CorePipelineCache {
2472    fn drop(&mut self) {
2473        self.context.0.pipeline_cache_drop(self.id)
2474    }
2475}
2476
2477impl dispatch::CommandEncoderInterface for CoreCommandEncoder {
2478    fn copy_buffer_to_buffer(
2479        &self,
2480        source: &dispatch::DispatchBuffer,
2481        source_offset: crate::BufferAddress,
2482        destination: &dispatch::DispatchBuffer,
2483        destination_offset: crate::BufferAddress,
2484        copy_size: Option<crate::BufferAddress>,
2485    ) {
2486        let source = source.as_core();
2487        let destination = destination.as_core();
2488
2489        if let Err(cause) = self.context.0.command_encoder_copy_buffer_to_buffer(
2490            self.id,
2491            source.id,
2492            source_offset,
2493            destination.id,
2494            destination_offset,
2495            copy_size,
2496        ) {
2497            self.context.handle_error_nolabel(
2498                &self.error_sink,
2499                cause,
2500                "CommandEncoder::copy_buffer_to_buffer",
2501            );
2502        }
2503    }
2504
2505    fn copy_buffer_to_texture(
2506        &self,
2507        source: crate::TexelCopyBufferInfo<'_>,
2508        destination: crate::TexelCopyTextureInfo<'_>,
2509        copy_size: crate::Extent3d,
2510    ) {
2511        if let Err(cause) = self.context.0.command_encoder_copy_buffer_to_texture(
2512            self.id,
2513            &map_buffer_copy_view(source),
2514            &map_texture_copy_view(destination),
2515            &copy_size,
2516        ) {
2517            self.context.handle_error_nolabel(
2518                &self.error_sink,
2519                cause,
2520                "CommandEncoder::copy_buffer_to_texture",
2521            );
2522        }
2523    }
2524
2525    fn copy_texture_to_buffer(
2526        &self,
2527        source: crate::TexelCopyTextureInfo<'_>,
2528        destination: crate::TexelCopyBufferInfo<'_>,
2529        copy_size: crate::Extent3d,
2530    ) {
2531        if let Err(cause) = self.context.0.command_encoder_copy_texture_to_buffer(
2532            self.id,
2533            &map_texture_copy_view(source),
2534            &map_buffer_copy_view(destination),
2535            &copy_size,
2536        ) {
2537            self.context.handle_error_nolabel(
2538                &self.error_sink,
2539                cause,
2540                "CommandEncoder::copy_texture_to_buffer",
2541            );
2542        }
2543    }
2544
2545    fn copy_texture_to_texture(
2546        &self,
2547        source: crate::TexelCopyTextureInfo<'_>,
2548        destination: crate::TexelCopyTextureInfo<'_>,
2549        copy_size: crate::Extent3d,
2550    ) {
2551        if let Err(cause) = self.context.0.command_encoder_copy_texture_to_texture(
2552            self.id,
2553            &map_texture_copy_view(source),
2554            &map_texture_copy_view(destination),
2555            &copy_size,
2556        ) {
2557            self.context.handle_error_nolabel(
2558                &self.error_sink,
2559                cause,
2560                "CommandEncoder::copy_texture_to_texture",
2561            );
2562        }
2563    }
2564
2565    fn begin_compute_pass(
2566        &self,
2567        desc: &crate::ComputePassDescriptor<'_>,
2568    ) -> dispatch::DispatchComputePass {
2569        let timestamp_writes =
2570            desc.timestamp_writes
2571                .as_ref()
2572                .map(|tw| wgc::command::PassTimestampWrites {
2573                    query_set: tw.query_set.inner.as_core().id,
2574                    beginning_of_pass_write_index: tw.beginning_of_pass_write_index,
2575                    end_of_pass_write_index: tw.end_of_pass_write_index,
2576                });
2577
2578        let (pass, err) = self.context.0.command_encoder_begin_compute_pass(
2579            self.id,
2580            &wgc::command::ComputePassDescriptor {
2581                label: desc.label.map(Borrowed),
2582                timestamp_writes,
2583            },
2584        );
2585
2586        if let Some(cause) = err {
2587            self.context.handle_error(
2588                &self.error_sink,
2589                cause,
2590                desc.label,
2591                "CommandEncoder::begin_compute_pass",
2592            );
2593        }
2594
2595        CoreComputePass {
2596            context: self.context.clone(),
2597            pass,
2598            error_sink: self.error_sink.clone(),
2599            id: crate::cmp::Identifier::create(),
2600        }
2601        .into()
2602    }
2603
2604    fn begin_render_pass(
2605        &self,
2606        desc: &crate::RenderPassDescriptor<'_>,
2607    ) -> dispatch::DispatchRenderPass {
2608        let colors = desc
2609            .color_attachments
2610            .iter()
2611            .map(|ca| {
2612                ca.as_ref()
2613                    .map(|at| wgc::command::RenderPassColorAttachment {
2614                        view: at.view.inner.as_core().id,
2615                        depth_slice: at.depth_slice,
2616                        resolve_target: at.resolve_target.map(|view| view.inner.as_core().id),
2617                        load_op: at.ops.load,
2618                        store_op: at.ops.store,
2619                    })
2620            })
2621            .collect::<Vec<_>>();
2622
2623        let depth_stencil = desc.depth_stencil_attachment.as_ref().map(|dsa| {
2624            wgc::command::RenderPassDepthStencilAttachment {
2625                view: dsa.view.inner.as_core().id,
2626                depth: map_pass_channel(dsa.depth_ops.as_ref()),
2627                stencil: map_pass_channel(dsa.stencil_ops.as_ref()),
2628            }
2629        });
2630
2631        let timestamp_writes =
2632            desc.timestamp_writes
2633                .as_ref()
2634                .map(|tw| wgc::command::PassTimestampWrites {
2635                    query_set: tw.query_set.inner.as_core().id,
2636                    beginning_of_pass_write_index: tw.beginning_of_pass_write_index,
2637                    end_of_pass_write_index: tw.end_of_pass_write_index,
2638                });
2639
2640        let (pass, err) = self.context.0.command_encoder_begin_render_pass(
2641            self.id,
2642            &wgc::command::RenderPassDescriptor {
2643                label: desc.label.map(Borrowed),
2644                timestamp_writes,
2645                color_attachments: Borrowed(&colors),
2646                depth_stencil_attachment: depth_stencil,
2647                occlusion_query_set: desc.occlusion_query_set.map(|qs| qs.inner.as_core().id),
2648                multiview_mask: desc.multiview_mask,
2649            },
2650        );
2651
2652        if let Some(cause) = err {
2653            self.context.handle_error(
2654                &self.error_sink,
2655                cause,
2656                desc.label,
2657                "CommandEncoder::begin_render_pass",
2658            );
2659        }
2660
2661        CoreRenderPass {
2662            context: self.context.clone(),
2663            pass,
2664            error_sink: self.error_sink.clone(),
2665            id: crate::cmp::Identifier::create(),
2666        }
2667        .into()
2668    }
2669
2670    fn finish(&mut self) -> dispatch::DispatchCommandBuffer {
2671        let descriptor = wgt::CommandBufferDescriptor::default();
2672        let (id, opt_label_and_error) =
2673            self.context
2674                .0
2675                .command_encoder_finish(self.id, &descriptor, None);
2676        if let Some((label, cause)) = opt_label_and_error {
2677            self.context
2678                .handle_error(&self.error_sink, cause, Some(&label), "a CommandEncoder");
2679        }
2680        CoreCommandBuffer {
2681            context: self.context.clone(),
2682            id,
2683        }
2684        .into()
2685    }
2686
2687    fn clear_texture(
2688        &self,
2689        texture: &dispatch::DispatchTexture,
2690        subresource_range: &crate::ImageSubresourceRange,
2691    ) {
2692        let texture = texture.as_core();
2693
2694        if let Err(cause) =
2695            self.context
2696                .0
2697                .command_encoder_clear_texture(self.id, texture.id, subresource_range)
2698        {
2699            self.context.handle_error_nolabel(
2700                &self.error_sink,
2701                cause,
2702                "CommandEncoder::clear_texture",
2703            );
2704        }
2705    }
2706
2707    fn clear_buffer(
2708        &self,
2709        buffer: &dispatch::DispatchBuffer,
2710        offset: crate::BufferAddress,
2711        size: Option<crate::BufferAddress>,
2712    ) {
2713        let buffer = buffer.as_core();
2714
2715        if let Err(cause) = self
2716            .context
2717            .0
2718            .command_encoder_clear_buffer(self.id, buffer.id, offset, size)
2719        {
2720            self.context.handle_error_nolabel(
2721                &self.error_sink,
2722                cause,
2723                "CommandEncoder::fill_buffer",
2724            );
2725        }
2726    }
2727
2728    fn insert_debug_marker(&self, label: &str) {
2729        if let Err(cause) = self
2730            .context
2731            .0
2732            .command_encoder_insert_debug_marker(self.id, label)
2733        {
2734            self.context.handle_error_nolabel(
2735                &self.error_sink,
2736                cause,
2737                "CommandEncoder::insert_debug_marker",
2738            );
2739        }
2740    }
2741
2742    fn push_debug_group(&self, label: &str) {
2743        if let Err(cause) = self
2744            .context
2745            .0
2746            .command_encoder_push_debug_group(self.id, label)
2747        {
2748            self.context.handle_error_nolabel(
2749                &self.error_sink,
2750                cause,
2751                "CommandEncoder::push_debug_group",
2752            );
2753        }
2754    }
2755
2756    fn pop_debug_group(&self) {
2757        if let Err(cause) = self.context.0.command_encoder_pop_debug_group(self.id) {
2758            self.context.handle_error_nolabel(
2759                &self.error_sink,
2760                cause,
2761                "CommandEncoder::pop_debug_group",
2762            );
2763        }
2764    }
2765
2766    fn write_timestamp(&self, query_set: &dispatch::DispatchQuerySet, query_index: u32) {
2767        let query_set = query_set.as_core();
2768
2769        if let Err(cause) =
2770            self.context
2771                .0
2772                .command_encoder_write_timestamp(self.id, query_set.id, query_index)
2773        {
2774            self.context.handle_error_nolabel(
2775                &self.error_sink,
2776                cause,
2777                "CommandEncoder::write_timestamp",
2778            );
2779        }
2780    }
2781
2782    fn resolve_query_set(
2783        &self,
2784        query_set: &dispatch::DispatchQuerySet,
2785        first_query: u32,
2786        query_count: u32,
2787        destination: &dispatch::DispatchBuffer,
2788        destination_offset: crate::BufferAddress,
2789    ) {
2790        let query_set = query_set.as_core();
2791        let destination = destination.as_core();
2792
2793        if let Err(cause) = self.context.0.command_encoder_resolve_query_set(
2794            self.id,
2795            query_set.id,
2796            first_query,
2797            query_count,
2798            destination.id,
2799            destination_offset,
2800        ) {
2801            self.context.handle_error_nolabel(
2802                &self.error_sink,
2803                cause,
2804                "CommandEncoder::resolve_query_set",
2805            );
2806        }
2807    }
2808
2809    fn mark_acceleration_structures_built<'a>(
2810        &self,
2811        blas: &mut dyn Iterator<Item = &'a Blas>,
2812        tlas: &mut dyn Iterator<Item = &'a Tlas>,
2813    ) {
2814        let blas = blas
2815            .map(|b| b.inner.as_core().id)
2816            .collect::<SmallVec<[_; 4]>>();
2817        let tlas = tlas
2818            .map(|t| t.inner.as_core().id)
2819            .collect::<SmallVec<[_; 4]>>();
2820        if let Err(cause) = self
2821            .context
2822            .0
2823            .command_encoder_mark_acceleration_structures_built(self.id, &blas, &tlas)
2824        {
2825            self.context.handle_error_nolabel(
2826                &self.error_sink,
2827                cause,
2828                "CommandEncoder::build_acceleration_structures_unsafe_tlas",
2829            );
2830        }
2831    }
2832
2833    fn build_acceleration_structures<'a>(
2834        &self,
2835        blas: &mut dyn Iterator<Item = &'a crate::BlasBuildEntry<'a>>,
2836        tlas: &mut dyn Iterator<Item = &'a crate::Tlas>,
2837    ) {
2838        let blas = blas.map(|e: &crate::BlasBuildEntry<'_>| {
2839            let geometries = match e.geometry {
2840                crate::BlasGeometries::TriangleGeometries(ref triangle_geometries) => {
2841                    let iter = triangle_geometries.iter().map(|tg| {
2842                        wgc::ray_tracing::BlasTriangleGeometry {
2843                            vertex_buffer: tg.vertex_buffer.inner.as_core().id,
2844                            index_buffer: tg.index_buffer.map(|buf| buf.inner.as_core().id),
2845                            transform_buffer: tg.transform_buffer.map(|buf| buf.inner.as_core().id),
2846                            size: tg.size,
2847                            transform_buffer_offset: tg.transform_buffer_offset,
2848                            first_vertex: tg.first_vertex,
2849                            vertex_stride: tg.vertex_stride,
2850                            first_index: tg.first_index,
2851                        }
2852                    });
2853                    wgc::ray_tracing::BlasGeometries::TriangleGeometries(Box::new(iter))
2854                }
2855                crate::BlasGeometries::AabbGeometries(ref aabb_geometries) => {
2856                    let iter =
2857                        aabb_geometries
2858                            .iter()
2859                            .map(|ag| wgc::ray_tracing::BlasAabbGeometry {
2860                                aabb_buffer: ag.aabb_buffer.inner.as_core().id,
2861                                stride: ag.stride,
2862                                size: ag.size,
2863                                primitive_offset: ag.primitive_offset,
2864                            });
2865                    wgc::ray_tracing::BlasGeometries::AabbGeometries(Box::new(iter))
2866                }
2867            };
2868            wgc::ray_tracing::BlasBuildEntry {
2869                blas_id: e.blas.inner.as_core().id,
2870                geometries,
2871            }
2872        });
2873
2874        let tlas = tlas.into_iter().map(|e| {
2875            let instances = e
2876                .instances
2877                .iter()
2878                .map(|instance: &Option<crate::TlasInstance>| {
2879                    instance
2880                        .as_ref()
2881                        .map(|instance| wgc::ray_tracing::TlasInstance {
2882                            blas_id: instance.blas.as_core().id,
2883                            transform: &instance.transform,
2884                            custom_data: instance.custom_data,
2885                            mask: instance.mask,
2886                        })
2887                });
2888            wgc::ray_tracing::TlasPackage {
2889                tlas_id: e.inner.as_core().id,
2890                instances: Box::new(instances),
2891                lowest_unmodified: e.lowest_unmodified,
2892            }
2893        });
2894
2895        if let Err(cause) = self
2896            .context
2897            .0
2898            .command_encoder_build_acceleration_structures(self.id, blas, tlas)
2899        {
2900            self.context.handle_error_nolabel(
2901                &self.error_sink,
2902                cause,
2903                "CommandEncoder::build_acceleration_structures_unsafe_tlas",
2904            );
2905        }
2906    }
2907
2908    fn transition_resources<'a>(
2909        &mut self,
2910        buffer_transitions: &mut dyn Iterator<
2911            Item = wgt::BufferTransition<&'a dispatch::DispatchBuffer>,
2912        >,
2913        texture_transitions: &mut dyn Iterator<
2914            Item = wgt::TextureTransition<&'a dispatch::DispatchTexture>,
2915        >,
2916    ) {
2917        let result = self.context.0.command_encoder_transition_resources(
2918            self.id,
2919            buffer_transitions.map(|t| wgt::BufferTransition {
2920                buffer: t.buffer.as_core().id,
2921                state: t.state,
2922            }),
2923            texture_transitions.map(|t| wgt::TextureTransition {
2924                texture: t.texture.as_core().id,
2925                selector: t.selector.clone(),
2926                state: t.state,
2927            }),
2928        );
2929
2930        if let Err(cause) = result {
2931            self.context.handle_error_nolabel(
2932                &self.error_sink,
2933                cause,
2934                "CommandEncoder::transition_resources",
2935            );
2936        }
2937    }
2938}
2939
2940impl Drop for CoreCommandEncoder {
2941    fn drop(&mut self) {
2942        self.context.0.command_encoder_drop(self.id)
2943    }
2944}
2945
2946impl dispatch::CommandBufferInterface for CoreCommandBuffer {}
2947
2948impl Drop for CoreCommandBuffer {
2949    fn drop(&mut self) {
2950        self.context.0.command_buffer_drop(self.id)
2951    }
2952}
2953
2954impl dispatch::ComputePassInterface for CoreComputePass {
2955    fn set_pipeline(&mut self, pipeline: &dispatch::DispatchComputePipeline) {
2956        let pipeline = pipeline.as_core();
2957
2958        if let Err(cause) = self
2959            .context
2960            .0
2961            .compute_pass_set_pipeline(&mut self.pass, pipeline.id)
2962        {
2963            self.context.handle_error(
2964                &self.error_sink,
2965                cause,
2966                self.pass.label(),
2967                "ComputePass::set_pipeline",
2968            );
2969        }
2970    }
2971
2972    fn set_bind_group(
2973        &mut self,
2974        index: u32,
2975        bind_group: Option<&dispatch::DispatchBindGroup>,
2976        offsets: &[crate::DynamicOffset],
2977    ) {
2978        let bg = bind_group.map(|bg| bg.as_core().id);
2979
2980        if let Err(cause) =
2981            self.context
2982                .0
2983                .compute_pass_set_bind_group(&mut self.pass, index, bg, offsets)
2984        {
2985            self.context.handle_error(
2986                &self.error_sink,
2987                cause,
2988                self.pass.label(),
2989                "ComputePass::set_bind_group",
2990            );
2991        }
2992    }
2993
2994    fn set_immediates(&mut self, offset: u32, data: &[u8]) {
2995        if let Err(cause) = self
2996            .context
2997            .0
2998            .compute_pass_set_immediates(&mut self.pass, offset, data)
2999        {
3000            self.context.handle_error(
3001                &self.error_sink,
3002                cause,
3003                self.pass.label(),
3004                "ComputePass::set_immediates",
3005            );
3006        }
3007    }
3008
3009    fn insert_debug_marker(&mut self, label: &str) {
3010        if let Err(cause) =
3011            self.context
3012                .0
3013                .compute_pass_insert_debug_marker(&mut self.pass, label, 0)
3014        {
3015            self.context.handle_error(
3016                &self.error_sink,
3017                cause,
3018                self.pass.label(),
3019                "ComputePass::insert_debug_marker",
3020            );
3021        }
3022    }
3023
3024    fn push_debug_group(&mut self, group_label: &str) {
3025        if let Err(cause) =
3026            self.context
3027                .0
3028                .compute_pass_push_debug_group(&mut self.pass, group_label, 0)
3029        {
3030            self.context.handle_error(
3031                &self.error_sink,
3032                cause,
3033                self.pass.label(),
3034                "ComputePass::push_debug_group",
3035            );
3036        }
3037    }
3038
3039    fn pop_debug_group(&mut self) {
3040        if let Err(cause) = self.context.0.compute_pass_pop_debug_group(&mut self.pass) {
3041            self.context.handle_error(
3042                &self.error_sink,
3043                cause,
3044                self.pass.label(),
3045                "ComputePass::pop_debug_group",
3046            );
3047        }
3048    }
3049
3050    fn write_timestamp(&mut self, query_set: &dispatch::DispatchQuerySet, query_index: u32) {
3051        let query_set = query_set.as_core();
3052
3053        if let Err(cause) =
3054            self.context
3055                .0
3056                .compute_pass_write_timestamp(&mut self.pass, query_set.id, query_index)
3057        {
3058            self.context.handle_error(
3059                &self.error_sink,
3060                cause,
3061                self.pass.label(),
3062                "ComputePass::write_timestamp",
3063            );
3064        }
3065    }
3066
3067    fn begin_pipeline_statistics_query(
3068        &mut self,
3069        query_set: &dispatch::DispatchQuerySet,
3070        query_index: u32,
3071    ) {
3072        let query_set = query_set.as_core();
3073
3074        if let Err(cause) = self.context.0.compute_pass_begin_pipeline_statistics_query(
3075            &mut self.pass,
3076            query_set.id,
3077            query_index,
3078        ) {
3079            self.context.handle_error(
3080                &self.error_sink,
3081                cause,
3082                self.pass.label(),
3083                "ComputePass::begin_pipeline_statistics_query",
3084            );
3085        }
3086    }
3087
3088    fn end_pipeline_statistics_query(&mut self) {
3089        if let Err(cause) = self
3090            .context
3091            .0
3092            .compute_pass_end_pipeline_statistics_query(&mut self.pass)
3093        {
3094            self.context.handle_error(
3095                &self.error_sink,
3096                cause,
3097                self.pass.label(),
3098                "ComputePass::end_pipeline_statistics_query",
3099            );
3100        }
3101    }
3102
3103    fn dispatch_workgroups(&mut self, x: u32, y: u32, z: u32) {
3104        if let Err(cause) = self
3105            .context
3106            .0
3107            .compute_pass_dispatch_workgroups(&mut self.pass, x, y, z)
3108        {
3109            self.context.handle_error(
3110                &self.error_sink,
3111                cause,
3112                self.pass.label(),
3113                "ComputePass::dispatch_workgroups",
3114            );
3115        }
3116    }
3117
3118    fn dispatch_workgroups_indirect(
3119        &mut self,
3120        indirect_buffer: &dispatch::DispatchBuffer,
3121        indirect_offset: crate::BufferAddress,
3122    ) {
3123        let indirect_buffer = indirect_buffer.as_core();
3124
3125        if let Err(cause) = self.context.0.compute_pass_dispatch_workgroups_indirect(
3126            &mut self.pass,
3127            indirect_buffer.id,
3128            indirect_offset,
3129        ) {
3130            self.context.handle_error(
3131                &self.error_sink,
3132                cause,
3133                self.pass.label(),
3134                "ComputePass::dispatch_workgroups_indirect",
3135            );
3136        }
3137    }
3138
3139    fn transition_resources<'a>(
3140        &mut self,
3141        buffer_transitions: &mut dyn Iterator<
3142            Item = wgt::BufferTransition<&'a dispatch::DispatchBuffer>,
3143        >,
3144        texture_transitions: &mut dyn Iterator<
3145            Item = wgt::TextureTransition<&'a dispatch::DispatchTextureView>,
3146        >,
3147    ) {
3148        let result = self.context.0.compute_pass_transition_resources(
3149            &mut self.pass,
3150            buffer_transitions.map(|t| wgt::BufferTransition {
3151                buffer: t.buffer.as_core().id,
3152                state: t.state,
3153            }),
3154            texture_transitions.map(|t| wgt::TextureTransition {
3155                texture: t.texture.as_core().id,
3156                selector: t.selector.clone(),
3157                state: t.state,
3158            }),
3159        );
3160
3161        if let Err(cause) = result {
3162            self.context.handle_error(
3163                &self.error_sink,
3164                cause,
3165                self.pass.label(),
3166                "ComputePass::transition_resources",
3167            );
3168        }
3169    }
3170}
3171
3172impl Drop for CoreComputePass {
3173    fn drop(&mut self) {
3174        if let Err(cause) = self.context.0.compute_pass_end(&mut self.pass) {
3175            self.context.handle_error(
3176                &self.error_sink,
3177                cause,
3178                self.pass.label(),
3179                "ComputePass::end",
3180            );
3181        }
3182    }
3183}
3184
3185impl dispatch::RenderPassInterface for CoreRenderPass {
3186    fn set_pipeline(&mut self, pipeline: &dispatch::DispatchRenderPipeline) {
3187        let pipeline = pipeline.as_core();
3188
3189        if let Err(cause) = self
3190            .context
3191            .0
3192            .render_pass_set_pipeline(&mut self.pass, pipeline.id)
3193        {
3194            self.context.handle_error(
3195                &self.error_sink,
3196                cause,
3197                self.pass.label(),
3198                "RenderPass::set_pipeline",
3199            );
3200        }
3201    }
3202
3203    fn set_bind_group(
3204        &mut self,
3205        index: u32,
3206        bind_group: Option<&dispatch::DispatchBindGroup>,
3207        offsets: &[crate::DynamicOffset],
3208    ) {
3209        let bg = bind_group.map(|bg| bg.as_core().id);
3210
3211        if let Err(cause) =
3212            self.context
3213                .0
3214                .render_pass_set_bind_group(&mut self.pass, index, bg, offsets)
3215        {
3216            self.context.handle_error(
3217                &self.error_sink,
3218                cause,
3219                self.pass.label(),
3220                "RenderPass::set_bind_group",
3221            );
3222        }
3223    }
3224
3225    fn set_index_buffer(
3226        &mut self,
3227        buffer: &dispatch::DispatchBuffer,
3228        index_format: crate::IndexFormat,
3229        offset: crate::BufferAddress,
3230        size: Option<crate::BufferSize>,
3231    ) {
3232        let buffer = buffer.as_core();
3233
3234        if let Err(cause) = self.context.0.render_pass_set_index_buffer(
3235            &mut self.pass,
3236            buffer.id,
3237            index_format,
3238            offset,
3239            size,
3240        ) {
3241            self.context.handle_error(
3242                &self.error_sink,
3243                cause,
3244                self.pass.label(),
3245                "RenderPass::set_index_buffer",
3246            );
3247        }
3248    }
3249
3250    fn set_vertex_buffer(
3251        &mut self,
3252        slot: u32,
3253        buffer: Option<&dispatch::DispatchBuffer>,
3254        offset: crate::BufferAddress,
3255        size: Option<crate::BufferSize>,
3256    ) {
3257        let buffer = buffer.map(|buffer| buffer.as_core().id);
3258
3259        if let Err(cause) =
3260            self.context
3261                .0
3262                .render_pass_set_vertex_buffer(&mut self.pass, slot, buffer, offset, size)
3263        {
3264            self.context.handle_error(
3265                &self.error_sink,
3266                cause,
3267                self.pass.label(),
3268                "RenderPass::set_vertex_buffer",
3269            );
3270        }
3271    }
3272
3273    fn set_immediates(&mut self, offset: u32, data: &[u8]) {
3274        if let Err(cause) = self
3275            .context
3276            .0
3277            .render_pass_set_immediates(&mut self.pass, offset, data)
3278        {
3279            self.context.handle_error(
3280                &self.error_sink,
3281                cause,
3282                self.pass.label(),
3283                "RenderPass::set_immediates",
3284            );
3285        }
3286    }
3287
3288    fn set_blend_constant(&mut self, color: crate::Color) {
3289        if let Err(cause) = self
3290            .context
3291            .0
3292            .render_pass_set_blend_constant(&mut self.pass, color)
3293        {
3294            self.context.handle_error(
3295                &self.error_sink,
3296                cause,
3297                self.pass.label(),
3298                "RenderPass::set_blend_constant",
3299            );
3300        }
3301    }
3302
3303    fn set_scissor_rect(&mut self, x: u32, y: u32, width: u32, height: u32) {
3304        if let Err(cause) =
3305            self.context
3306                .0
3307                .render_pass_set_scissor_rect(&mut self.pass, x, y, width, height)
3308        {
3309            self.context.handle_error(
3310                &self.error_sink,
3311                cause,
3312                self.pass.label(),
3313                "RenderPass::set_scissor_rect",
3314            );
3315        }
3316    }
3317
3318    fn set_viewport(
3319        &mut self,
3320        x: f32,
3321        y: f32,
3322        width: f32,
3323        height: f32,
3324        min_depth: f32,
3325        max_depth: f32,
3326    ) {
3327        if let Err(cause) = self.context.0.render_pass_set_viewport(
3328            &mut self.pass,
3329            x,
3330            y,
3331            width,
3332            height,
3333            min_depth,
3334            max_depth,
3335        ) {
3336            self.context.handle_error(
3337                &self.error_sink,
3338                cause,
3339                self.pass.label(),
3340                "RenderPass::set_viewport",
3341            );
3342        }
3343    }
3344
3345    fn set_stencil_reference(&mut self, reference: u32) {
3346        if let Err(cause) = self
3347            .context
3348            .0
3349            .render_pass_set_stencil_reference(&mut self.pass, reference)
3350        {
3351            self.context.handle_error(
3352                &self.error_sink,
3353                cause,
3354                self.pass.label(),
3355                "RenderPass::set_stencil_reference",
3356            );
3357        }
3358    }
3359
3360    fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>) {
3361        if let Err(cause) = self.context.0.render_pass_draw(
3362            &mut self.pass,
3363            vertices.end - vertices.start,
3364            instances.end - instances.start,
3365            vertices.start,
3366            instances.start,
3367        ) {
3368            self.context.handle_error(
3369                &self.error_sink,
3370                cause,
3371                self.pass.label(),
3372                "RenderPass::draw",
3373            );
3374        }
3375    }
3376
3377    fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>) {
3378        if let Err(cause) = self.context.0.render_pass_draw_indexed(
3379            &mut self.pass,
3380            indices.end - indices.start,
3381            instances.end - instances.start,
3382            indices.start,
3383            base_vertex,
3384            instances.start,
3385        ) {
3386            self.context.handle_error(
3387                &self.error_sink,
3388                cause,
3389                self.pass.label(),
3390                "RenderPass::draw_indexed",
3391            );
3392        }
3393    }
3394
3395    fn draw_mesh_tasks(&mut self, group_count_x: u32, group_count_y: u32, group_count_z: u32) {
3396        if let Err(cause) = self.context.0.render_pass_draw_mesh_tasks(
3397            &mut self.pass,
3398            group_count_x,
3399            group_count_y,
3400            group_count_z,
3401        ) {
3402            self.context.handle_error(
3403                &self.error_sink,
3404                cause,
3405                self.pass.label(),
3406                "RenderPass::draw_mesh_tasks",
3407            );
3408        }
3409    }
3410
3411    fn draw_indirect(
3412        &mut self,
3413        indirect_buffer: &dispatch::DispatchBuffer,
3414        indirect_offset: crate::BufferAddress,
3415    ) {
3416        let indirect_buffer = indirect_buffer.as_core();
3417
3418        if let Err(cause) = self.context.0.render_pass_draw_indirect(
3419            &mut self.pass,
3420            indirect_buffer.id,
3421            indirect_offset,
3422        ) {
3423            self.context.handle_error(
3424                &self.error_sink,
3425                cause,
3426                self.pass.label(),
3427                "RenderPass::draw_indirect",
3428            );
3429        }
3430    }
3431
3432    fn draw_indexed_indirect(
3433        &mut self,
3434        indirect_buffer: &dispatch::DispatchBuffer,
3435        indirect_offset: crate::BufferAddress,
3436    ) {
3437        let indirect_buffer = indirect_buffer.as_core();
3438
3439        if let Err(cause) = self.context.0.render_pass_draw_indexed_indirect(
3440            &mut self.pass,
3441            indirect_buffer.id,
3442            indirect_offset,
3443        ) {
3444            self.context.handle_error(
3445                &self.error_sink,
3446                cause,
3447                self.pass.label(),
3448                "RenderPass::draw_indexed_indirect",
3449            );
3450        }
3451    }
3452
3453    fn draw_mesh_tasks_indirect(
3454        &mut self,
3455        indirect_buffer: &dispatch::DispatchBuffer,
3456        indirect_offset: crate::BufferAddress,
3457    ) {
3458        let indirect_buffer = indirect_buffer.as_core();
3459
3460        if let Err(cause) = self.context.0.render_pass_draw_mesh_tasks_indirect(
3461            &mut self.pass,
3462            indirect_buffer.id,
3463            indirect_offset,
3464        ) {
3465            self.context.handle_error(
3466                &self.error_sink,
3467                cause,
3468                self.pass.label(),
3469                "RenderPass::draw_mesh_tasks_indirect",
3470            );
3471        }
3472    }
3473
3474    fn multi_draw_indirect(
3475        &mut self,
3476        indirect_buffer: &dispatch::DispatchBuffer,
3477        indirect_offset: crate::BufferAddress,
3478        count: u32,
3479    ) {
3480        let indirect_buffer = indirect_buffer.as_core();
3481
3482        if let Err(cause) = self.context.0.render_pass_multi_draw_indirect(
3483            &mut self.pass,
3484            indirect_buffer.id,
3485            indirect_offset,
3486            count,
3487        ) {
3488            self.context.handle_error(
3489                &self.error_sink,
3490                cause,
3491                self.pass.label(),
3492                "RenderPass::multi_draw_indirect",
3493            );
3494        }
3495    }
3496
3497    fn multi_draw_indexed_indirect(
3498        &mut self,
3499        indirect_buffer: &dispatch::DispatchBuffer,
3500        indirect_offset: crate::BufferAddress,
3501        count: u32,
3502    ) {
3503        let indirect_buffer = indirect_buffer.as_core();
3504
3505        if let Err(cause) = self.context.0.render_pass_multi_draw_indexed_indirect(
3506            &mut self.pass,
3507            indirect_buffer.id,
3508            indirect_offset,
3509            count,
3510        ) {
3511            self.context.handle_error(
3512                &self.error_sink,
3513                cause,
3514                self.pass.label(),
3515                "RenderPass::multi_draw_indexed_indirect",
3516            );
3517        }
3518    }
3519
3520    fn multi_draw_mesh_tasks_indirect(
3521        &mut self,
3522        indirect_buffer: &dispatch::DispatchBuffer,
3523        indirect_offset: crate::BufferAddress,
3524        count: u32,
3525    ) {
3526        let indirect_buffer = indirect_buffer.as_core();
3527
3528        if let Err(cause) = self.context.0.render_pass_multi_draw_mesh_tasks_indirect(
3529            &mut self.pass,
3530            indirect_buffer.id,
3531            indirect_offset,
3532            count,
3533        ) {
3534            self.context.handle_error(
3535                &self.error_sink,
3536                cause,
3537                self.pass.label(),
3538                "RenderPass::multi_draw_mesh_tasks_indirect",
3539            );
3540        }
3541    }
3542
3543    fn multi_draw_indirect_count(
3544        &mut self,
3545        indirect_buffer: &dispatch::DispatchBuffer,
3546        indirect_offset: crate::BufferAddress,
3547        count_buffer: &dispatch::DispatchBuffer,
3548        count_buffer_offset: crate::BufferAddress,
3549        max_count: u32,
3550    ) {
3551        let indirect_buffer = indirect_buffer.as_core();
3552        let count_buffer = count_buffer.as_core();
3553
3554        if let Err(cause) = self.context.0.render_pass_multi_draw_indirect_count(
3555            &mut self.pass,
3556            indirect_buffer.id,
3557            indirect_offset,
3558            count_buffer.id,
3559            count_buffer_offset,
3560            max_count,
3561        ) {
3562            self.context.handle_error(
3563                &self.error_sink,
3564                cause,
3565                self.pass.label(),
3566                "RenderPass::multi_draw_indirect_count",
3567            );
3568        }
3569    }
3570
3571    fn multi_draw_indexed_indirect_count(
3572        &mut self,
3573        indirect_buffer: &dispatch::DispatchBuffer,
3574        indirect_offset: crate::BufferAddress,
3575        count_buffer: &dispatch::DispatchBuffer,
3576        count_buffer_offset: crate::BufferAddress,
3577        max_count: u32,
3578    ) {
3579        let indirect_buffer = indirect_buffer.as_core();
3580        let count_buffer = count_buffer.as_core();
3581
3582        if let Err(cause) = self
3583            .context
3584            .0
3585            .render_pass_multi_draw_indexed_indirect_count(
3586                &mut self.pass,
3587                indirect_buffer.id,
3588                indirect_offset,
3589                count_buffer.id,
3590                count_buffer_offset,
3591                max_count,
3592            )
3593        {
3594            self.context.handle_error(
3595                &self.error_sink,
3596                cause,
3597                self.pass.label(),
3598                "RenderPass::multi_draw_indexed_indirect_count",
3599            );
3600        }
3601    }
3602
3603    fn multi_draw_mesh_tasks_indirect_count(
3604        &mut self,
3605        indirect_buffer: &dispatch::DispatchBuffer,
3606        indirect_offset: crate::BufferAddress,
3607        count_buffer: &dispatch::DispatchBuffer,
3608        count_buffer_offset: crate::BufferAddress,
3609        max_count: u32,
3610    ) {
3611        let indirect_buffer = indirect_buffer.as_core();
3612        let count_buffer = count_buffer.as_core();
3613
3614        if let Err(cause) = self
3615            .context
3616            .0
3617            .render_pass_multi_draw_mesh_tasks_indirect_count(
3618                &mut self.pass,
3619                indirect_buffer.id,
3620                indirect_offset,
3621                count_buffer.id,
3622                count_buffer_offset,
3623                max_count,
3624            )
3625        {
3626            self.context.handle_error(
3627                &self.error_sink,
3628                cause,
3629                self.pass.label(),
3630                "RenderPass::multi_draw_mesh_tasks_indirect_count",
3631            );
3632        }
3633    }
3634
3635    fn insert_debug_marker(&mut self, label: &str) {
3636        if let Err(cause) = self
3637            .context
3638            .0
3639            .render_pass_insert_debug_marker(&mut self.pass, label, 0)
3640        {
3641            self.context.handle_error(
3642                &self.error_sink,
3643                cause,
3644                self.pass.label(),
3645                "RenderPass::insert_debug_marker",
3646            );
3647        }
3648    }
3649
3650    fn push_debug_group(&mut self, group_label: &str) {
3651        if let Err(cause) =
3652            self.context
3653                .0
3654                .render_pass_push_debug_group(&mut self.pass, group_label, 0)
3655        {
3656            self.context.handle_error(
3657                &self.error_sink,
3658                cause,
3659                self.pass.label(),
3660                "RenderPass::push_debug_group",
3661            );
3662        }
3663    }
3664
3665    fn pop_debug_group(&mut self) {
3666        if let Err(cause) = self.context.0.render_pass_pop_debug_group(&mut self.pass) {
3667            self.context.handle_error(
3668                &self.error_sink,
3669                cause,
3670                self.pass.label(),
3671                "RenderPass::pop_debug_group",
3672            );
3673        }
3674    }
3675
3676    fn write_timestamp(&mut self, query_set: &dispatch::DispatchQuerySet, query_index: u32) {
3677        let query_set = query_set.as_core();
3678
3679        if let Err(cause) =
3680            self.context
3681                .0
3682                .render_pass_write_timestamp(&mut self.pass, query_set.id, query_index)
3683        {
3684            self.context.handle_error(
3685                &self.error_sink,
3686                cause,
3687                self.pass.label(),
3688                "RenderPass::write_timestamp",
3689            );
3690        }
3691    }
3692
3693    fn begin_occlusion_query(&mut self, query_index: u32) {
3694        if let Err(cause) = self
3695            .context
3696            .0
3697            .render_pass_begin_occlusion_query(&mut self.pass, query_index)
3698        {
3699            self.context.handle_error(
3700                &self.error_sink,
3701                cause,
3702                self.pass.label(),
3703                "RenderPass::begin_occlusion_query",
3704            );
3705        }
3706    }
3707
3708    fn end_occlusion_query(&mut self) {
3709        if let Err(cause) = self
3710            .context
3711            .0
3712            .render_pass_end_occlusion_query(&mut self.pass)
3713        {
3714            self.context.handle_error(
3715                &self.error_sink,
3716                cause,
3717                self.pass.label(),
3718                "RenderPass::end_occlusion_query",
3719            );
3720        }
3721    }
3722
3723    fn begin_pipeline_statistics_query(
3724        &mut self,
3725        query_set: &dispatch::DispatchQuerySet,
3726        query_index: u32,
3727    ) {
3728        let query_set = query_set.as_core();
3729
3730        if let Err(cause) = self.context.0.render_pass_begin_pipeline_statistics_query(
3731            &mut self.pass,
3732            query_set.id,
3733            query_index,
3734        ) {
3735            self.context.handle_error(
3736                &self.error_sink,
3737                cause,
3738                self.pass.label(),
3739                "RenderPass::begin_pipeline_statistics_query",
3740            );
3741        }
3742    }
3743
3744    fn end_pipeline_statistics_query(&mut self) {
3745        if let Err(cause) = self
3746            .context
3747            .0
3748            .render_pass_end_pipeline_statistics_query(&mut self.pass)
3749        {
3750            self.context.handle_error(
3751                &self.error_sink,
3752                cause,
3753                self.pass.label(),
3754                "RenderPass::end_pipeline_statistics_query",
3755            );
3756        }
3757    }
3758
3759    fn execute_bundles(
3760        &mut self,
3761        render_bundles: &mut dyn Iterator<Item = &dispatch::DispatchRenderBundle>,
3762    ) {
3763        let temp_render_bundles = render_bundles
3764            .map(|rb| rb.as_core().id)
3765            .collect::<SmallVec<[_; 4]>>();
3766        if let Err(cause) = self
3767            .context
3768            .0
3769            .render_pass_execute_bundles(&mut self.pass, &temp_render_bundles)
3770        {
3771            self.context.handle_error(
3772                &self.error_sink,
3773                cause,
3774                self.pass.label(),
3775                "RenderPass::execute_bundles",
3776            );
3777        }
3778    }
3779}
3780
3781impl Drop for CoreRenderPass {
3782    fn drop(&mut self) {
3783        if let Err(cause) = self.context.0.render_pass_end(&mut self.pass) {
3784            self.context.handle_error(
3785                &self.error_sink,
3786                cause,
3787                self.pass.label(),
3788                "RenderPass::end",
3789            );
3790        }
3791    }
3792}
3793
3794impl dispatch::RenderBundleEncoderInterface for CoreRenderBundleEncoder {
3795    fn set_pipeline(&mut self, pipeline: &dispatch::DispatchRenderPipeline) {
3796        let pipeline = pipeline.as_core();
3797
3798        self.context
3799            .0
3800            .render_bundle_encoder_set_pipeline(&mut self.encoder, pipeline.id)
3801            .expect("RenderBundleEncoder should not have ended")
3802    }
3803
3804    fn set_bind_group(
3805        &mut self,
3806        index: u32,
3807        bind_group: Option<&dispatch::DispatchBindGroup>,
3808        offsets: &[crate::DynamicOffset],
3809    ) {
3810        let bg = bind_group.map(|bg| bg.as_core().id);
3811
3812        self.context
3813            .0
3814            .render_bundle_encoder_set_bind_group(&mut self.encoder, index, bg, offsets)
3815            .expect("RenderBundleEncoder should not have ended");
3816    }
3817
3818    fn set_index_buffer(
3819        &mut self,
3820        buffer: &dispatch::DispatchBuffer,
3821        index_format: crate::IndexFormat,
3822        offset: crate::BufferAddress,
3823        size: Option<crate::BufferSize>,
3824    ) {
3825        let buffer = buffer.as_core();
3826
3827        self.context
3828            .0
3829            .render_bundle_encoder_set_index_buffer(
3830                &mut self.encoder,
3831                buffer.id,
3832                index_format,
3833                offset,
3834                size,
3835            )
3836            .expect("RenderBundleEncoder should not have ended");
3837    }
3838
3839    fn set_vertex_buffer(
3840        &mut self,
3841        slot: u32,
3842        buffer: Option<&dispatch::DispatchBuffer>,
3843        offset: crate::BufferAddress,
3844        size: Option<crate::BufferSize>,
3845    ) {
3846        let buffer = buffer.map(|buffer| buffer.as_core().id);
3847
3848        self.context
3849            .0
3850            .render_bundle_encoder_set_vertex_buffer(&mut self.encoder, slot, buffer, offset, size)
3851            .expect("RenderBundleEncoder should not have ended");
3852    }
3853
3854    fn set_immediates(&mut self, offset: u32, data: &[u8]) {
3855        self.context
3856            .0
3857            .render_bundle_encoder_set_immediates(&mut self.encoder, offset, data)
3858            .expect("RenderBundleEncoder should not have ended");
3859    }
3860
3861    fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>) {
3862        self.context
3863            .0
3864            .render_bundle_encoder_draw(
3865                &mut self.encoder,
3866                vertices.end - vertices.start,
3867                instances.end - instances.start,
3868                vertices.start,
3869                instances.start,
3870            )
3871            .expect("RenderBundleEncoder should not have ended");
3872    }
3873
3874    fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>) {
3875        self.context
3876            .0
3877            .render_bundle_encoder_draw_indexed(
3878                &mut self.encoder,
3879                indices.end - indices.start,
3880                instances.end - instances.start,
3881                indices.start,
3882                base_vertex,
3883                instances.start,
3884            )
3885            .expect("RenderBundleEncoder should not have ended");
3886    }
3887
3888    fn draw_indirect(
3889        &mut self,
3890        indirect_buffer: &dispatch::DispatchBuffer,
3891        indirect_offset: crate::BufferAddress,
3892    ) {
3893        let indirect_buffer = indirect_buffer.as_core();
3894
3895        self.context
3896            .0
3897            .render_bundle_encoder_draw_indirect(
3898                &mut self.encoder,
3899                indirect_buffer.id,
3900                indirect_offset,
3901            )
3902            .expect("RenderBundleEncoder should not have ended");
3903    }
3904
3905    fn draw_indexed_indirect(
3906        &mut self,
3907        indirect_buffer: &dispatch::DispatchBuffer,
3908        indirect_offset: crate::BufferAddress,
3909    ) {
3910        let indirect_buffer = indirect_buffer.as_core();
3911
3912        self.context
3913            .0
3914            .render_bundle_encoder_draw_indexed_indirect(
3915                &mut self.encoder,
3916                indirect_buffer.id,
3917                indirect_offset,
3918            )
3919            .expect("RenderBundleEncoder should not have ended");
3920    }
3921
3922    fn finish(mut self, desc: &crate::RenderBundleDescriptor<'_>) -> dispatch::DispatchRenderBundle
3923    where
3924        Self: Sized,
3925    {
3926        let (id, error) = self.context.0.render_bundle_encoder_finish(
3927            &mut self.encoder,
3928            &desc.map_label(|l| l.map(Borrowed)),
3929            None,
3930        );
3931        if let Some(err) = error {
3932            self.context
3933                .handle_error_fatal(err, "RenderBundleEncoder::finish");
3934        }
3935        CoreRenderBundle {
3936            context: self.context.clone(),
3937            id,
3938        }
3939        .into()
3940    }
3941
3942    #[cfg(custom)]
3943    fn finish_boxed(
3944        self: Box<Self>,
3945        desc: &crate::RenderBundleDescriptor<'_>,
3946    ) -> dispatch::DispatchRenderBundle {
3947        (*self).finish(desc)
3948    }
3949}
3950
3951impl dispatch::RenderBundleInterface for CoreRenderBundle {}
3952
3953impl Drop for CoreRenderBundle {
3954    fn drop(&mut self) {
3955        self.context.0.render_bundle_drop(self.id)
3956    }
3957}
3958
3959impl dispatch::SurfaceInterface for CoreSurface {
3960    fn get_capabilities(&self, adapter: &dispatch::DispatchAdapter) -> wgt::SurfaceCapabilities {
3961        let adapter = adapter.as_core();
3962
3963        self.context
3964            .0
3965            .surface_get_capabilities(self.id, adapter.id)
3966            .unwrap_or_default()
3967    }
3968
3969    fn display_hdr_info(&self, adapter: &dispatch::DispatchAdapter) -> wgt::DisplayHdrInfo {
3970        let adapter = adapter.as_core();
3971
3972        self.context.0.surface_display_hdr_info(self.id, adapter.id)
3973    }
3974
3975    fn configure(&self, device: &dispatch::DispatchDevice, config: &crate::SurfaceConfiguration) {
3976        let device = device.as_core();
3977
3978        let error = self.context.0.surface_configure(self.id, device.id, config);
3979        if let Some(e) = error {
3980            self.context
3981                .handle_error_nolabel(&device.error_sink, e, "Surface::configure");
3982        } else {
3983            *self.configured_device.lock() = Some(device.id);
3984            *self.error_sink.lock() = Some(device.error_sink.clone());
3985        }
3986    }
3987
3988    fn get_current_texture(
3989        &self,
3990    ) -> (
3991        Option<dispatch::DispatchTexture>,
3992        crate::SurfaceStatus,
3993        dispatch::DispatchSurfaceOutputDetail,
3994    ) {
3995        let error_sink = if let Some(error_sink) = self.error_sink.lock().as_ref() {
3996            error_sink.clone()
3997        } else {
3998            Arc::new(Mutex::new(ErrorSinkRaw::new()))
3999        };
4000
4001        let output_detail = CoreSurfaceOutputDetail {
4002            context: self.context.clone(),
4003            surface_id: self.id,
4004            error_sink: error_sink.clone(),
4005        }
4006        .into();
4007
4008        match self.context.0.surface_get_current_texture(self.id, None) {
4009            Ok(wgc::present::SurfaceOutput {
4010                status,
4011                texture: texture_id,
4012            }) => {
4013                let data = texture_id
4014                    .map(|id| CoreTexture {
4015                        context: self.context.clone(),
4016                        id,
4017                        error_sink,
4018                    })
4019                    .map(Into::into);
4020
4021                (data, status, output_detail)
4022            }
4023            Err(err) => {
4024                let error_sink = self.error_sink.lock();
4025                match error_sink.as_ref() {
4026                    Some(error_sink) => {
4027                        self.context.handle_error_nolabel(
4028                            error_sink,
4029                            err,
4030                            "Surface::get_current_texture_view",
4031                        );
4032                        (None, crate::SurfaceStatus::Validation, output_detail)
4033                    }
4034                    None => self
4035                        .context
4036                        .handle_error_fatal(err, "Surface::get_current_texture_view"),
4037                }
4038            }
4039        }
4040    }
4041}
4042
4043impl Drop for CoreSurface {
4044    fn drop(&mut self) {
4045        self.context.0.surface_drop(self.id)
4046    }
4047}
4048
4049impl dispatch::SurfaceOutputDetailInterface for CoreSurfaceOutputDetail {
4050    fn texture_discard(&self) {
4051        match self.context.0.surface_texture_discard(self.surface_id) {
4052            Ok(_status) => (),
4053            Err(err) => {
4054                self.context
4055                    .handle_error_nolabel(&self.error_sink, err, "Surface::discard_texture")
4056            }
4057        }
4058    }
4059
4060    fn texture_release(&self) {
4061        match self.context.0.surface_texture_release(self.surface_id) {
4062            Ok(_status) => (),
4063            Err(err) => {
4064                self.context
4065                    .handle_error_nolabel(&self.error_sink, err, "Surface::release_texture")
4066            }
4067        }
4068    }
4069}
4070impl Drop for CoreSurfaceOutputDetail {
4071    fn drop(&mut self) {
4072        // Discard gets called by the api struct
4073
4074        // no-op
4075    }
4076}
4077
4078impl dispatch::QueueWriteBufferInterface for CoreQueueWriteBuffer {
4079    #[inline]
4080    fn len(&self) -> usize {
4081        self.mapping.len()
4082    }
4083
4084    #[inline]
4085    unsafe fn write_slice(&mut self) -> WriteOnly<'_, [u8]> {
4086        unsafe { self.mapping.write_slice() }
4087    }
4088}
4089impl Drop for CoreQueueWriteBuffer {
4090    fn drop(&mut self) {
4091        // The api struct calls queue.write_staging_buffer
4092
4093        // no-op
4094    }
4095}
4096
4097impl dispatch::BufferMappedRangeInterface for CoreBufferMappedRange {
4098    #[inline]
4099    fn len(&self) -> usize {
4100        self.size
4101    }
4102
4103    #[inline]
4104    unsafe fn read_slice(&self) -> &[u8] {
4105        unsafe { slice::from_raw_parts(self.ptr.as_ptr(), self.size) }
4106    }
4107
4108    #[inline]
4109    unsafe fn write_slice(&mut self) -> WriteOnly<'_, [u8]> {
4110        unsafe { WriteOnly::new(NonNull::slice_from_raw_parts(self.ptr, self.size)) }
4111    }
4112
4113    #[cfg(webgpu)]
4114    fn as_uint8array(&self) -> &js_sys::Uint8Array {
4115        panic!("Only available on WebGPU")
4116    }
4117}