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