1use alloc::borrow::ToOwned;
2use alloc::{
3 borrow::Cow::{self, Borrowed},
4 boxed::Box,
5 string::String,
6 sync::Arc,
7 vec::Vec,
8};
9use core::{
10 error::Error,
11 fmt,
12 future::ready,
13 ops::{Deref, Range},
14 pin::Pin,
15 ptr::NonNull,
16 slice,
17};
18use wgc::resource::ParentDevice as _;
19use wgt::error::WebGpuError;
20
21use arrayvec::ArrayVec;
22use smallvec::SmallVec;
23use wgc::resource::BlasPrepareCompactResult;
24use wgt::WasmNotSendSync;
25
26use crate::{
27 api,
28 dispatch::{self, BlasCompactCallback, BufferMappedRangeInterface},
29 BindingResource, Blas, BufferBinding, BufferDescriptor, Features, LoadOp, MapMode, Operations,
30 ShaderSource, SurfaceTargetUnsafe, TextureDescriptor, Tlas, WriteOnly,
31};
32use crate::{dispatch::DispatchAdapter, util::Mutex};
33
34use wgc::error::format_error;
35
36#[derive(Clone)]
37pub struct ContextWgpuCore(Arc<wgc::instance::Instance>);
38
39impl fmt::Debug for ContextWgpuCore {
40 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41 f.debug_struct("ContextWgpuCore")
42 .field("type", &"Native")
43 .finish()
44 }
45}
46
47#[track_caller]
48#[cold]
49fn handle_error_fatal(cause: impl Error + WasmNotSendSync + 'static, operation: &'static str) -> ! {
50 panic!("Error in {operation}: {f}", f = format_error(&cause));
51}
52
53impl ContextWgpuCore {
54 pub unsafe fn from_hal_instance<A: hal::Api>(hal_instance: A::Instance) -> Self {
55 Self(wgc::instance::Instance::from_hal_instance::<A>(
56 "wgpu".to_owned(),
57 hal_instance,
58 ))
59 }
60
61 pub unsafe fn instance_as_hal<A: hal::Api>(&self) -> Option<&A::Instance> {
65 unsafe { self.0.as_hal::<A>() }
66 }
67
68 pub fn from_core_instance(core_instance: Arc<wgc::instance::Instance>) -> Self {
69 Self(core_instance)
70 }
71
72 #[cfg(wgpu_core)]
73 pub fn enumerate_adapters(&self, backends: wgt::Backends) -> Vec<Arc<wgc::instance::Adapter>> {
74 self.0
75 .enumerate_adapters(backends, false )
76 }
77
78 pub unsafe fn create_adapter_from_hal<A: hal::Api>(
79 &self,
80 hal_adapter: hal::ExposedAdapter<A>,
81 ) -> Arc<wgc::instance::Adapter> {
82 unsafe { self.0.create_adapter_from_hal(hal_adapter.into()) }
83 }
84}
85
86fn map_buffer_copy_view(
87 view: crate::TexelCopyBufferInfo<'_>,
88) -> wgt::TexelCopyBufferInfo<Arc<wgc::resource::Buffer>> {
89 wgt::TexelCopyBufferInfo {
90 buffer: view.buffer.inner.as_core().wgpu_buffer.clone(),
91 layout: view.layout,
92 }
93}
94
95fn map_texture_copy_view(
96 view: crate::TexelCopyTextureInfo<'_>,
97) -> wgt::TexelCopyTextureInfo<Arc<wgc::resource::Texture>> {
98 wgt::TexelCopyTextureInfo {
99 texture: view.texture.inner.as_core().wgpu_texture.clone(),
100 mip_level: view.mip_level,
101 origin: view.origin,
102 aspect: view.aspect,
103 }
104}
105
106#[cfg_attr(not(webgl), expect(unused))]
107fn map_texture_tagged_copy_view(
108 view: crate::CopyExternalImageDestInfo<&api::Texture>,
109) -> wgt::CopyExternalImageDestInfo<Arc<wgc::resource::Texture>> {
110 wgt::CopyExternalImageDestInfo {
111 texture: view.texture.inner.as_core().wgpu_texture.clone(),
112 mip_level: view.mip_level,
113 origin: view.origin,
114 aspect: view.aspect,
115 color_space: view.color_space,
116 premultiplied_alpha: view.premultiplied_alpha,
117 }
118}
119
120fn map_load_op<V: Copy>(load: &LoadOp<V>) -> LoadOp<Option<V>> {
121 match *load {
122 LoadOp::Clear(clear_value) => LoadOp::Clear(Some(clear_value)),
123 LoadOp::DontCare(token) => LoadOp::DontCare(token),
124 LoadOp::Load => LoadOp::Load,
125 }
126}
127
128fn map_pass_channel<V: Copy>(ops: Option<&Operations<V>>) -> wgc::command::PassChannel<Option<V>> {
129 match ops {
130 Some(&Operations { load, store }) => wgc::command::PassChannel {
131 load_op: Some(map_load_op(&load)),
132 store_op: Some(store),
133 read_only: false,
134 },
135 None => wgc::command::PassChannel {
136 load_op: None,
137 store_op: None,
138 read_only: true,
139 },
140 }
141}
142
143#[derive(Clone)]
144pub struct CoreSurface {
145 pub(crate) wgpu_surface: Arc<wgc::instance::Surface>,
146 configured_device: Arc<Mutex<Option<Arc<wgc::device::Device>>>>,
149}
150
151impl fmt::Debug for CoreSurface {
152 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
153 f.debug_struct("CoreSurface")
154 .field("wgpu_surface", &Arc::as_ptr(&self.wgpu_surface))
155 .field("configured_device", &self.configured_device)
156 .finish()
157 }
158}
159
160impl CoreSurface {
161 pub unsafe fn as_hal<A: hal::Api>(&self) -> Option<impl Deref<Target = A::Surface>> {
162 unsafe { self.wgpu_surface.clone().as_hal::<A>() }
163 }
164}
165
166#[derive(Clone)]
167pub struct CoreAdapter {
168 pub(crate) wgpu_adapter: Arc<wgc::instance::Adapter>,
169}
170
171impl fmt::Debug for CoreAdapter {
172 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
173 f.debug_struct("CoreAdapter")
174 .field("wgpu_adapter", &Arc::as_ptr(&self.wgpu_adapter))
175 .finish()
176 }
177}
178
179impl CoreAdapter {
180 pub unsafe fn as_hal<A: hal::Api>(
181 &self,
182 ) -> Option<impl Deref<Target = A::Adapter> + WasmNotSendSync> {
183 unsafe { self.wgpu_adapter.clone().as_hal::<A>() }
184 }
185
186 pub unsafe fn create_device_from_hal<A: hal::Api>(
187 &self,
188 hal_device: hal::OpenDevice<A>,
189 desc: &crate::DeviceDescriptor<'_>,
190 ) -> Result<(CoreDevice, CoreQueue), crate::RequestDeviceError> {
191 let (device, queue) = unsafe {
192 self.wgpu_adapter.create_device_and_queue_from_hal(
193 hal_device.into(),
194 &desc.map_label(|l| l.map(Borrowed)),
195 )
196 }?;
197 let device = CoreDevice {
198 wgpu_device: device.clone(),
199 };
200 let queue = CoreQueue { wgpu_queue: queue };
201 Ok((device, queue))
202 }
203}
204
205#[derive(Debug, Clone)]
206pub struct CoreDevice {
207 pub(crate) wgpu_device: Arc<wgc::device::Device>,
208}
209
210impl CoreDevice {
211 pub unsafe fn as_hal<A: hal::Api>(&self) -> Option<impl Deref<Target = A::Device>> {
212 unsafe { self.wgpu_device.clone().as_hal::<A>() }
213 }
214
215 pub unsafe fn create_texture_from_hal<A: hal::Api>(
216 &self,
217 hal_texture: A::Texture,
218 desc: &TextureDescriptor<'_>,
219 initial_state: wgt::TextureUses,
220 cleared: bool,
221 ) -> CoreTexture {
222 let descriptor = desc.map_label_and_view_formats(|l| l.map(Borrowed), |v| v.to_vec());
223 let (wgpu_texture, error) = unsafe {
224 self.wgpu_device.create_texture_from_hal(
225 Box::new(hal_texture),
226 &descriptor,
227 initial_state,
228 cleared,
229 )
230 };
231 if let Some(cause) = error {
232 self.wgpu_device
233 .handle_error(cause, desc.label, "Device::create_texture_from_hal");
234 }
235 CoreTexture { wgpu_texture }
236 }
237
238 pub unsafe fn create_buffer_from_hal<A: hal::Api>(
245 &self,
246 hal_buffer: A::Buffer,
247 desc: &BufferDescriptor<'_>,
248 ) -> CoreBuffer {
249 let (wgpu_buffer, error) = unsafe {
250 self.wgpu_device
251 .create_buffer_from_hal(Box::new(hal_buffer), &desc.map_label(|l| l.map(Borrowed)))
252 };
253 if let Some(cause) = error {
254 self.wgpu_device
255 .handle_error(cause, desc.label, "Device::create_buffer_from_hal");
256 }
257 CoreBuffer { wgpu_buffer }
258 }
259
260 #[cfg(webgl)]
262 pub fn texture_belongs_to_device(&self, texture: &CoreTexture) -> bool {
263 use wgc::resource::ParentDevice as _;
264 texture.wgpu_texture.same_device(&self.wgpu_device).is_ok()
265 }
266}
267
268#[derive(Debug, Clone)]
269pub struct CoreBuffer {
270 pub(crate) wgpu_buffer: Arc<wgc::resource::Buffer>,
271}
272
273impl CoreBuffer {
274 pub unsafe fn as_hal<A: hal::Api>(&self) -> Option<impl Deref<Target = A::Buffer>> {
275 unsafe { self.wgpu_buffer.clone().as_hal::<A>() }
276 }
277}
278
279#[derive(Debug, Clone)]
280pub struct CoreShaderModule {
281 pub(crate) wgpu_shader_module: Arc<wgc::pipeline::ShaderModule>,
282}
283
284#[derive(Debug, Clone)]
285pub struct CoreBindGroupLayout {
286 pub(crate) wgpu_bind_group_layout: Arc<wgc::binding_model::BindGroupLayout>,
287}
288
289#[derive(Debug, Clone)]
290pub struct CoreBindGroup {
291 pub(crate) wgpu_bind_group: Arc<wgc::binding_model::BindGroup>,
292}
293
294#[derive(Debug, Clone)]
295pub struct CoreTexture {
296 pub(crate) wgpu_texture: Arc<wgc::resource::Texture>,
297}
298
299impl CoreTexture {
300 pub unsafe fn as_hal<A: hal::Api>(&self) -> Option<impl Deref<Target = A::Texture>> {
301 unsafe { self.wgpu_texture.clone().as_hal::<A>() }
302 }
303}
304
305#[derive(Debug, Clone)]
306pub struct CoreTextureView {
307 pub(crate) wgpu_texture_view: Arc<wgc::resource::TextureView>,
308}
309
310impl CoreTextureView {
311 pub unsafe fn as_hal<A: hal::Api>(&self) -> Option<impl Deref<Target = A::TextureView>> {
312 unsafe { self.wgpu_texture_view.clone().as_hal::<A>() }
313 }
314}
315
316#[derive(Debug, Clone)]
317pub struct CoreExternalTexture {
318 pub(crate) wgpu_external_texture: Arc<wgc::resource::ExternalTexture>,
319}
320
321#[derive(Debug, Clone)]
322pub struct CoreSampler {
323 pub(crate) wgpu_sampler: Arc<wgc::resource::Sampler>,
324}
325
326#[derive(Debug, Clone)]
327pub struct CoreQuerySet {
328 pub(crate) wgpu_query_set: Arc<wgc::resource::QuerySet>,
329}
330
331#[derive(Debug, Clone)]
332pub struct CorePipelineLayout {
333 pub(crate) wgpu_pipeline_layout: Arc<wgc::binding_model::PipelineLayout>,
334}
335
336#[derive(Debug, Clone)]
337pub struct CorePipelineCache {
338 pub(crate) wgpu_pipeline_cache: Arc<wgc::pipeline::PipelineCache>,
339}
340
341pub struct CoreCommandBuffer {
342 pub(crate) wgpu_command_buffer: Arc<wgc::command::CommandBuffer>,
343}
344
345impl fmt::Debug for CoreCommandBuffer {
346 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
347 f.debug_struct("CoreCommandBuffer")
348 .field(
349 "wgpu_command_buffer",
350 &Arc::as_ptr(&self.wgpu_command_buffer),
351 )
352 .finish()
353 }
354}
355
356#[derive(Debug)]
357pub struct CoreRenderBundleEncoder {
358 encoder: Box<wgc::command::RenderBundleEncoder>,
359}
360
361#[derive(Debug, Clone)]
362pub struct CoreRenderBundle {
363 pub(crate) wgpu_render_bundle: Arc<wgc::command::RenderBundle>,
364}
365
366#[derive(Clone)]
367pub struct CoreQueue {
368 pub(crate) wgpu_queue: Arc<wgc::device::queue::Queue>,
369}
370
371impl fmt::Debug for CoreQueue {
372 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
373 f.debug_struct("CoreQueue")
374 .field("wgpu_queue", &Arc::as_ptr(&self.wgpu_queue))
375 .finish()
376 }
377}
378
379impl CoreQueue {
380 pub unsafe fn as_hal<A: hal::Api>(
381 &self,
382 ) -> Option<impl Deref<Target = A::Queue> + WasmNotSendSync> {
383 unsafe { self.wgpu_queue.clone().as_hal::<A>() }
384 }
385}
386
387#[derive(Debug, Clone)]
388pub struct CoreComputePipeline {
389 pub(crate) wgpu_compute_pipeline: Arc<wgc::pipeline::ComputePipeline>,
390}
391
392#[derive(Debug, Clone)]
393pub struct CoreRenderPipeline {
394 pub(crate) wgpu_render_pipeline: Arc<wgc::pipeline::RenderPipeline>,
395}
396
397#[derive(Debug)]
398pub struct CoreComputePass {
399 pass: wgc::command::ComputePass,
400
401 id: crate::cmp::Identifier,
402}
403
404#[derive(Debug)]
405pub struct CoreRenderPass {
406 pass: wgc::command::RenderPass,
407
408 id: crate::cmp::Identifier,
409}
410
411pub struct CoreCommandEncoder {
412 pub(crate) wgpu_command_encoder: Arc<wgc::command::CommandEncoder>,
413}
414
415impl fmt::Debug for CoreCommandEncoder {
416 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
417 f.debug_struct("CoreCommandEncoder")
418 .field(
419 "wgpu_command_encoder",
420 &Arc::as_ptr(&self.wgpu_command_encoder),
421 )
422 .finish()
423 }
424}
425
426impl CoreCommandEncoder {
427 pub unsafe fn as_hal_mut<A: hal::Api, F: FnOnce(Option<&mut A::CommandEncoder>) -> R, R>(
429 &self,
430 hal_command_encoder_callback: F,
431 ) -> R {
432 unsafe {
433 self.wgpu_command_encoder
434 .as_hal_mut::<A, F, R>(hal_command_encoder_callback)
435 }
436 }
437}
438
439#[derive(Debug, Clone)]
440pub struct CoreBlas {
441 pub(crate) wgpu_blas: Arc<wgc::resource::Blas>,
442}
443
444impl CoreBlas {
445 pub unsafe fn as_hal<A: hal::Api>(
446 &self,
447 ) -> Option<impl Deref<Target = A::AccelerationStructure>> {
448 unsafe { self.wgpu_blas.clone().as_hal::<A>() }
449 }
450}
451
452#[derive(Debug, Clone)]
453pub struct CoreTlas {
454 pub(crate) wgpu_tlas: Arc<wgc::resource::Tlas>,
455}
456
457impl CoreTlas {
458 pub unsafe fn as_hal<A: hal::Api>(
459 &self,
460 ) -> Option<impl Deref<Target = A::AccelerationStructure>> {
461 unsafe { self.wgpu_tlas.clone().as_hal::<A>() }
462 }
463}
464
465#[derive(Clone)]
466pub struct CoreSurfaceOutputDetail {
467 wgpu_surface: Arc<wgc::instance::Surface>,
468 error_sink: ErrorSink,
469}
470
471impl fmt::Debug for CoreSurfaceOutputDetail {
472 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
473 f.debug_struct("CoreSurfaceOutputDetail")
474 .field("wgpu_surface", &Arc::as_ptr(&self.wgpu_surface))
475 .finish()
476 }
477}
478
479#[derive(Debug)]
480pub struct CoreQueueWriteBuffer {
481 wgpu_staging_buffer: wgc::resource::StagingBuffer,
482 mapping: CoreBufferMappedRange,
483}
484
485#[derive(Debug)]
486pub struct CoreBufferMappedRange {
487 ptr: NonNull<u8>,
488 size: usize,
489}
490
491#[cfg(send_sync)]
492unsafe impl Send for CoreBufferMappedRange {}
493#[cfg(send_sync)]
494unsafe impl Sync for CoreBufferMappedRange {}
495
496impl Drop for CoreBufferMappedRange {
497 fn drop(&mut self) {
498 }
501}
502
503crate::cmp::impl_eq_ord_hash_arc_address!(ContextWgpuCore => .0);
504crate::cmp::impl_eq_ord_hash_arc_address!(CoreAdapter => .wgpu_adapter);
505crate::cmp::impl_eq_ord_hash_arc_address!(CoreDevice => .wgpu_device);
506crate::cmp::impl_eq_ord_hash_arc_address!(CoreQueue => .wgpu_queue);
507crate::cmp::impl_eq_ord_hash_arc_address!(CoreShaderModule => .wgpu_shader_module);
508crate::cmp::impl_eq_ord_hash_arc_address!(CoreBindGroupLayout => .wgpu_bind_group_layout);
509crate::cmp::impl_eq_ord_hash_arc_address!(CoreBindGroup => .wgpu_bind_group);
510crate::cmp::impl_eq_ord_hash_arc_address!(CoreTextureView => .wgpu_texture_view);
511crate::cmp::impl_eq_ord_hash_arc_address!(CoreSampler => .wgpu_sampler);
512crate::cmp::impl_eq_ord_hash_arc_address!(CoreBuffer => .wgpu_buffer);
513crate::cmp::impl_eq_ord_hash_arc_address!(CoreTexture => .wgpu_texture);
514crate::cmp::impl_eq_ord_hash_arc_address!(CoreExternalTexture => .wgpu_external_texture);
515crate::cmp::impl_eq_ord_hash_arc_address!(CoreBlas => .wgpu_blas);
516crate::cmp::impl_eq_ord_hash_arc_address!(CoreTlas => .wgpu_tlas);
517crate::cmp::impl_eq_ord_hash_arc_address!(CoreQuerySet => .wgpu_query_set);
518crate::cmp::impl_eq_ord_hash_arc_address!(CorePipelineLayout => .wgpu_pipeline_layout);
519crate::cmp::impl_eq_ord_hash_arc_address!(CoreRenderPipeline => .wgpu_render_pipeline);
520crate::cmp::impl_eq_ord_hash_arc_address!(CoreComputePipeline => .wgpu_compute_pipeline);
521crate::cmp::impl_eq_ord_hash_arc_address!(CorePipelineCache => .wgpu_pipeline_cache);
522crate::cmp::impl_eq_ord_hash_arc_address!(CoreCommandEncoder => .wgpu_command_encoder);
523crate::cmp::impl_eq_ord_hash_proxy!(CoreComputePass => .id);
524crate::cmp::impl_eq_ord_hash_proxy!(CoreRenderPass => .id);
525crate::cmp::impl_eq_ord_hash_arc_address!(CoreCommandBuffer => .wgpu_command_buffer);
526crate::cmp::impl_eq_ord_hash_box_address!(CoreRenderBundleEncoder => .encoder);
527crate::cmp::impl_eq_ord_hash_arc_address!(CoreRenderBundle => .wgpu_render_bundle);
528crate::cmp::impl_eq_ord_hash_arc_address!(CoreSurface => .wgpu_surface);
529crate::cmp::impl_eq_ord_hash_arc_address!(CoreSurfaceOutputDetail => .wgpu_surface);
530crate::cmp::impl_eq_ord_hash_proxy!(CoreQueueWriteBuffer => .mapping.ptr);
531crate::cmp::impl_eq_ord_hash_proxy!(CoreBufferMappedRange => .ptr);
532
533impl dispatch::InstanceInterface for ContextWgpuCore {
534 fn new(desc: wgt::InstanceDescriptor) -> Self
535 where
536 Self: Sized,
537 {
538 Self(wgc::instance::Instance::new("wgpu", desc, None))
539 }
540
541 unsafe fn create_surface(
542 &self,
543 target: crate::api::SurfaceTargetUnsafe,
544 ) -> Result<dispatch::DispatchSurface, crate::CreateSurfaceError> {
545 let wgpu_surface = match target {
546 SurfaceTargetUnsafe::RawHandle {
547 raw_display_handle,
548 raw_window_handle,
549 } => unsafe { self.0.create_surface(raw_display_handle, raw_window_handle) },
550
551 #[cfg(all(drm, not(target_os = "netbsd")))]
552 SurfaceTargetUnsafe::Drm {
553 fd,
554 plane,
555 connector_id,
556 width,
557 height,
558 refresh_rate,
559 } => unsafe {
560 self.0
561 .create_surface_from_drm(fd, plane, connector_id, width, height, refresh_rate)
562 },
563
564 #[cfg(metal)]
565 SurfaceTargetUnsafe::CoreAnimationLayer(layer) => unsafe {
566 self.0.create_surface_metal(layer)
567 },
568
569 #[cfg(all(drm, target_os = "netbsd"))]
570 SurfaceTargetUnsafe::Drm { .. } => Err(
571 wgc::instance::CreateSurfaceError::BackendNotEnabled(wgt::Backend::Vulkan),
572 ),
573
574 #[cfg(dx12)]
575 SurfaceTargetUnsafe::CompositionVisual(visual) => unsafe {
576 self.0.create_surface_from_visual(visual)
577 },
578
579 #[cfg(dx12)]
580 SurfaceTargetUnsafe::SurfaceHandle(surface_handle) => unsafe {
581 self.0.create_surface_from_surface_handle(surface_handle)
582 },
583
584 #[cfg(dx12)]
585 SurfaceTargetUnsafe::SwapChainPanel(swap_chain_panel) => unsafe {
586 self.0
587 .create_surface_from_swap_chain_panel(swap_chain_panel)
588 },
589 }?;
590
591 Ok(CoreSurface {
592 wgpu_surface,
593 configured_device: Arc::new(Mutex::default()),
594 }
595 .into())
596 }
597
598 fn request_adapter(
599 &self,
600 options: &crate::api::RequestAdapterOptions<'_, '_>,
601 ) -> Pin<Box<dyn dispatch::RequestAdapterFuture>> {
602 let adapter = self.0.request_adapter(
603 &wgt::RequestAdapterOptions {
604 power_preference: options.power_preference,
605 force_fallback_adapter: options.force_fallback_adapter,
606 compatible_surface: options
607 .compatible_surface
608 .map(|surface| &*surface.inner.as_core().wgpu_surface),
609 apply_limit_buckets: false,
610 },
611 wgt::Backends::all(),
612 );
613 let adapter = adapter.map(|wgpu_adapter| {
614 let core = CoreAdapter { wgpu_adapter };
615 let generic: dispatch::DispatchAdapter = core.into();
616 generic
617 });
618 Box::pin(ready(adapter))
619 }
620
621 fn poll_all_devices(&self, force_wait: bool) -> bool {
622 match self.0.poll_all_devices(force_wait) {
623 Ok(all_queue_empty) => all_queue_empty,
624 Err(err) => handle_error_fatal(err, "Instance::poll_all_devices"),
625 }
626 }
627
628 #[cfg(feature = "wgsl")]
629 fn wgsl_language_features(&self) -> crate::WgslLanguageFeatures {
630 use wgc::naga::front::wgsl::ImplementedLanguageExtension;
631 ImplementedLanguageExtension::all().iter().copied().fold(
632 crate::WgslLanguageFeatures::empty(),
633 |acc, wle| {
634 acc | match wle {
635 ImplementedLanguageExtension::ReadOnlyAndReadWriteStorageTextures => {
636 crate::WgslLanguageFeatures::ReadOnlyAndReadWriteStorageTextures
637 }
638 ImplementedLanguageExtension::Packed4x8IntegerDotProduct => {
639 crate::WgslLanguageFeatures::Packed4x8IntegerDotProduct
640 }
641 ImplementedLanguageExtension::PointerCompositeAccess => {
642 crate::WgslLanguageFeatures::PointerCompositeAccess
643 }
644 ImplementedLanguageExtension::ImmediateAddressSpace => {
645 crate::WgslLanguageFeatures::ImmediateAddressSpace
646 }
647 }
648 },
649 )
650 }
651
652 fn enumerate_adapters(
653 &self,
654 backends: crate::Backends,
655 ) -> Pin<Box<dyn dispatch::EnumerateAdapterFuture>> {
656 let adapters: Vec<DispatchAdapter> = self
657 .enumerate_adapters(backends)
658 .into_iter()
659 .map(|adapter| {
660 let core = crate::backend::wgpu_core::CoreAdapter {
661 wgpu_adapter: adapter,
662 };
663 core.into()
664 })
665 .collect();
666 Box::pin(ready(adapters))
667 }
668}
669
670impl dispatch::AdapterInterface for CoreAdapter {
671 fn request_device(
672 &self,
673 desc: &crate::DeviceDescriptor<'_>,
674 ) -> Pin<Box<dyn dispatch::RequestDeviceFuture>> {
675 let res = self
676 .wgpu_adapter
677 .request_device(&desc.map_label(|l| l.map(Borrowed)));
678 let (device, queue) = match res {
679 Ok(ids) => ids,
680 Err(err) => {
681 return Box::pin(ready(Err(err.into())));
682 }
683 };
684 let device = CoreDevice {
685 wgpu_device: device,
686 };
687 let queue = CoreQueue { wgpu_queue: queue };
688 Box::pin(ready(Ok((device.into(), queue.into()))))
689 }
690
691 fn is_surface_supported(&self, surface: &dispatch::DispatchSurface) -> bool {
692 let surface = surface.as_core();
693
694 self.wgpu_adapter
695 .is_surface_supported(&surface.wgpu_surface)
696 }
697
698 fn features(&self) -> crate::Features {
699 self.wgpu_adapter.features()
700 }
701
702 fn limits(&self) -> crate::Limits {
703 self.wgpu_adapter.limits()
704 }
705
706 fn downlevel_capabilities(&self) -> crate::DownlevelCapabilities {
707 self.wgpu_adapter.downlevel_capabilities()
708 }
709
710 fn get_info(&self) -> crate::AdapterInfo {
711 self.wgpu_adapter.get_info()
712 }
713
714 fn get_texture_format_features(
715 &self,
716 format: crate::TextureFormat,
717 ) -> crate::TextureFormatFeatures {
718 self.wgpu_adapter.get_texture_format_features(format)
719 }
720
721 fn get_presentation_timestamp(&self) -> crate::PresentationTimestamp {
722 self.wgpu_adapter.get_presentation_timestamp()
723 }
724
725 fn cooperative_matrix_properties(&self) -> Vec<crate::wgt::CooperativeMatrixProperties> {
726 self.wgpu_adapter.cooperative_matrix_properties()
727 }
728}
729
730impl Drop for CoreAdapter {
731 fn drop(&mut self) {}
732}
733
734impl dispatch::DeviceInterface for CoreDevice {
735 fn features(&self) -> crate::Features {
736 *self.wgpu_device.features()
737 }
738
739 fn limits(&self) -> crate::Limits {
740 self.wgpu_device.limits().clone()
741 }
742
743 fn adapter_info(&self) -> crate::AdapterInfo {
744 self.wgpu_device.adapter_info()
745 }
746
747 #[cfg_attr(
749 not(any(
750 feature = "spirv",
751 feature = "glsl",
752 feature = "wgsl",
753 feature = "naga-ir"
754 )),
755 expect(unused)
756 )]
757 fn create_shader_module(
758 &self,
759 desc: crate::ShaderModuleDescriptor<'_>,
760 shader_bound_checks: wgt::ShaderRuntimeChecks,
761 ) -> dispatch::DispatchShaderModule {
762 let descriptor = wgc::pipeline::ShaderModuleDescriptor {
763 label: desc.label.map(Borrowed),
764 runtime_checks: shader_bound_checks,
765 };
766 let source = match desc.source {
767 #[cfg(feature = "spirv")]
768 ShaderSource::SpirV(ref spv) => {
769 let options = naga::front::spv::Options {
771 adjust_coordinate_space: false, strict_capabilities: true,
773 block_ctx_dump_prefix: None,
774 };
775 wgc::pipeline::ShaderModuleSource::SpirV(Borrowed(spv), options)
776 }
777 #[cfg(feature = "glsl")]
778 ShaderSource::Glsl {
779 ref shader,
780 stage,
781 defines,
782 } => {
783 let options = naga::front::glsl::Options {
784 stage,
785 defines: defines
786 .iter()
787 .map(|&(key, value)| (String::from(key), String::from(value)))
788 .collect(),
789 };
790 wgc::pipeline::ShaderModuleSource::Glsl(Borrowed(shader), options)
791 }
792 #[cfg(feature = "wgsl")]
793 ShaderSource::Wgsl(ref code) => wgc::pipeline::ShaderModuleSource::Wgsl(Borrowed(code)),
794 #[cfg(feature = "naga-ir")]
795 ShaderSource::Naga(module) => wgc::pipeline::ShaderModuleSource::Naga(module),
796 ShaderSource::Dummy(_) => panic!("found `ShaderSource::Dummy`"),
797 };
798 let wgpu_shader_module = self.wgpu_device.create_shader_module(&descriptor, source);
799
800 CoreShaderModule { wgpu_shader_module }.into()
801 }
802
803 unsafe fn create_shader_module_passthrough(
804 &self,
805 desc: &crate::ShaderModuleDescriptorPassthrough<'_>,
806 ) -> dispatch::DispatchShaderModule {
807 let desc = desc.map_label(|l| l.map(Cow::from));
808 let wgpu_shader_module =
809 unsafe { self.wgpu_device.create_shader_module_passthrough(&desc) };
810
811 CoreShaderModule { wgpu_shader_module }.into()
812 }
813
814 fn create_bind_group_layout(
815 &self,
816 desc: &crate::BindGroupLayoutDescriptor<'_>,
817 ) -> dispatch::DispatchBindGroupLayout {
818 let descriptor = wgc::binding_model::BindGroupLayoutDescriptor {
819 label: desc.label.map(Borrowed),
820 entries: Borrowed(desc.entries),
821 };
822 let wgpu_bind_group_layout = self.wgpu_device.create_bind_group_layout(&descriptor);
823 CoreBindGroupLayout {
824 wgpu_bind_group_layout,
825 }
826 .into()
827 }
828
829 fn create_bind_group(
830 &self,
831 desc: &crate::BindGroupDescriptor<'_>,
832 ) -> dispatch::DispatchBindGroup {
833 use wgc::binding_model as bm;
834
835 let mut arrayed_texture_views = Vec::new();
836 let mut arrayed_samplers = Vec::new();
837 if self
838 .wgpu_device
839 .features()
840 .contains(Features::TEXTURE_BINDING_ARRAY)
841 {
842 for entry in desc.entries.iter() {
844 if let BindingResource::TextureViewArray(array) = entry.resource {
845 arrayed_texture_views.extend(
846 array
847 .iter()
848 .map(|view| view.inner.as_core().wgpu_texture_view.clone()),
849 );
850 }
851 if let BindingResource::SamplerArray(array) = entry.resource {
852 arrayed_samplers.extend(
853 array
854 .iter()
855 .map(|sampler| sampler.inner.as_core().wgpu_sampler.clone()),
856 );
857 }
858 }
859 }
860 let mut remaining_arrayed_texture_views = &arrayed_texture_views[..];
861 let mut remaining_arrayed_samplers = &arrayed_samplers[..];
862
863 let mut arrayed_buffer_bindings = Vec::new();
864 if self
865 .wgpu_device
866 .features()
867 .contains(Features::BUFFER_BINDING_ARRAY)
868 {
869 for entry in desc.entries.iter() {
871 if let BindingResource::BufferArray(array) = entry.resource {
872 arrayed_buffer_bindings.extend(array.iter().map(|binding| bm::BufferBinding {
873 buffer: binding.buffer.inner.as_core().wgpu_buffer.clone(),
874 offset: binding.offset,
875 size: binding.size.map(wgt::BufferSize::get),
876 }));
877 }
878 }
879 }
880 let mut remaining_arrayed_buffer_bindings = &arrayed_buffer_bindings[..];
881
882 let mut arrayed_acceleration_structures = Vec::new();
883 if self
884 .wgpu_device
885 .features()
886 .contains(Features::ACCELERATION_STRUCTURE_BINDING_ARRAY)
887 {
888 for entry in desc.entries.iter() {
890 if let BindingResource::AccelerationStructureArray(array) = entry.resource {
891 arrayed_acceleration_structures.extend(
892 array
893 .iter()
894 .map(|tlas| tlas.inner.as_core().wgpu_tlas.clone()),
895 );
896 }
897 }
898 }
899 let mut remaining_arrayed_acceleration_structures = &arrayed_acceleration_structures[..];
900
901 let entries = desc
902 .entries
903 .iter()
904 .map(|entry| bm::BindGroupEntry {
905 binding: entry.binding,
906 resource: match entry.resource {
907 BindingResource::Buffer(BufferBinding {
908 buffer,
909 offset,
910 size,
911 }) => bm::BindingResource::Buffer(bm::BufferBinding {
912 buffer: buffer.inner.as_core().wgpu_buffer.clone(),
913 offset,
914 size: size.map(wgt::BufferSize::get),
915 }),
916 BindingResource::BufferArray(array) => {
917 let slice = &remaining_arrayed_buffer_bindings[..array.len()];
918 remaining_arrayed_buffer_bindings =
919 &remaining_arrayed_buffer_bindings[array.len()..];
920 bm::BindingResource::BufferArray(Borrowed(slice))
921 }
922 BindingResource::Sampler(sampler) => {
923 bm::BindingResource::Sampler(sampler.inner.as_core().wgpu_sampler.clone())
924 }
925 BindingResource::SamplerArray(array) => {
926 let slice = &remaining_arrayed_samplers[..array.len()];
927 remaining_arrayed_samplers = &remaining_arrayed_samplers[array.len()..];
928 bm::BindingResource::SamplerArray(Borrowed(slice))
929 }
930 BindingResource::TextureView(texture_view) => bm::BindingResource::TextureView(
931 texture_view.inner.as_core().wgpu_texture_view.clone(),
932 ),
933 BindingResource::TextureViewArray(array) => {
934 let slice = &remaining_arrayed_texture_views[..array.len()];
935 remaining_arrayed_texture_views =
936 &remaining_arrayed_texture_views[array.len()..];
937 bm::BindingResource::TextureViewArray(Borrowed(slice))
938 }
939 BindingResource::AccelerationStructure(acceleration_structure) => {
940 bm::BindingResource::AccelerationStructure(
941 acceleration_structure.inner.as_core().wgpu_tlas.clone(),
942 )
943 }
944 BindingResource::AccelerationStructureArray(array) => {
945 let slice = &remaining_arrayed_acceleration_structures[..array.len()];
946 remaining_arrayed_acceleration_structures =
947 &remaining_arrayed_acceleration_structures[array.len()..];
948 bm::BindingResource::AccelerationStructureArray(Borrowed(slice))
949 }
950 BindingResource::ExternalTexture(external_texture) => {
951 bm::BindingResource::ExternalTexture(
952 external_texture
953 .inner
954 .as_core()
955 .wgpu_external_texture
956 .clone(),
957 )
958 }
959 },
960 })
961 .collect::<Vec<_>>();
962 let descriptor = bm::BindGroupDescriptor {
963 label: desc.label.as_ref().map(|label| Borrowed(&label[..])),
964 layout: desc.layout.inner.as_core().wgpu_bind_group_layout.clone(),
965 entries: Borrowed(&entries),
966 };
967
968 let wgpu_bind_group = self.wgpu_device.create_bind_group(&descriptor);
969 CoreBindGroup { wgpu_bind_group }.into()
970 }
971
972 fn create_pipeline_layout(
973 &self,
974 desc: &crate::PipelineLayoutDescriptor<'_>,
975 ) -> dispatch::DispatchPipelineLayout {
976 assert!(
979 desc.bind_group_layouts.len() <= wgc::MAX_BIND_GROUPS,
980 "Bind group layout count {} exceeds device bind group limit {}",
981 desc.bind_group_layouts.len(),
982 wgc::MAX_BIND_GROUPS
983 );
984
985 let temp_layouts = desc
986 .bind_group_layouts
987 .iter()
988 .map(|bgl| bgl.map(|bgl| bgl.inner.as_core().wgpu_bind_group_layout.clone()))
989 .collect::<ArrayVec<_, { wgc::MAX_BIND_GROUPS }>>();
990 let descriptor = wgc::binding_model::PipelineLayoutDescriptor {
991 label: desc.label.map(Borrowed),
992 bind_group_layouts: Borrowed(&temp_layouts),
993 immediate_size: desc.immediate_size,
994 };
995
996 let wgpu_pipeline_layout = self.wgpu_device.create_pipeline_layout(&descriptor);
997
998 CorePipelineLayout {
999 wgpu_pipeline_layout,
1000 }
1001 .into()
1002 }
1003
1004 fn create_render_pipeline(
1005 &self,
1006 desc: &crate::RenderPipelineDescriptor<'_>,
1007 ) -> dispatch::DispatchRenderPipeline {
1008 use wgc::pipeline as pipe;
1009
1010 let vertex_buffers: ArrayVec<_, { wgc::MAX_VERTEX_BUFFERS }> = desc
1011 .vertex
1012 .buffers
1013 .iter()
1014 .map(|vbuf| {
1015 vbuf.as_ref().map(|vbuf| pipe::VertexBufferLayout {
1016 array_stride: vbuf.array_stride,
1017 step_mode: vbuf.step_mode,
1018 attributes: Borrowed(vbuf.attributes),
1019 })
1020 })
1021 .collect();
1022
1023 let vert_constants = desc
1024 .vertex
1025 .compilation_options
1026 .constants
1027 .iter()
1028 .map(|&(key, value)| (String::from(key), value))
1029 .collect();
1030
1031 let descriptor = pipe::ResolvedGeneralRenderPipelineDescriptor {
1032 label: desc.label.map(Borrowed),
1033 layout: desc
1034 .layout
1035 .map(|layout| layout.inner.as_core().wgpu_pipeline_layout.clone()),
1036 vertex: wgc::pipeline::RenderPipelineVertexProcessor::Vertex(pipe::VertexState {
1037 stage: pipe::ProgrammableStageDescriptor {
1038 module: desc
1039 .vertex
1040 .module
1041 .inner
1042 .as_core()
1043 .wgpu_shader_module
1044 .clone(),
1045 entry_point: desc.vertex.entry_point.map(Borrowed),
1046 constants: vert_constants,
1047 zero_initialize_workgroup_memory: desc
1048 .vertex
1049 .compilation_options
1050 .zero_initialize_workgroup_memory,
1051 },
1052 buffers: Borrowed(&vertex_buffers),
1053 }),
1054 primitive: desc.primitive,
1055 depth_stencil: desc.depth_stencil.clone(),
1056 multisample: desc.multisample,
1057 fragment: desc.fragment.as_ref().map(|frag| {
1058 let frag_constants = frag
1059 .compilation_options
1060 .constants
1061 .iter()
1062 .map(|&(key, value)| (String::from(key), value))
1063 .collect();
1064 pipe::FragmentState {
1065 stage: pipe::ProgrammableStageDescriptor {
1066 module: frag.module.inner.as_core().wgpu_shader_module.clone(),
1067 entry_point: frag.entry_point.map(Borrowed),
1068 constants: frag_constants,
1069 zero_initialize_workgroup_memory: frag
1070 .compilation_options
1071 .zero_initialize_workgroup_memory,
1072 },
1073 targets: Borrowed(frag.targets),
1074 }
1075 }),
1076 multiview_mask: desc.multiview_mask,
1077 cache: desc
1078 .cache
1079 .map(|cache| cache.inner.as_core().wgpu_pipeline_cache.clone()),
1080 };
1081
1082 let wgpu_render_pipeline = self.wgpu_device.create_render_pipeline(descriptor);
1083 CoreRenderPipeline {
1084 wgpu_render_pipeline,
1085 }
1086 .into()
1087 }
1088
1089 fn create_mesh_pipeline(
1090 &self,
1091 desc: &crate::MeshPipelineDescriptor<'_>,
1092 ) -> dispatch::DispatchRenderPipeline {
1093 use wgc::pipeline as pipe;
1094
1095 let mesh_constants = desc
1096 .mesh
1097 .compilation_options
1098 .constants
1099 .iter()
1100 .map(|&(key, value)| (String::from(key), value))
1101 .collect();
1102 let descriptor = pipe::MeshPipelineDescriptor {
1103 label: desc.label.map(Borrowed),
1104 task: desc.task.as_ref().map(|task| {
1105 let task_constants = task
1106 .compilation_options
1107 .constants
1108 .iter()
1109 .map(|&(key, value)| (String::from(key), value))
1110 .collect();
1111 pipe::TaskState {
1112 stage: pipe::ProgrammableStageDescriptor {
1113 module: task.module.inner.as_core().wgpu_shader_module.clone(),
1114 entry_point: task.entry_point.map(Borrowed),
1115 constants: task_constants,
1116 zero_initialize_workgroup_memory: desc
1117 .mesh
1118 .compilation_options
1119 .zero_initialize_workgroup_memory,
1120 },
1121 }
1122 }),
1123 mesh: pipe::MeshState {
1124 stage: pipe::ProgrammableStageDescriptor {
1125 module: desc.mesh.module.inner.as_core().wgpu_shader_module.clone(),
1126 entry_point: desc.mesh.entry_point.map(Borrowed),
1127 constants: mesh_constants,
1128 zero_initialize_workgroup_memory: desc
1129 .mesh
1130 .compilation_options
1131 .zero_initialize_workgroup_memory,
1132 },
1133 },
1134 layout: desc
1135 .layout
1136 .map(|layout| layout.inner.as_core().wgpu_pipeline_layout.clone()),
1137 primitive: desc.primitive,
1138 depth_stencil: desc.depth_stencil.clone(),
1139 multisample: desc.multisample,
1140 fragment: desc.fragment.as_ref().map(|frag| {
1141 let frag_constants = frag
1142 .compilation_options
1143 .constants
1144 .iter()
1145 .map(|&(key, value)| (String::from(key), value))
1146 .collect();
1147 pipe::FragmentState {
1148 stage: pipe::ProgrammableStageDescriptor {
1149 module: frag.module.inner.as_core().wgpu_shader_module.clone(),
1150 entry_point: frag.entry_point.map(Borrowed),
1151 constants: frag_constants,
1152 zero_initialize_workgroup_memory: frag
1153 .compilation_options
1154 .zero_initialize_workgroup_memory,
1155 },
1156 targets: Borrowed(frag.targets),
1157 }
1158 }),
1159 multiview: desc.multiview,
1160 cache: desc
1161 .cache
1162 .map(|cache| cache.inner.as_core().wgpu_pipeline_cache.clone()),
1163 };
1164
1165 let wgpu_render_pipeline = self.wgpu_device.create_render_pipeline(descriptor.into());
1166 CoreRenderPipeline {
1167 wgpu_render_pipeline,
1168 }
1169 .into()
1170 }
1171
1172 fn create_compute_pipeline(
1173 &self,
1174 desc: &crate::ComputePipelineDescriptor<'_>,
1175 ) -> dispatch::DispatchComputePipeline {
1176 use wgc::pipeline as pipe;
1177
1178 let constants = desc
1179 .compilation_options
1180 .constants
1181 .iter()
1182 .map(|&(key, value)| (String::from(key), value))
1183 .collect();
1184
1185 let descriptor = pipe::ComputePipelineDescriptor {
1186 label: desc.label.map(Borrowed),
1187 layout: desc
1188 .layout
1189 .map(|pll| pll.inner.as_core().wgpu_pipeline_layout.clone()),
1190 stage: pipe::ProgrammableStageDescriptor {
1191 module: desc.module.inner.as_core().wgpu_shader_module.clone(),
1192 entry_point: desc.entry_point.map(Borrowed),
1193 constants,
1194 zero_initialize_workgroup_memory: desc
1195 .compilation_options
1196 .zero_initialize_workgroup_memory,
1197 },
1198 cache: desc
1199 .cache
1200 .map(|cache| cache.inner.as_core().wgpu_pipeline_cache.clone()),
1201 };
1202
1203 let wgpu_compute_pipeline = self.wgpu_device.create_compute_pipeline(descriptor);
1204 CoreComputePipeline {
1205 wgpu_compute_pipeline,
1206 }
1207 .into()
1208 }
1209
1210 unsafe fn create_pipeline_cache(
1211 &self,
1212 desc: &crate::PipelineCacheDescriptor<'_>,
1213 ) -> dispatch::DispatchPipelineCache {
1214 use wgc::pipeline as pipe;
1215
1216 let descriptor = pipe::PipelineCacheDescriptor {
1217 label: desc.label.map(Borrowed),
1218 data: desc.data.map(Borrowed),
1219 fallback: desc.fallback,
1220 };
1221 let (wgpu_pipeline_cache, error) =
1222 unsafe { self.wgpu_device.create_pipeline_cache(&descriptor) };
1223 if let Some(cause) = error {
1224 self.wgpu_device.handle_error(
1225 cause,
1226 desc.label,
1227 "Device::device_create_pipeline_cache_init",
1228 );
1229 }
1230 CorePipelineCache {
1231 wgpu_pipeline_cache,
1232 }
1233 .into()
1234 }
1235
1236 fn create_buffer(&self, desc: &crate::BufferDescriptor<'_>) -> dispatch::DispatchBuffer {
1237 let wgpu_buffer = self
1238 .wgpu_device
1239 .create_buffer(&desc.map_label(|l| l.map(Borrowed)));
1240
1241 CoreBuffer { wgpu_buffer }.into()
1242 }
1243
1244 fn create_texture(&self, desc: &crate::TextureDescriptor<'_>) -> dispatch::DispatchTexture {
1245 let wgt_desc = desc.map_label_and_view_formats(|l| l.map(Borrowed), |v| v.to_vec());
1246 let wgpu_texture = self.wgpu_device.create_texture(&wgt_desc);
1247
1248 CoreTexture { wgpu_texture }.into()
1249 }
1250
1251 fn create_external_texture(
1252 &self,
1253 desc: &crate::ExternalTextureDescriptor<'_>,
1254 planes: &[&crate::TextureView],
1255 ) -> dispatch::DispatchExternalTexture {
1256 let wgt_desc = desc.map_label(|l| l.map(Borrowed));
1257 let planes = planes
1258 .iter()
1259 .map(|plane| plane.inner.as_core().wgpu_texture_view.clone())
1260 .collect::<Vec<_>>();
1261 let wgpu_external_texture = self.wgpu_device.create_external_texture(&wgt_desc, &planes);
1262
1263 CoreExternalTexture {
1264 wgpu_external_texture,
1265 }
1266 .into()
1267 }
1268
1269 fn create_blas(
1270 &self,
1271 desc: &crate::CreateBlasDescriptor<'_>,
1272 sizes: crate::BlasGeometrySizeDescriptors,
1273 ) -> (Option<u64>, dispatch::DispatchBlas) {
1274 let (wgpu_blas, error) = self
1275 .wgpu_device
1276 .create_blas(&desc.map_label(|l| l.map(Borrowed)), sizes);
1277 if let Some(cause) = error {
1278 self.wgpu_device
1279 .handle_error(cause, desc.label, "Device::create_blas");
1280 }
1281 (wgpu_blas.handle(), CoreBlas { wgpu_blas }.into())
1282 }
1283
1284 fn create_tlas(&self, desc: &crate::CreateTlasDescriptor<'_>) -> dispatch::DispatchTlas {
1285 let (wgpu_tlas, error) = self
1286 .wgpu_device
1287 .create_tlas(&desc.map_label(|l| l.map(Borrowed)));
1288 if let Some(cause) = error {
1289 self.wgpu_device
1290 .handle_error(cause, desc.label, "Device::create_tlas");
1291 }
1292 CoreTlas { wgpu_tlas }.into()
1293 }
1294
1295 fn create_sampler(&self, desc: &crate::SamplerDescriptor<'_>) -> dispatch::DispatchSampler {
1296 let descriptor = wgc::resource::SamplerDescriptor {
1297 label: desc.label.map(Borrowed),
1298 address_modes: [
1299 desc.address_mode_u,
1300 desc.address_mode_v,
1301 desc.address_mode_w,
1302 ],
1303 mag_filter: desc.mag_filter,
1304 min_filter: desc.min_filter,
1305 mipmap_filter: desc.mipmap_filter,
1306 lod_min_clamp: desc.lod_min_clamp,
1307 lod_max_clamp: desc.lod_max_clamp,
1308 compare: desc.compare,
1309 anisotropy_clamp: desc.anisotropy_clamp,
1310 border_color: desc.border_color,
1311 };
1312
1313 let wgpu_sampler = self.wgpu_device.create_sampler(&descriptor);
1314 CoreSampler { wgpu_sampler }.into()
1315 }
1316
1317 fn create_query_set(&self, desc: &crate::QuerySetDescriptor<'_>) -> dispatch::DispatchQuerySet {
1318 let wgpu_query_set = self
1319 .wgpu_device
1320 .create_query_set(&desc.map_label(|l| l.map(Borrowed)));
1321 CoreQuerySet { wgpu_query_set }.into()
1322 }
1323
1324 fn create_command_encoder(
1325 &self,
1326 desc: &crate::CommandEncoderDescriptor<'_>,
1327 ) -> dispatch::DispatchCommandEncoder {
1328 let wgpu_command_encoder = self
1329 .wgpu_device
1330 .create_command_encoder(&desc.map_label(|l| l.map(Borrowed)));
1331
1332 CoreCommandEncoder {
1333 wgpu_command_encoder,
1334 }
1335 .into()
1336 }
1337
1338 fn create_render_bundle_encoder(
1339 &self,
1340 desc: &crate::RenderBundleEncoderDescriptor<'_>,
1341 ) -> dispatch::DispatchRenderBundleEncoder {
1342 let descriptor = wgc::command::RenderBundleEncoderDescriptor {
1343 label: desc.label.map(Borrowed),
1344 color_formats: Borrowed(desc.color_formats),
1345 depth_stencil: desc.depth_stencil,
1346 sample_count: desc.sample_count,
1347 multiview: desc.multiview,
1348 };
1349 let encoder = self.wgpu_device.create_render_bundle_encoder(&descriptor);
1350
1351 CoreRenderBundleEncoder { encoder }.into()
1352 }
1353
1354 fn set_device_lost_callback(&self, device_lost_callback: dispatch::BoxDeviceLostCallback) {
1355 self.wgpu_device
1356 .set_device_lost_closure(device_lost_callback);
1357 }
1358
1359 fn on_uncaptured_error(&self, handler: Arc<dyn crate::UncapturedErrorHandler>) {
1360 self.wgpu_device.on_uncaptured_error(handler);
1361 }
1362
1363 fn push_error_scope(&self, filter: crate::ErrorFilter) -> u32 {
1364 self.wgpu_device.push_error_scope_with_index(filter)
1365 }
1366
1367 fn pop_error_scope(&self, index: u32) -> Pin<Box<dyn dispatch::PopErrorScopeFuture>> {
1368 Box::pin(ready(self.wgpu_device.pop_error_scope_checked(index)))
1369 }
1370
1371 unsafe fn start_graphics_debugger_capture(&self) {
1372 unsafe { self.wgpu_device.start_graphics_debugger_capture() };
1373 }
1374
1375 unsafe fn stop_graphics_debugger_capture(&self) {
1376 unsafe { self.wgpu_device.stop_graphics_debugger_capture() };
1377 }
1378
1379 fn poll(&self, poll_type: wgt::PollType<u64>) -> Result<crate::PollStatus, crate::PollError> {
1380 match self.wgpu_device.poll(poll_type) {
1381 Ok(status) => Ok(status),
1382 Err(err) => {
1383 if let Some(poll_error) = err.to_poll_error() {
1384 return Err(poll_error);
1385 }
1386
1387 handle_error_fatal(err, "Device::poll")
1388 }
1389 }
1390 }
1391
1392 fn get_internal_counters(&self) -> crate::InternalCounters {
1393 self.wgpu_device.get_internal_counters()
1394 }
1395
1396 fn generate_allocator_report(&self) -> Option<wgt::AllocatorReport> {
1397 self.wgpu_device.generate_allocator_report()
1398 }
1399
1400 fn destroy(&self) {
1401 self.wgpu_device.destroy();
1402 }
1403}
1404
1405impl Drop for CoreDevice {
1406 fn drop(&mut self) {}
1407}
1408
1409impl dispatch::QueueInterface for CoreQueue {
1410 fn write_buffer(
1411 &self,
1412 buffer: &dispatch::DispatchBuffer,
1413 offset: crate::BufferAddress,
1414 data: &[u8],
1415 ) {
1416 let buffer = buffer.as_core();
1417
1418 self.wgpu_queue
1419 .write_buffer(buffer.wgpu_buffer.clone(), offset, data)
1420 }
1421
1422 fn create_staging_buffer(
1423 &self,
1424 size: crate::BufferSize,
1425 ) -> Option<dispatch::DispatchQueueWriteBuffer> {
1426 match self.wgpu_queue.create_staging_buffer(size) {
1427 Ok((wgpu_staging_buffer, ptr)) => Some(
1428 CoreQueueWriteBuffer {
1429 wgpu_staging_buffer,
1430 mapping: CoreBufferMappedRange {
1431 ptr,
1432 size: size.get() as usize,
1433 },
1434 }
1435 .into(),
1436 ),
1437 Err(err) => {
1438 self.wgpu_queue
1439 .device()
1440 .handle_error_nolabel(err, "Queue::write_buffer_with");
1441 None
1442 }
1443 }
1444 }
1445
1446 fn validate_write_buffer(
1447 &self,
1448 buffer: &dispatch::DispatchBuffer,
1449 offset: wgt::BufferAddress,
1450 size: wgt::BufferSize,
1451 ) -> Option<()> {
1452 let buffer = buffer.as_core();
1453
1454 match self
1455 .wgpu_queue
1456 .validate_write_buffer(buffer.wgpu_buffer.clone(), offset, size)
1457 {
1458 Ok(()) => Some(()),
1459 Err(err) => {
1460 self.wgpu_queue
1461 .device()
1462 .handle_error_nolabel(err, "Queue::write_buffer_with");
1463 None
1464 }
1465 }
1466 }
1467
1468 fn write_staging_buffer(
1469 &self,
1470 buffer: &dispatch::DispatchBuffer,
1471 offset: crate::BufferAddress,
1472 staging_buffer: dispatch::DispatchQueueWriteBuffer,
1473 ) {
1474 let buffer = buffer.as_core();
1475 let staging_buffer = {
1476 #[allow(
1477 clippy::allow_attributes,
1478 unreachable_patterns,
1479 reason = "features may be disabled"
1480 )]
1481 match staging_buffer {
1482 dispatch::DispatchQueueWriteBuffer::Core(value) => value,
1483 _ => panic!(concat!(
1484 stringify!(DispatchQueueWriteBuffer),
1485 " is not core"
1486 )),
1487 }
1488 };
1489
1490 match self.wgpu_queue.write_staging_buffer(
1491 buffer.wgpu_buffer.clone(),
1492 offset,
1493 staging_buffer.wgpu_staging_buffer,
1494 ) {
1495 Ok(()) => (),
1496 Err(err) => {
1497 self.wgpu_queue
1498 .device()
1499 .handle_error_nolabel(err, "Queue::write_buffer_with");
1500 }
1501 }
1502 }
1503
1504 fn write_texture(
1505 &self,
1506 texture: crate::TexelCopyTextureInfo<'_>,
1507 data: &[u8],
1508 data_layout: crate::TexelCopyBufferLayout,
1509 size: crate::Extent3d,
1510 ) {
1511 self.wgpu_queue
1512 .write_texture(map_texture_copy_view(texture), data, &data_layout, &size);
1513 }
1514
1515 #[cfg(web)]
1518 #[cfg_attr(not(webgl), expect(unused_variables))]
1519 fn copy_external_image_to_texture(
1520 &self,
1521 source: &crate::CopyExternalImageSourceInfo,
1522 dest: crate::CopyExternalImageDestInfo<&crate::api::Texture>,
1523 size: crate::Extent3d,
1524 ) {
1525 #[cfg(webgl)]
1526 match self.wgpu_queue.copy_external_image_to_texture(
1527 source,
1528 map_texture_tagged_copy_view(dest),
1529 size,
1530 ) {
1531 Ok(()) => (),
1532 Err(err) => self
1533 .wgpu_queue
1534 .device()
1535 .handle_error_nolabel(err, "Queue::copy_external_image_to_texture"),
1536 }
1537 }
1538
1539 fn submit(
1540 &self,
1541 command_buffers: &mut dyn Iterator<Item = dispatch::DispatchCommandBuffer>,
1542 ) -> u64 {
1543 let temp_command_buffers = command_buffers.collect::<SmallVec<[_; 4]>>();
1544 let command_buffers = temp_command_buffers
1545 .iter()
1546 .map(|cmdbuf| cmdbuf.as_core().wgpu_command_buffer.clone())
1547 .collect::<SmallVec<[_; 4]>>();
1548
1549 let index = self.wgpu_queue.submit(&command_buffers);
1550
1551 drop(temp_command_buffers);
1552
1553 index
1554 }
1555
1556 fn get_timestamp_period(&self) -> f32 {
1557 self.wgpu_queue.get_timestamp_period()
1558 }
1559
1560 fn on_submitted_work_done(&self, callback: dispatch::BoxSubmittedWorkDoneCallback) {
1561 self.wgpu_queue.on_submitted_work_done(callback);
1562 }
1563
1564 fn compact_blas(&self, blas: &dispatch::DispatchBlas) -> (Option<u64>, dispatch::DispatchBlas) {
1565 let (wgpu_blas, error) = self.wgpu_queue.compact_blas(&blas.as_core().wgpu_blas);
1566
1567 if let Some(cause) = error {
1568 self.wgpu_queue
1569 .device()
1570 .handle_error_nolabel(cause, "Queue::compact_blas");
1571 }
1572 (wgpu_blas.handle(), CoreBlas { wgpu_blas }.into())
1573 }
1574
1575 fn present(&self, detail: &dispatch::DispatchSurfaceOutputDetail) {
1576 let detail = detail.as_core();
1577 match detail.wgpu_surface.present() {
1578 Ok(_status) => (),
1579 Err(err) => {
1580 self.wgpu_queue
1581 .device()
1582 .handle_error_nolabel(err, "Queue::present");
1583 }
1584 }
1585 }
1586}
1587
1588impl dispatch::ShaderModuleInterface for CoreShaderModule {
1589 fn get_compilation_info(&self) -> Pin<Box<dyn dispatch::ShaderCompilationInfoFuture>> {
1590 Box::pin(ready(self.wgpu_shader_module.compilation_info().clone()))
1591 }
1592}
1593
1594impl dispatch::BindGroupLayoutInterface for CoreBindGroupLayout {}
1595
1596impl dispatch::BindGroupInterface for CoreBindGroup {}
1597
1598impl dispatch::TextureViewInterface for CoreTextureView {}
1599
1600impl dispatch::ExternalTextureInterface for CoreExternalTexture {
1601 fn destroy(&self) {
1602 self.wgpu_external_texture.destroy();
1603 }
1604}
1605
1606impl dispatch::SamplerInterface for CoreSampler {}
1607
1608impl dispatch::BufferInterface for CoreBuffer {
1609 fn map_async(
1610 &self,
1611 mode: crate::MapMode,
1612 range: Range<crate::BufferAddress>,
1613 callback: dispatch::BufferMapCallback,
1614 ) {
1615 let operation = wgc::resource::BufferMapOperation {
1616 host: match mode {
1617 MapMode::Read => wgc::device::HostMap::Read,
1618 MapMode::Write => wgc::device::HostMap::Write,
1619 },
1620 callback: Some(Box::new(|status| {
1621 let res = status.map_err(|_| crate::BufferAsyncError);
1622 callback(res);
1623 })),
1624 };
1625
1626 self.wgpu_buffer
1627 .map_async(range.start, Some(range.end - range.start), operation);
1628 }
1629
1630 fn get_mapped_range(
1631 &self,
1632 sub_range: Range<crate::BufferAddress>,
1633 ) -> Result<dispatch::DispatchBufferMappedRange, crate::MapRangeError> {
1634 let size = sub_range.end - sub_range.start;
1635 self.wgpu_buffer
1636 .get_mapped_range(sub_range.start, Some(size))
1637 .map(|(ptr, size)| {
1638 CoreBufferMappedRange {
1639 ptr,
1640 size: size as usize,
1641 }
1642 .into()
1643 })
1644 .map_err(|err| crate::MapRangeError(format_error(&err)))
1645 }
1646
1647 fn unmap(&self) {
1648 self.wgpu_buffer.unmap();
1649 }
1650
1651 fn destroy(&self) {
1652 self.wgpu_buffer.destroy();
1653 }
1654
1655 fn size(&self) -> crate::BufferAddress {
1656 self.wgpu_buffer.size()
1657 }
1658
1659 fn usage(&self) -> crate::BufferUsages {
1660 self.wgpu_buffer.usage()
1661 }
1662}
1663
1664impl dispatch::TextureInterface for CoreTexture {
1665 fn create_view(
1666 &self,
1667 desc: &crate::TextureViewDescriptor<'_>,
1668 ) -> dispatch::DispatchTextureView {
1669 let descriptor = wgc::resource::TextureViewDescriptor {
1670 label: desc.label.map(Borrowed),
1671 format: desc.format,
1672 dimension: desc.dimension,
1673 usage: desc.usage,
1674 range: wgt::ImageSubresourceRange {
1675 aspect: desc.aspect,
1676 base_mip_level: desc.base_mip_level,
1677 mip_level_count: desc.mip_level_count,
1678 base_array_layer: desc.base_array_layer,
1679 array_layer_count: desc.array_layer_count,
1680 },
1681 swizzle: desc.swizzle,
1682 };
1683 let wgpu_texture_view = self.wgpu_texture.create_view(&descriptor);
1684 CoreTextureView { wgpu_texture_view }.into()
1685 }
1686
1687 fn destroy(&self) {
1688 self.wgpu_texture.destroy();
1689 }
1690
1691 fn size(&self) -> wgt::Extent3d {
1692 self.wgpu_texture.descriptor().size
1693 }
1694
1695 fn mip_level_count(&self) -> u32 {
1696 self.wgpu_texture.descriptor().mip_level_count
1697 }
1698
1699 fn sample_count(&self) -> u32 {
1700 self.wgpu_texture.descriptor().sample_count
1701 }
1702
1703 fn dimension(&self) -> wgt::TextureDimension {
1704 self.wgpu_texture.descriptor().dimension
1705 }
1706
1707 fn format(&self) -> wgt::TextureFormat {
1708 self.wgpu_texture.descriptor().format
1709 }
1710
1711 fn usage(&self) -> wgt::TextureUsages {
1712 self.wgpu_texture.descriptor().usage
1713 }
1714
1715 unsafe fn mark_externally_initialized(&self) {
1716 unsafe { self.wgpu_texture.mark_externally_initialized() }
1717 }
1718}
1719
1720impl dispatch::BlasInterface for CoreBlas {
1721 fn prepare_compact_async(&self, callback: BlasCompactCallback) {
1722 let callback: Option<wgc::resource::BlasCompactCallback> =
1723 Some(Box::new(|status: BlasPrepareCompactResult| {
1724 let res = status.map_err(|_| crate::BlasAsyncError);
1725 callback(res);
1726 }));
1727
1728 match self.wgpu_blas.prepare_compact_async(callback) {
1729 Ok(_) => (),
1730 Err(cause) => self
1731 .wgpu_blas
1732 .device()
1733 .handle_error_nolabel(cause, "Blas::prepare_compact_async"),
1734 }
1735 }
1736
1737 fn ready_for_compaction(&self) -> bool {
1738 match self.wgpu_blas.ready_for_compaction() {
1739 Ok(ready) => ready,
1740 Err(cause) => {
1741 self.wgpu_blas
1742 .device()
1743 .handle_error_nolabel(cause, "Blas::ready_for_compaction");
1744 false
1746 }
1747 }
1748 }
1749}
1750
1751impl dispatch::TlasInterface for CoreTlas {}
1752
1753impl dispatch::QuerySetInterface for CoreQuerySet {
1754 fn destroy(&self) {
1755 self.wgpu_query_set.destroy();
1756 }
1757
1758 fn ty(&self) -> crate::QueryType {
1759 self.wgpu_query_set.descriptor().ty
1760 }
1761
1762 fn count(&self) -> u32 {
1763 self.wgpu_query_set.descriptor().count
1764 }
1765}
1766
1767impl dispatch::PipelineLayoutInterface for CorePipelineLayout {}
1768
1769impl dispatch::RenderPipelineInterface for CoreRenderPipeline {
1770 fn get_bind_group_layout(&self, index: u32) -> dispatch::DispatchBindGroupLayout {
1771 let wgpu_bind_group_layout = self.wgpu_render_pipeline.get_bind_group_layout(index);
1772 CoreBindGroupLayout {
1773 wgpu_bind_group_layout,
1774 }
1775 .into()
1776 }
1777}
1778
1779impl dispatch::ComputePipelineInterface for CoreComputePipeline {
1780 fn get_bind_group_layout(&self, index: u32) -> dispatch::DispatchBindGroupLayout {
1781 let wgpu_bind_group_layout = self.wgpu_compute_pipeline.get_bind_group_layout(index);
1782 CoreBindGroupLayout {
1783 wgpu_bind_group_layout,
1784 }
1785 .into()
1786 }
1787}
1788
1789impl dispatch::PipelineCacheInterface for CorePipelineCache {
1790 fn get_data(&self) -> Option<Vec<u8>> {
1791 self.wgpu_pipeline_cache.get_data()
1792 }
1793}
1794
1795impl dispatch::CommandEncoderInterface for CoreCommandEncoder {
1796 fn copy_buffer_to_buffer(
1797 &self,
1798 source: &dispatch::DispatchBuffer,
1799 source_offset: crate::BufferAddress,
1800 destination: &dispatch::DispatchBuffer,
1801 destination_offset: crate::BufferAddress,
1802 copy_size: Option<crate::BufferAddress>,
1803 ) {
1804 let source = source.as_core();
1805 let destination = destination.as_core();
1806
1807 self.wgpu_command_encoder.copy_buffer_to_buffer(
1808 source.wgpu_buffer.clone(),
1809 source_offset,
1810 destination.wgpu_buffer.clone(),
1811 destination_offset,
1812 copy_size,
1813 )
1814 }
1815
1816 fn copy_buffer_to_texture(
1817 &self,
1818 source: crate::TexelCopyBufferInfo<'_>,
1819 destination: crate::TexelCopyTextureInfo<'_>,
1820 copy_size: crate::Extent3d,
1821 ) {
1822 self.wgpu_command_encoder.copy_buffer_to_texture(
1823 &map_buffer_copy_view(source),
1824 &map_texture_copy_view(destination),
1825 ©_size,
1826 )
1827 }
1828
1829 fn copy_texture_to_buffer(
1830 &self,
1831 source: crate::TexelCopyTextureInfo<'_>,
1832 destination: crate::TexelCopyBufferInfo<'_>,
1833 copy_size: crate::Extent3d,
1834 ) {
1835 self.wgpu_command_encoder.copy_texture_to_buffer(
1836 &map_texture_copy_view(source),
1837 &map_buffer_copy_view(destination),
1838 ©_size,
1839 );
1840 }
1841
1842 fn copy_texture_to_texture(
1843 &self,
1844 source: crate::TexelCopyTextureInfo<'_>,
1845 destination: crate::TexelCopyTextureInfo<'_>,
1846 copy_size: crate::Extent3d,
1847 ) {
1848 self.wgpu_command_encoder.copy_texture_to_texture(
1849 &map_texture_copy_view(source),
1850 &map_texture_copy_view(destination),
1851 ©_size,
1852 );
1853 }
1854
1855 fn begin_compute_pass(
1856 &self,
1857 desc: &crate::ComputePassDescriptor<'_>,
1858 ) -> dispatch::DispatchComputePass {
1859 let timestamp_writes =
1860 desc.timestamp_writes
1861 .as_ref()
1862 .map(|tw| wgc::command::PassTimestampWrites {
1863 query_set: tw.query_set.inner.as_core().wgpu_query_set.clone(),
1864 beginning_of_pass_write_index: tw.beginning_of_pass_write_index,
1865 end_of_pass_write_index: tw.end_of_pass_write_index,
1866 });
1867
1868 let pass =
1869 self.wgpu_command_encoder
1870 .begin_compute_pass(&wgc::command::ComputePassDescriptor {
1871 label: desc.label.map(Borrowed),
1872 timestamp_writes,
1873 });
1874
1875 CoreComputePass {
1876 pass,
1877 id: crate::cmp::Identifier::create(),
1878 }
1879 .into()
1880 }
1881
1882 fn begin_render_pass(
1883 &self,
1884 desc: &crate::RenderPassDescriptor<'_>,
1885 ) -> dispatch::DispatchRenderPass {
1886 let colors = desc
1887 .color_attachments
1888 .iter()
1889 .map(|ca| {
1890 ca.as_ref()
1891 .map(|at| wgc::command::RenderPassColorAttachment {
1892 view: at.view.inner.as_core().wgpu_texture_view.clone(),
1893 depth_slice: at.depth_slice,
1894 resolve_target: at
1895 .resolve_target
1896 .map(|view| view.inner.as_core().wgpu_texture_view.clone()),
1897 load_op: at.ops.load,
1898 store_op: at.ops.store,
1899 })
1900 })
1901 .collect::<Vec<_>>();
1902
1903 let depth_stencil = desc.depth_stencil_attachment.as_ref().map(|dsa| {
1904 wgc::command::RenderPassDepthStencilAttachment {
1905 view: dsa.view.inner.as_core().wgpu_texture_view.clone(),
1906 depth: map_pass_channel(dsa.depth_ops.as_ref()),
1907 stencil: map_pass_channel(dsa.stencil_ops.as_ref()),
1908 }
1909 });
1910
1911 let timestamp_writes =
1912 desc.timestamp_writes
1913 .as_ref()
1914 .map(|tw| wgc::command::PassTimestampWrites {
1915 query_set: tw.query_set.inner.as_core().wgpu_query_set.clone(),
1916 beginning_of_pass_write_index: tw.beginning_of_pass_write_index,
1917 end_of_pass_write_index: tw.end_of_pass_write_index,
1918 });
1919
1920 let pass = self.wgpu_command_encoder.begin_render_pass(
1921 wgc::command::ResolvedRenderPassDescriptor {
1922 label: desc.label.map(Borrowed),
1923 timestamp_writes,
1924 color_attachments: Borrowed(&colors),
1925 depth_stencil_attachment: depth_stencil,
1926 occlusion_query_set: desc
1927 .occlusion_query_set
1928 .map(|qs| qs.inner.as_core().wgpu_query_set.clone()),
1929 multiview_mask: desc.multiview_mask,
1930 },
1931 );
1932
1933 CoreRenderPass {
1934 pass,
1935 id: crate::cmp::Identifier::create(),
1936 }
1937 .into()
1938 }
1939
1940 fn finish(&mut self) -> dispatch::DispatchCommandBuffer {
1941 let descriptor = wgt::CommandBufferDescriptor::default();
1942 let wgpu_command_buffer = self.wgpu_command_encoder.finish(&descriptor);
1943 CoreCommandBuffer {
1944 wgpu_command_buffer,
1945 }
1946 .into()
1947 }
1948
1949 fn clear_texture(
1950 &self,
1951 texture: &dispatch::DispatchTexture,
1952 subresource_range: &crate::ImageSubresourceRange,
1953 ) {
1954 let texture = texture.as_core();
1955
1956 self.wgpu_command_encoder
1957 .clear_texture(texture.wgpu_texture.clone(), subresource_range)
1958 }
1959
1960 fn clear_buffer(
1961 &self,
1962 buffer: &dispatch::DispatchBuffer,
1963 offset: crate::BufferAddress,
1964 size: Option<crate::BufferAddress>,
1965 ) {
1966 let buffer = buffer.as_core();
1967
1968 self.wgpu_command_encoder
1969 .clear_buffer(buffer.wgpu_buffer.clone(), offset, size)
1970 }
1971
1972 fn insert_debug_marker(&self, label: &str) {
1973 self.wgpu_command_encoder.insert_debug_marker(label)
1974 }
1975
1976 fn push_debug_group(&self, label: &str) {
1977 self.wgpu_command_encoder.push_debug_group(label)
1978 }
1979
1980 fn pop_debug_group(&self) {
1981 self.wgpu_command_encoder.pop_debug_group()
1982 }
1983
1984 fn write_timestamp(&self, query_set: &dispatch::DispatchQuerySet, query_index: u32) {
1985 let query_set = query_set.as_core();
1986
1987 self.wgpu_command_encoder
1988 .write_timestamp(query_set.wgpu_query_set.clone(), query_index)
1989 }
1990
1991 fn resolve_query_set(
1992 &self,
1993 query_set: &dispatch::DispatchQuerySet,
1994 first_query: u32,
1995 query_count: u32,
1996 destination: &dispatch::DispatchBuffer,
1997 destination_offset: crate::BufferAddress,
1998 ) {
1999 let query_set = query_set.as_core();
2000 let destination = destination.as_core();
2001
2002 self.wgpu_command_encoder.resolve_query_set(
2003 query_set.wgpu_query_set.clone(),
2004 first_query,
2005 query_count,
2006 destination.wgpu_buffer.clone(),
2007 destination_offset,
2008 );
2009 }
2010
2011 fn mark_acceleration_structures_built<'a>(
2012 &self,
2013 blas: &mut dyn Iterator<Item = &'a Blas>,
2014 tlas: &mut dyn Iterator<Item = &'a Tlas>,
2015 ) {
2016 let blas = blas
2017 .map(|b| b.inner.as_core().wgpu_blas.clone())
2018 .collect::<SmallVec<[_; 4]>>();
2019 let tlas = tlas
2020 .map(|t| t.inner.as_core().wgpu_tlas.clone())
2021 .collect::<SmallVec<[_; 4]>>();
2022 self.wgpu_command_encoder
2023 .mark_acceleration_structures_built(&blas, &tlas)
2024 }
2025
2026 fn build_acceleration_structures<'a>(
2027 &self,
2028 blas: &mut dyn Iterator<Item = &'a crate::BlasBuildEntry<'a>>,
2029 tlas: &mut dyn Iterator<Item = &'a crate::Tlas>,
2030 ) {
2031 let blas = blas.map(|e: &crate::BlasBuildEntry<'_>| {
2032 let geometries = match e.geometry {
2033 crate::BlasGeometries::TriangleGeometries(ref triangle_geometries) => {
2034 let iter = triangle_geometries.iter().map(|tg| {
2035 wgc::ray_tracing::BlasTriangleGeometry {
2036 vertex_buffer: tg.vertex_buffer.inner.as_core().wgpu_buffer.clone(),
2037 index_buffer: tg
2038 .index_buffer
2039 .map(|buf| buf.inner.as_core().wgpu_buffer.clone()),
2040 transform_buffer: tg
2041 .transform_buffer
2042 .map(|buf| buf.inner.as_core().wgpu_buffer.clone()),
2043 size: tg.size,
2044 transform_buffer_offset: tg.transform_buffer_offset,
2045 first_vertex: tg.first_vertex,
2046 vertex_stride: tg.vertex_stride,
2047 first_index: tg.first_index,
2048 }
2049 });
2050 wgc::ray_tracing::BlasGeometries::TriangleGeometries(Box::new(iter))
2051 }
2052 crate::BlasGeometries::AabbGeometries(ref aabb_geometries) => {
2053 let iter =
2054 aabb_geometries
2055 .iter()
2056 .map(|ag| wgc::ray_tracing::BlasAabbGeometry {
2057 aabb_buffer: ag.aabb_buffer.inner.as_core().wgpu_buffer.clone(),
2058 stride: ag.stride,
2059 size: ag.size,
2060 primitive_offset: ag.primitive_offset,
2061 });
2062 wgc::ray_tracing::BlasGeometries::AabbGeometries(Box::new(iter))
2063 }
2064 };
2065 wgc::ray_tracing::BlasBuildEntry {
2066 blas: e.blas.inner.as_core().wgpu_blas.clone(),
2067 geometries,
2068 }
2069 });
2070
2071 let tlas = tlas.into_iter().map(|e| {
2072 let instances = e
2073 .instances
2074 .iter()
2075 .map(|instance: &Option<crate::TlasInstance>| {
2076 instance
2077 .as_ref()
2078 .map(|instance| wgc::ray_tracing::ArcTlasInstance {
2079 blas: instance.blas.as_core().wgpu_blas.clone(),
2080 transform: instance.transform,
2081 custom_data: instance.custom_data,
2082 mask: instance.mask,
2083 })
2084 })
2085 .collect();
2086 wgc::ray_tracing::ArcTlasPackage {
2087 tlas: e.inner.as_core().wgpu_tlas.clone(),
2088 instances,
2089 lowest_unmodified: e.lowest_unmodified,
2090 }
2091 });
2092
2093 self.wgpu_command_encoder
2094 .build_acceleration_structures(blas, tlas.collect())
2095 }
2096
2097 fn transition_resources<'a>(
2098 &mut self,
2099 buffer_transitions: &mut dyn Iterator<
2100 Item = wgt::BufferTransition<&'a dispatch::DispatchBuffer>,
2101 >,
2102 texture_transitions: &mut dyn Iterator<
2103 Item = wgt::TextureTransition<&'a dispatch::DispatchTexture>,
2104 >,
2105 ) {
2106 self.wgpu_command_encoder.transition_resources(
2107 buffer_transitions.map(|t| wgt::BufferTransition {
2108 buffer: t.buffer.as_core().wgpu_buffer.clone(),
2109 state: t.state,
2110 }),
2111 texture_transitions.map(|t| wgt::TextureTransition {
2112 texture: t.texture.as_core().wgpu_texture.clone(),
2113 selector: t.selector.clone(),
2114 state: t.state,
2115 }),
2116 );
2117 }
2118}
2119
2120impl dispatch::CommandBufferInterface for CoreCommandBuffer {}
2121
2122impl dispatch::ComputePassInterface for CoreComputePass {
2123 fn set_pipeline(&mut self, pipeline: &dispatch::DispatchComputePipeline) {
2124 let pipeline = pipeline.as_core();
2125
2126 self.pass
2127 .set_pipeline(pipeline.wgpu_compute_pipeline.clone());
2128 }
2129
2130 fn set_bind_group(
2131 &mut self,
2132 index: u32,
2133 bind_group: Option<&dispatch::DispatchBindGroup>,
2134 offsets: &[crate::DynamicOffset],
2135 ) {
2136 let bg = bind_group.map(|bg| bg.as_core().wgpu_bind_group.clone());
2137
2138 self.pass.set_bind_group(index, bg, offsets);
2139 }
2140
2141 fn set_immediates(&mut self, offset: u32, data: &[u8]) {
2142 self.pass.set_immediates(offset, data);
2143 }
2144
2145 fn insert_debug_marker(&mut self, label: &str) {
2146 self.pass.insert_debug_marker(label, 0);
2147 }
2148
2149 fn push_debug_group(&mut self, group_label: &str) {
2150 self.pass.push_debug_group(group_label, 0);
2151 }
2152
2153 fn pop_debug_group(&mut self) {
2154 self.pass.pop_debug_group();
2155 }
2156
2157 fn write_timestamp(&mut self, query_set: &dispatch::DispatchQuerySet, query_index: u32) {
2158 let query_set = query_set.as_core();
2159
2160 self.pass
2161 .write_timestamp(query_set.wgpu_query_set.clone(), query_index);
2162 }
2163
2164 fn begin_pipeline_statistics_query(
2165 &mut self,
2166 query_set: &dispatch::DispatchQuerySet,
2167 query_index: u32,
2168 ) {
2169 let query_set = query_set.as_core();
2170
2171 self.pass
2172 .begin_pipeline_statistics_query(query_set.wgpu_query_set.clone(), query_index);
2173 }
2174
2175 fn end_pipeline_statistics_query(&mut self) {
2176 self.pass.end_pipeline_statistics_query();
2177 }
2178
2179 fn dispatch_workgroups(&mut self, x: u32, y: u32, z: u32) {
2180 self.pass.dispatch_workgroups(x, y, z);
2181 }
2182
2183 fn dispatch_workgroups_indirect(
2184 &mut self,
2185 indirect_buffer: &dispatch::DispatchBuffer,
2186 indirect_offset: crate::BufferAddress,
2187 ) {
2188 let indirect_buffer = indirect_buffer.as_core();
2189
2190 self.pass
2191 .dispatch_workgroups_indirect(indirect_buffer.wgpu_buffer.clone(), indirect_offset);
2192 }
2193
2194 fn transition_resources<'a>(
2195 &mut self,
2196 buffer_transitions: &mut dyn Iterator<
2197 Item = wgt::BufferTransition<&'a dispatch::DispatchBuffer>,
2198 >,
2199 texture_transitions: &mut dyn Iterator<
2200 Item = wgt::TextureTransition<&'a dispatch::DispatchTextureView>,
2201 >,
2202 ) {
2203 self.pass.transition_resources(
2204 buffer_transitions.map(|t| wgt::BufferTransition {
2205 buffer: t.buffer.as_core().wgpu_buffer.clone(),
2206 state: t.state,
2207 }),
2208 texture_transitions.map(|t| wgt::TextureTransition {
2209 texture: t.texture.as_core().wgpu_texture_view.clone(),
2210 selector: t.selector.clone(),
2211 state: t.state,
2212 }),
2213 );
2214 }
2215}
2216
2217impl Drop for CoreComputePass {
2218 fn drop(&mut self) {
2219 self.pass.end();
2220 }
2221}
2222
2223impl dispatch::RenderPassInterface for CoreRenderPass {
2224 fn set_pipeline(&mut self, pipeline: &dispatch::DispatchRenderPipeline) {
2225 let pipeline = pipeline.as_core();
2226
2227 self.pass
2228 .set_pipeline(pipeline.wgpu_render_pipeline.clone());
2229 }
2230
2231 fn set_bind_group(
2232 &mut self,
2233 index: u32,
2234 bind_group: Option<&dispatch::DispatchBindGroup>,
2235 offsets: &[crate::DynamicOffset],
2236 ) {
2237 let bg = bind_group.map(|bg| bg.as_core().wgpu_bind_group.clone());
2238
2239 self.pass.set_bind_group(index, bg, offsets);
2240 }
2241
2242 fn set_index_buffer(
2243 &mut self,
2244 buffer: &dispatch::DispatchBuffer,
2245 index_format: crate::IndexFormat,
2246 offset: crate::BufferAddress,
2247 size: Option<crate::BufferAddress>,
2248 ) {
2249 let buffer = buffer.as_core();
2250
2251 self.pass
2252 .set_index_buffer(buffer.wgpu_buffer.clone(), index_format, offset, size)
2253 }
2254
2255 fn set_vertex_buffer(
2256 &mut self,
2257 slot: u32,
2258 buffer: Option<&dispatch::DispatchBuffer>,
2259 offset: crate::BufferAddress,
2260 size: Option<crate::BufferAddress>,
2261 ) {
2262 let buffer = buffer.map(|buffer| buffer.as_core().wgpu_buffer.clone());
2263
2264 self.pass.set_vertex_buffer(slot, buffer, offset, size);
2265 }
2266
2267 fn set_immediates(&mut self, offset: u32, data: &[u8]) {
2268 self.pass.set_immediates(offset, data);
2269 }
2270
2271 fn set_blend_constant(&mut self, color: crate::Color) {
2272 self.pass.set_blend_constant(color);
2273 }
2274
2275 fn set_scissor_rect(&mut self, x: u32, y: u32, width: u32, height: u32) {
2276 self.pass.set_scissor_rect(x, y, width, height);
2277 }
2278
2279 fn set_viewport(
2280 &mut self,
2281 x: f32,
2282 y: f32,
2283 width: f32,
2284 height: f32,
2285 min_depth: f32,
2286 max_depth: f32,
2287 ) {
2288 self.pass
2289 .set_viewport(x, y, width, height, min_depth, max_depth);
2290 }
2291
2292 fn set_stencil_reference(&mut self, reference: u32) {
2293 self.pass.set_stencil_reference(reference);
2294 }
2295
2296 fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>) {
2297 self.pass.draw(
2298 vertices.end - vertices.start,
2299 instances.end - instances.start,
2300 vertices.start,
2301 instances.start,
2302 );
2303 }
2304
2305 fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>) {
2306 self.pass.draw_indexed(
2307 indices.end - indices.start,
2308 instances.end - instances.start,
2309 indices.start,
2310 base_vertex,
2311 instances.start,
2312 );
2313 }
2314
2315 fn draw_mesh_tasks(&mut self, group_count_x: u32, group_count_y: u32, group_count_z: u32) {
2316 self.pass
2317 .draw_mesh_tasks(group_count_x, group_count_y, group_count_z);
2318 }
2319
2320 fn draw_indirect(
2321 &mut self,
2322 indirect_buffer: &dispatch::DispatchBuffer,
2323 indirect_offset: crate::BufferAddress,
2324 ) {
2325 let indirect_buffer = indirect_buffer.as_core();
2326
2327 self.pass
2328 .draw_indirect(indirect_buffer.wgpu_buffer.clone(), indirect_offset);
2329 }
2330
2331 fn draw_indexed_indirect(
2332 &mut self,
2333 indirect_buffer: &dispatch::DispatchBuffer,
2334 indirect_offset: crate::BufferAddress,
2335 ) {
2336 let indirect_buffer = indirect_buffer.as_core();
2337
2338 self.pass
2339 .draw_indexed_indirect(indirect_buffer.wgpu_buffer.clone(), indirect_offset);
2340 }
2341
2342 fn draw_mesh_tasks_indirect(
2343 &mut self,
2344 indirect_buffer: &dispatch::DispatchBuffer,
2345 indirect_offset: crate::BufferAddress,
2346 ) {
2347 let indirect_buffer = indirect_buffer.as_core();
2348
2349 self.pass
2350 .draw_mesh_tasks_indirect(indirect_buffer.wgpu_buffer.clone(), indirect_offset);
2351 }
2352
2353 fn multi_draw_indirect(
2354 &mut self,
2355 indirect_buffer: &dispatch::DispatchBuffer,
2356 indirect_offset: crate::BufferAddress,
2357 count: u32,
2358 ) {
2359 let indirect_buffer = indirect_buffer.as_core();
2360
2361 self.pass
2362 .multi_draw_indirect(indirect_buffer.wgpu_buffer.clone(), indirect_offset, count);
2363 }
2364
2365 fn multi_draw_indexed_indirect(
2366 &mut self,
2367 indirect_buffer: &dispatch::DispatchBuffer,
2368 indirect_offset: crate::BufferAddress,
2369 count: u32,
2370 ) {
2371 let indirect_buffer = indirect_buffer.as_core();
2372
2373 self.pass.multi_draw_indexed_indirect(
2374 indirect_buffer.wgpu_buffer.clone(),
2375 indirect_offset,
2376 count,
2377 );
2378 }
2379
2380 fn multi_draw_mesh_tasks_indirect(
2381 &mut self,
2382 indirect_buffer: &dispatch::DispatchBuffer,
2383 indirect_offset: crate::BufferAddress,
2384 count: u32,
2385 ) {
2386 let indirect_buffer = indirect_buffer.as_core();
2387
2388 self.pass.multi_draw_mesh_tasks_indirect(
2389 indirect_buffer.wgpu_buffer.clone(),
2390 indirect_offset,
2391 count,
2392 );
2393 }
2394
2395 fn multi_draw_indirect_count(
2396 &mut self,
2397 indirect_buffer: &dispatch::DispatchBuffer,
2398 indirect_offset: crate::BufferAddress,
2399 count_buffer: &dispatch::DispatchBuffer,
2400 count_buffer_offset: crate::BufferAddress,
2401 max_count: u32,
2402 ) {
2403 let indirect_buffer = indirect_buffer.as_core();
2404 let count_buffer = count_buffer.as_core();
2405
2406 self.pass.multi_draw_indirect_count(
2407 indirect_buffer.wgpu_buffer.clone(),
2408 indirect_offset,
2409 count_buffer.wgpu_buffer.clone(),
2410 count_buffer_offset,
2411 max_count,
2412 );
2413 }
2414
2415 fn multi_draw_indexed_indirect_count(
2416 &mut self,
2417 indirect_buffer: &dispatch::DispatchBuffer,
2418 indirect_offset: crate::BufferAddress,
2419 count_buffer: &dispatch::DispatchBuffer,
2420 count_buffer_offset: crate::BufferAddress,
2421 max_count: u32,
2422 ) {
2423 let indirect_buffer = indirect_buffer.as_core();
2424 let count_buffer = count_buffer.as_core();
2425
2426 self.pass.multi_draw_indexed_indirect_count(
2427 indirect_buffer.wgpu_buffer.clone(),
2428 indirect_offset,
2429 count_buffer.wgpu_buffer.clone(),
2430 count_buffer_offset,
2431 max_count,
2432 );
2433 }
2434
2435 fn multi_draw_mesh_tasks_indirect_count(
2436 &mut self,
2437 indirect_buffer: &dispatch::DispatchBuffer,
2438 indirect_offset: crate::BufferAddress,
2439 count_buffer: &dispatch::DispatchBuffer,
2440 count_buffer_offset: crate::BufferAddress,
2441 max_count: u32,
2442 ) {
2443 let indirect_buffer = indirect_buffer.as_core();
2444 let count_buffer = count_buffer.as_core();
2445
2446 self.pass.multi_draw_mesh_tasks_indirect_count(
2447 indirect_buffer.wgpu_buffer.clone(),
2448 indirect_offset,
2449 count_buffer.wgpu_buffer.clone(),
2450 count_buffer_offset,
2451 max_count,
2452 );
2453 }
2454
2455 fn insert_debug_marker(&mut self, label: &str) {
2456 self.pass.insert_debug_marker(label, 0);
2457 }
2458
2459 fn push_debug_group(&mut self, group_label: &str) {
2460 self.pass.push_debug_group(group_label, 0);
2461 }
2462
2463 fn pop_debug_group(&mut self) {
2464 self.pass.pop_debug_group();
2465 }
2466
2467 fn write_timestamp(&mut self, query_set: &dispatch::DispatchQuerySet, query_index: u32) {
2468 let query_set = query_set.as_core();
2469
2470 self.pass
2471 .write_timestamp(query_set.wgpu_query_set.clone(), query_index);
2472 }
2473
2474 fn begin_occlusion_query(&mut self, query_index: u32) {
2475 self.pass.begin_occlusion_query(query_index);
2476 }
2477
2478 fn end_occlusion_query(&mut self) {
2479 self.pass.end_occlusion_query();
2480 }
2481
2482 fn begin_pipeline_statistics_query(
2483 &mut self,
2484 query_set: &dispatch::DispatchQuerySet,
2485 query_index: u32,
2486 ) {
2487 let query_set = query_set.as_core();
2488
2489 self.pass
2490 .begin_pipeline_statistics_query(query_set.wgpu_query_set.clone(), query_index);
2491 }
2492
2493 fn end_pipeline_statistics_query(&mut self) {
2494 self.pass.end_pipeline_statistics_query();
2495 }
2496
2497 fn execute_bundles(
2498 &mut self,
2499 render_bundles: &mut dyn Iterator<Item = &dispatch::DispatchRenderBundle>,
2500 ) {
2501 let temp_render_bundles = render_bundles
2502 .map(|rb| rb.as_core().wgpu_render_bundle.clone())
2503 .collect::<SmallVec<[_; 4]>>();
2504 self.pass.execute_bundles(&temp_render_bundles);
2505 }
2506}
2507
2508impl Drop for CoreRenderPass {
2509 fn drop(&mut self) {
2510 self.pass.end()
2511 }
2512}
2513
2514impl dispatch::RenderBundleEncoderInterface for CoreRenderBundleEncoder {
2515 fn set_pipeline(&mut self, pipeline: &dispatch::DispatchRenderPipeline) {
2516 let pipeline = pipeline.as_core();
2517
2518 self.encoder
2519 .set_pipeline(pipeline.wgpu_render_pipeline.clone())
2520 }
2521
2522 fn set_bind_group(
2523 &mut self,
2524 index: u32,
2525 bind_group: Option<&dispatch::DispatchBindGroup>,
2526 offsets: &[crate::DynamicOffset],
2527 ) {
2528 let bg = bind_group.map(|bg| bg.as_core().wgpu_bind_group.clone());
2529
2530 self.encoder.set_bind_group(index, bg, offsets);
2531 }
2532
2533 fn set_index_buffer(
2534 &mut self,
2535 buffer: &dispatch::DispatchBuffer,
2536 index_format: crate::IndexFormat,
2537 offset: crate::BufferAddress,
2538 size: Option<crate::BufferAddress>,
2539 ) {
2540 let buffer = buffer.as_core();
2541
2542 self.encoder
2543 .set_index_buffer(buffer.wgpu_buffer.clone(), index_format, offset, size);
2544 }
2545
2546 fn set_vertex_buffer(
2547 &mut self,
2548 slot: u32,
2549 buffer: Option<&dispatch::DispatchBuffer>,
2550 offset: crate::BufferAddress,
2551 size: Option<crate::BufferAddress>,
2552 ) {
2553 let buffer = buffer.map(|buffer| buffer.as_core().wgpu_buffer.clone());
2554
2555 self.encoder.set_vertex_buffer(slot, buffer, offset, size);
2556 }
2557
2558 fn set_immediates(&mut self, offset: u32, data: &[u8]) {
2559 if !data
2560 .len()
2561 .is_multiple_of(wgt::IMMEDIATE_DATA_ALIGNMENT as usize)
2562 {
2563 self.encoder.device().handle_error(
2564 wgc::binding_model::ImmediateUploadError::SizeUnaligned(data.len()),
2565 self.encoder.label(),
2566 "RenderBundleEncoder::set_immediates",
2567 );
2568 return;
2569 }
2570
2571 self.encoder.set_immediates(offset, data);
2572 }
2573
2574 fn insert_debug_marker(&mut self, label: &str) {
2575 self.encoder.insert_debug_marker(label);
2576 }
2577
2578 fn push_debug_group(&mut self, group_label: &str) {
2579 self.encoder.push_debug_group(group_label);
2580 }
2581
2582 fn pop_debug_group(&mut self) {
2583 self.encoder.pop_debug_group();
2584 }
2585
2586 fn draw(&mut self, vertices: Range<u32>, instances: Range<u32>) {
2587 self.encoder.draw(
2588 vertices.end - vertices.start,
2589 instances.end - instances.start,
2590 vertices.start,
2591 instances.start,
2592 );
2593 }
2594
2595 fn draw_indexed(&mut self, indices: Range<u32>, base_vertex: i32, instances: Range<u32>) {
2596 self.encoder.draw_indexed(
2597 indices.end - indices.start,
2598 instances.end - instances.start,
2599 indices.start,
2600 base_vertex,
2601 instances.start,
2602 );
2603 }
2604
2605 fn draw_indirect(
2606 &mut self,
2607 indirect_buffer: &dispatch::DispatchBuffer,
2608 indirect_offset: crate::BufferAddress,
2609 ) {
2610 let indirect_buffer = indirect_buffer.as_core();
2611
2612 self.encoder
2613 .draw_indirect(indirect_buffer.wgpu_buffer.clone(), indirect_offset);
2614 }
2615
2616 fn draw_indexed_indirect(
2617 &mut self,
2618 indirect_buffer: &dispatch::DispatchBuffer,
2619 indirect_offset: crate::BufferAddress,
2620 ) {
2621 let indirect_buffer = indirect_buffer.as_core();
2622
2623 self.encoder
2624 .draw_indexed_indirect(indirect_buffer.wgpu_buffer.clone(), indirect_offset);
2625 }
2626
2627 fn finish(mut self, desc: &crate::RenderBundleDescriptor<'_>) -> dispatch::DispatchRenderBundle
2628 where
2629 Self: Sized,
2630 {
2631 let wgpu_render_bundle = self.encoder.finish(&desc.map_label(|l| l.map(Borrowed)));
2632 CoreRenderBundle { wgpu_render_bundle }.into()
2633 }
2634
2635 #[cfg(custom)]
2636 fn finish_boxed(
2637 self: Box<Self>,
2638 desc: &crate::RenderBundleDescriptor<'_>,
2639 ) -> dispatch::DispatchRenderBundle {
2640 (*self).finish(desc)
2641 }
2642}
2643
2644impl dispatch::RenderBundleInterface for CoreRenderBundle {}
2645
2646#[derive(Clone)]
2647enum ErrorSink {
2648 Actual(Arc<wgc::device::Device>),
2649 Dummy(Arc<Mutex<wgc::error::ErrorSink>>),
2650}
2651
2652impl ErrorSink {
2653 fn new() -> Self {
2654 Self::Dummy(Arc::new(Mutex::new(wgc::error::ErrorSink::new())))
2655 }
2656
2657 fn handle_error_nolabel(
2658 &self,
2659 source: impl WebGpuError + WasmNotSendSync + 'static,
2660 fn_ident: &'static str,
2661 ) {
2662 match self {
2663 ErrorSink::Actual(device) => device.handle_error_nolabel(source, fn_ident),
2664 ErrorSink::Dummy(sink) => sink.lock().handle_error_nolabel(source, fn_ident),
2665 }
2666 }
2667}
2668
2669impl dispatch::SurfaceInterface for CoreSurface {
2670 fn get_capabilities(&self, adapter: &dispatch::DispatchAdapter) -> wgt::SurfaceCapabilities {
2671 let adapter = adapter.as_core();
2672
2673 self.wgpu_surface
2674 .get_capabilities(&adapter.wgpu_adapter)
2675 .unwrap_or_default()
2676 }
2677
2678 fn display_hdr_info(&self, adapter: &dispatch::DispatchAdapter) -> wgt::DisplayHdrInfo {
2679 let adapter = adapter.as_core();
2680
2681 self.wgpu_surface.display_hdr_info(&adapter.wgpu_adapter)
2682 }
2683
2684 fn configure(&self, device: &dispatch::DispatchDevice, config: &crate::SurfaceConfiguration) {
2685 let device = device.as_core();
2686
2687 let result = self.wgpu_surface.configure(&device.wgpu_device, config);
2688 if let Some(e) = result.err() {
2689 device
2690 .wgpu_device
2691 .handle_error_nolabel(e, "Surface::configure");
2692 } else {
2693 *self.configured_device.lock() = Some(device.wgpu_device.clone());
2694 }
2695 }
2696
2697 fn get_current_texture(
2698 &self,
2699 _desc: Option<crate::TextureDescriptor<'static>>,
2700 ) -> (
2701 Option<dispatch::DispatchTexture>,
2702 crate::SurfaceStatus,
2703 dispatch::DispatchSurfaceOutputDetail,
2704 ) {
2705 let error_sink = if let Some(error_sink) = self.configured_device.lock().as_ref() {
2706 ErrorSink::Actual(error_sink.clone())
2707 } else {
2708 ErrorSink::new()
2709 };
2710
2711 let output_detail = CoreSurfaceOutputDetail {
2712 wgpu_surface: self.wgpu_surface.clone(),
2713 error_sink,
2714 }
2715 .into();
2716
2717 match self.wgpu_surface.get_current_texture() {
2718 Ok(wgc::present::SurfaceOutput {
2719 status,
2720 texture: texture_id,
2721 }) => {
2722 let data = texture_id
2723 .map(|wgpu_texture| CoreTexture { wgpu_texture })
2724 .map(Into::into);
2725
2726 (data, status, output_detail)
2727 }
2728 Err(err) => {
2729 let error_sink = self.configured_device.lock();
2730 match error_sink.as_ref() {
2731 Some(error_sink) => {
2732 error_sink.handle_error_nolabel(err, "Surface::get_current_texture_view");
2733 (None, crate::SurfaceStatus::Validation, output_detail)
2734 }
2735 None => handle_error_fatal(err, "Surface::get_current_texture_view"),
2736 }
2737 }
2738 }
2739 }
2740}
2741
2742impl dispatch::SurfaceOutputDetailInterface for CoreSurfaceOutputDetail {
2743 fn texture_discard(&self) {
2744 match self.wgpu_surface.discard() {
2745 Ok(_status) => (),
2746 Err(err) => self
2747 .error_sink
2748 .handle_error_nolabel(err, "Surface::discard_texture"),
2749 }
2750 }
2751
2752 fn texture_release(&self) {
2753 match self.wgpu_surface.release() {
2754 Ok(_status) => (),
2755 Err(err) => self
2756 .error_sink
2757 .handle_error_nolabel(err, "Surface::release_texture"),
2758 }
2759 }
2760}
2761
2762impl dispatch::QueueWriteBufferInterface for CoreQueueWriteBuffer {
2763 #[inline]
2764 fn len(&self) -> usize {
2765 self.mapping.len()
2766 }
2767
2768 #[inline]
2769 unsafe fn write_slice(&mut self) -> WriteOnly<'_, [u8]> {
2770 unsafe { self.mapping.write_slice() }
2771 }
2772}
2773
2774impl dispatch::BufferMappedRangeInterface for CoreBufferMappedRange {
2775 #[inline]
2776 fn len(&self) -> usize {
2777 self.size
2778 }
2779
2780 #[inline]
2781 unsafe fn read_slice(&self) -> &[u8] {
2782 unsafe { slice::from_raw_parts(self.ptr.as_ptr(), self.size) }
2783 }
2784
2785 #[inline]
2786 unsafe fn write_slice(&mut self) -> WriteOnly<'_, [u8]> {
2787 unsafe { WriteOnly::new(NonNull::slice_from_raw_parts(self.ptr, self.size)) }
2788 }
2789
2790 #[cfg(webgpu)]
2791 fn as_uint8array(&self) -> &js_sys::Uint8Array {
2792 panic!("Only available on WebGPU")
2793 }
2794}