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