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