Skip to main content

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