1use alloc::{borrow::Cow, boxed::Box, string::String, sync::Arc, vec::Vec};
2use core::{ptr::NonNull, sync::atomic::Ordering};
3
4#[cfg(feature = "trace")]
5use crate::device::trace::{self, IntoTrace};
6use crate::{
7 api_log,
8 binding_model::{
9 self, BindGroupEntry, BindingResource, BufferBinding, ResolvedBindGroupDescriptor,
10 ResolvedBindGroupEntry, ResolvedBindingResource, ResolvedBufferBinding,
11 },
12 command::{self, CommandEncoder},
13 conv,
14 device::{life::WaitIdleError, DeviceError, DeviceLostClosure},
15 global::Global,
16 id::{self, AdapterId, DeviceId, QueueId, SurfaceId},
17 instance::{self, Adapter, Surface},
18 pipeline::{
19 self, RenderPipelineVertexProcessor, ResolvedComputePipelineDescriptor,
20 ResolvedFragmentState, ResolvedGeneralRenderPipelineDescriptor, ResolvedMeshState,
21 ResolvedProgrammableStageDescriptor, ResolvedTaskState, ResolvedVertexState,
22 },
23 present,
24 resource::{
25 self, BufferAccessError, BufferAccessResult, BufferMapOperation, CreateBufferError,
26 Fallible,
27 },
28 storage::Storage,
29 Label, LabelHelpers,
30};
31
32use wgt::{BufferAddress, TextureFormat};
33
34use super::UserClosures;
35
36impl Global {
37 pub fn adapter_is_surface_supported(
38 &self,
39 adapter_id: AdapterId,
40 surface_id: SurfaceId,
41 ) -> bool {
42 let surface = self.surfaces.get(surface_id);
43 let adapter = self.hub.adapters.get(adapter_id);
44 adapter.is_surface_supported(&surface)
45 }
46
47 pub fn surface_get_capabilities(
48 &self,
49 surface_id: SurfaceId,
50 adapter_id: AdapterId,
51 ) -> Result<wgt::SurfaceCapabilities, instance::GetSurfaceSupportError> {
52 profiling::scope!("Surface::get_capabilities");
53 self.fetch_adapter_and_surface::<_, _>(surface_id, adapter_id, |adapter, surface| {
54 let mut hal_caps = surface.get_capabilities(adapter)?;
55
56 hal_caps.formats.sort_by_key(|f| !f.is_srgb());
57
58 let usages = conv::map_texture_usage_from_hal(hal_caps.usage);
59
60 Ok(wgt::SurfaceCapabilities {
61 formats: hal_caps.formats,
62 present_modes: hal_caps.present_modes,
63 alpha_modes: hal_caps.composite_alpha_modes,
64 usages,
65 })
66 })
67 }
68
69 fn fetch_adapter_and_surface<F: FnOnce(&Adapter, &Surface) -> B, B>(
70 &self,
71 surface_id: SurfaceId,
72 adapter_id: AdapterId,
73 get_supported_callback: F,
74 ) -> B {
75 let surface = self.surfaces.get(surface_id);
76 let adapter = self.hub.adapters.get(adapter_id);
77 get_supported_callback(&adapter, &surface)
78 }
79
80 pub fn device_features(&self, device_id: DeviceId) -> wgt::Features {
81 let device = self.hub.devices.get(device_id);
82 device.features
83 }
84
85 pub fn device_limits(&self, device_id: DeviceId) -> wgt::Limits {
86 let device = self.hub.devices.get(device_id);
87 device.limits.clone()
88 }
89
90 pub fn device_downlevel_properties(&self, device_id: DeviceId) -> wgt::DownlevelCapabilities {
91 let device = self.hub.devices.get(device_id);
92 device.downlevel.clone()
93 }
94
95 pub fn device_create_buffer(
96 &self,
97 device_id: DeviceId,
98 desc: &resource::BufferDescriptor,
99 id_in: Option<id::BufferId>,
100 ) -> (id::BufferId, Option<CreateBufferError>) {
101 profiling::scope!("Device::create_buffer");
102
103 let hub = &self.hub;
104 let fid = hub.buffers.prepare(id_in);
105
106 let error = 'error: {
107 let device = self.hub.devices.get(device_id);
108
109 let buffer = match device.create_buffer(desc) {
110 Ok(buffer) => buffer,
111 Err(e) => {
112 break 'error e;
113 }
114 };
115
116 #[cfg(feature = "trace")]
117 if let Some(ref mut trace) = *device.trace.lock() {
118 let mut desc = desc.clone();
119 let mapped_at_creation = core::mem::replace(&mut desc.mapped_at_creation, false);
120 if mapped_at_creation && !desc.usage.contains(wgt::BufferUsages::MAP_WRITE) {
121 desc.usage |= wgt::BufferUsages::COPY_DST;
122 }
123 trace.add(trace::Action::CreateBuffer(buffer.to_trace(), desc));
124 }
125
126 let id = fid.assign(Fallible::Valid(buffer));
127
128 api_log!(
129 "Device::create_buffer({:?}{}) -> {id:?}",
130 desc.label.as_deref().unwrap_or(""),
131 if desc.mapped_at_creation {
132 ", mapped_at_creation"
133 } else {
134 ""
135 }
136 );
137
138 return (id, None);
139 };
140
141 let id = fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string())));
142 (id, Some(error))
143 }
144
145 pub fn create_buffer_error(
174 &self,
175 id_in: Option<id::BufferId>,
176 desc: &resource::BufferDescriptor,
177 ) {
178 let fid = self.hub.buffers.prepare(id_in);
179 fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string())));
180 }
181
182 pub fn create_render_bundle_error(
186 &self,
187 id_in: Option<id::RenderBundleId>,
188 desc: &command::RenderBundleDescriptor,
189 ) {
190 let fid = self.hub.render_bundles.prepare(id_in);
191 fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string())));
192 }
193
194 pub fn create_texture_error(
198 &self,
199 id_in: Option<id::TextureId>,
200 desc: &resource::TextureDescriptor,
201 ) {
202 let fid = self.hub.textures.prepare(id_in);
203 fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string())));
204 }
205
206 pub fn create_external_texture_error(
210 &self,
211 id_in: Option<id::ExternalTextureId>,
212 desc: &resource::ExternalTextureDescriptor,
213 ) {
214 let fid = self.hub.external_textures.prepare(id_in);
215 fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string())));
216 }
217
218 pub fn create_bind_group_layout_error(
227 &self,
228 id_in: Option<id::BindGroupLayoutId>,
229 label: Option<Cow<'_, str>>,
230 ) {
231 let fid = self.hub.bind_group_layouts.prepare(id_in);
232 fid.assign(Fallible::Invalid(Arc::new(label.to_string())));
233 }
234
235 pub fn buffer_destroy(&self, buffer_id: id::BufferId) {
236 profiling::scope!("Buffer::destroy");
237 api_log!("Buffer::destroy {buffer_id:?}");
238
239 let hub = &self.hub;
240
241 let Ok(buffer) = hub.buffers.get(buffer_id).get() else {
242 return;
244 };
245
246 #[cfg(feature = "trace")]
247 if let Some(trace) = buffer.device.trace.lock().as_mut() {
248 trace.add(trace::Action::FreeBuffer(buffer.to_trace()));
249 }
250
251 let _ = buffer.unmap();
252
253 buffer.destroy();
254 }
255
256 pub fn buffer_drop(&self, buffer_id: id::BufferId) {
257 profiling::scope!("Buffer::drop");
258 api_log!("Buffer::drop {buffer_id:?}");
259
260 let hub = &self.hub;
261
262 let buffer = match hub.buffers.remove(buffer_id).get() {
263 Ok(buffer) => buffer,
264 Err(_) => {
265 return;
266 }
267 };
268
269 #[cfg(feature = "trace")]
270 if let Some(t) = buffer.device.trace.lock().as_mut() {
271 t.add(trace::Action::DestroyBuffer(buffer.to_trace()));
272 }
273
274 let _ = buffer.unmap();
275 }
276
277 pub fn device_create_texture(
278 &self,
279 device_id: DeviceId,
280 desc: &resource::TextureDescriptor,
281 id_in: Option<id::TextureId>,
282 ) -> (id::TextureId, Option<resource::CreateTextureError>) {
283 profiling::scope!("Device::create_texture");
284
285 let hub = &self.hub;
286
287 let fid = hub.textures.prepare(id_in);
288
289 let error = 'error: {
290 let device = self.hub.devices.get(device_id);
291
292 let texture = match device.create_texture(desc) {
293 Ok(texture) => texture,
294 Err(error) => break 'error error,
295 };
296
297 #[cfg(feature = "trace")]
298 if let Some(ref mut trace) = *device.trace.lock() {
299 trace.add(trace::Action::CreateTexture(
300 texture.to_trace(),
301 desc.clone(),
302 ));
303 }
304
305 let id = fid.assign(Fallible::Valid(texture));
306 api_log!("Device::create_texture({desc:?}) -> {id:?}");
307
308 return (id, None);
309 };
310
311 let id = fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string())));
312 (id, Some(error))
313 }
314
315 pub unsafe fn create_texture_from_hal(
321 &self,
322 hal_texture: Box<dyn hal::DynTexture>,
323 device_id: DeviceId,
324 desc: &resource::TextureDescriptor,
325 id_in: Option<id::TextureId>,
326 ) -> (id::TextureId, Option<resource::CreateTextureError>) {
327 profiling::scope!("Device::create_texture_from_hal");
328
329 let hub = &self.hub;
330
331 let fid = hub.textures.prepare(id_in);
332
333 let error = 'error: {
334 let device = self.hub.devices.get(device_id);
335
336 let texture = match device.create_texture_from_hal(hal_texture, desc) {
337 Ok(texture) => texture,
338 Err(error) => break 'error error,
339 };
340
341 #[cfg(feature = "trace")]
344 if let Some(ref mut trace) = *device.trace.lock() {
345 trace.add(trace::Action::CreateTexture(
346 texture.to_trace(),
347 desc.clone(),
348 ));
349 }
350
351 let id = fid.assign(Fallible::Valid(texture));
352 api_log!("Device::create_texture({desc:?}) -> {id:?}");
353
354 return (id, None);
355 };
356
357 let id = fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string())));
358 (id, Some(error))
359 }
360
361 pub unsafe fn create_buffer_from_hal<A: hal::Api>(
368 &self,
369 hal_buffer: A::Buffer,
370 device_id: DeviceId,
371 desc: &resource::BufferDescriptor,
372 id_in: Option<id::BufferId>,
373 ) -> (id::BufferId, Option<CreateBufferError>) {
374 profiling::scope!("Device::create_buffer");
375
376 let hub = &self.hub;
377 let fid = hub.buffers.prepare(id_in);
378
379 let device = self.hub.devices.get(device_id);
380
381 let (buffer, err) = unsafe { device.create_buffer_from_hal(Box::new(hal_buffer), desc) };
382
383 #[cfg(feature = "trace")]
386 if let Some(trace) = device.trace.lock().as_mut() {
387 match &buffer {
388 Fallible::Valid(arc) => {
389 trace.add(trace::Action::CreateBuffer(arc.to_trace(), desc.clone()))
390 }
391 Fallible::Invalid(_) => {}
392 }
393 }
394
395 let id = fid.assign(buffer);
396 api_log!("Device::create_buffer -> {id:?}");
397
398 (id, err)
399 }
400
401 pub fn texture_destroy(&self, texture_id: id::TextureId) {
402 profiling::scope!("Texture::destroy");
403 api_log!("Texture::destroy {texture_id:?}");
404
405 let hub = &self.hub;
406
407 let Ok(texture) = hub.textures.get(texture_id).get() else {
408 return;
410 };
411
412 #[cfg(feature = "trace")]
413 if let Some(trace) = texture.device.trace.lock().as_mut() {
414 trace.add(trace::Action::FreeTexture(texture.to_trace()));
415 }
416
417 texture.destroy();
418 }
419
420 pub fn texture_drop(&self, texture_id: id::TextureId) {
421 profiling::scope!("Texture::drop");
422 api_log!("Texture::drop {texture_id:?}");
423
424 let hub = &self.hub;
425
426 let _texture = hub.textures.remove(texture_id);
427 #[cfg(feature = "trace")]
428 if let Ok(texture) = _texture.get() {
429 if let Some(t) = texture.device.trace.lock().as_mut() {
430 t.add(trace::Action::DestroyTexture(texture.to_trace()));
431 }
432 }
433 }
434
435 pub fn texture_create_view(
436 &self,
437 texture_id: id::TextureId,
438 desc: &resource::TextureViewDescriptor,
439 id_in: Option<id::TextureViewId>,
440 ) -> (id::TextureViewId, Option<resource::CreateTextureViewError>) {
441 profiling::scope!("Texture::create_view");
442
443 let hub = &self.hub;
444
445 let fid = hub.texture_views.prepare(id_in);
446
447 let error = 'error: {
448 let texture = match hub.textures.get(texture_id).get() {
449 Ok(texture) => texture,
450 Err(e) => break 'error e.into(),
451 };
452 let device = &texture.device;
453
454 let view = match device.create_texture_view(&texture, desc) {
455 Ok(view) => view,
456 Err(e) => break 'error e,
457 };
458
459 #[cfg(feature = "trace")]
460 if let Some(ref mut trace) = *device.trace.lock() {
461 trace.add(trace::Action::CreateTextureView {
462 id: view.to_trace(),
463 parent: texture.to_trace(),
464 desc: desc.clone(),
465 });
466 }
467
468 let id = fid.assign(Fallible::Valid(view));
469
470 api_log!("Texture::create_view({texture_id:?}) -> {id:?}");
471
472 return (id, None);
473 };
474
475 let id = fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string())));
476 (id, Some(error))
477 }
478
479 pub fn texture_view_drop(
480 &self,
481 texture_view_id: id::TextureViewId,
482 ) -> Result<(), resource::TextureViewDestroyError> {
483 profiling::scope!("TextureView::drop");
484 api_log!("TextureView::drop {texture_view_id:?}");
485
486 let hub = &self.hub;
487
488 let _view = hub.texture_views.remove(texture_view_id);
489
490 #[cfg(feature = "trace")]
491 if let Ok(view) = _view.get() {
492 if let Some(t) = view.device.trace.lock().as_mut() {
493 t.add(trace::Action::DestroyTextureView(view.to_trace()));
494 }
495 }
496 Ok(())
497 }
498
499 pub fn device_create_external_texture(
500 &self,
501 device_id: DeviceId,
502 desc: &resource::ExternalTextureDescriptor,
503 planes: &[id::TextureViewId],
504 id_in: Option<id::ExternalTextureId>,
505 ) -> (
506 id::ExternalTextureId,
507 Option<resource::CreateExternalTextureError>,
508 ) {
509 profiling::scope!("Device::create_external_texture");
510
511 let hub = &self.hub;
512
513 let fid = hub.external_textures.prepare(id_in);
514
515 let error = 'error: {
516 let device = self.hub.devices.get(device_id);
517
518 let planes = planes
519 .iter()
520 .map(|plane_id| self.hub.texture_views.get(*plane_id).get())
521 .collect::<Result<Vec<_>, _>>();
522 let planes = match planes {
523 Ok(planes) => planes,
524 Err(error) => break 'error error.into(),
525 };
526
527 let external_texture = match device.create_external_texture(desc, &planes) {
528 Ok(external_texture) => external_texture,
529 Err(error) => break 'error error,
530 };
531
532 #[cfg(feature = "trace")]
533 if let Some(ref mut trace) = *device.trace.lock() {
534 let planes = Box::from(
535 planes
536 .into_iter()
537 .map(|plane| plane.to_trace())
538 .collect::<Vec<_>>(),
539 );
540 trace.add(trace::Action::CreateExternalTexture {
541 id: external_texture.to_trace(),
542 desc: desc.clone(),
543 planes,
544 });
545 }
546
547 let id = fid.assign(Fallible::Valid(external_texture));
548 api_log!("Device::create_external_texture({desc:?}) -> {id:?}");
549
550 return (id, None);
551 };
552
553 let id = fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string())));
554 (id, Some(error))
555 }
556
557 pub fn external_texture_destroy(&self, external_texture_id: id::ExternalTextureId) {
558 profiling::scope!("ExternalTexture::destroy");
559 api_log!("ExternalTexture::destroy {external_texture_id:?}");
560
561 let hub = &self.hub;
562
563 let Ok(external_texture) = hub.external_textures.get(external_texture_id).get() else {
564 return;
566 };
567
568 #[cfg(feature = "trace")]
569 if let Some(trace) = external_texture.device.trace.lock().as_mut() {
570 trace.add(trace::Action::FreeExternalTexture(
571 external_texture.to_trace(),
572 ));
573 }
574
575 external_texture.destroy();
576 }
577
578 pub fn external_texture_drop(&self, external_texture_id: id::ExternalTextureId) {
579 profiling::scope!("ExternalTexture::drop");
580 api_log!("ExternalTexture::drop {external_texture_id:?}");
581
582 let hub = &self.hub;
583
584 let _external_texture = hub.external_textures.remove(external_texture_id);
585
586 #[cfg(feature = "trace")]
587 if let Ok(external_texture) = _external_texture.get() {
588 if let Some(t) = external_texture.device.trace.lock().as_mut() {
589 t.add(trace::Action::DestroyExternalTexture(
590 external_texture.to_trace(),
591 ));
592 }
593 }
594 }
595
596 pub fn device_create_sampler(
597 &self,
598 device_id: DeviceId,
599 desc: &resource::SamplerDescriptor,
600 id_in: Option<id::SamplerId>,
601 ) -> (id::SamplerId, Option<resource::CreateSamplerError>) {
602 profiling::scope!("Device::create_sampler");
603
604 let hub = &self.hub;
605 let fid = hub.samplers.prepare(id_in);
606
607 let error = 'error: {
608 let device = self.hub.devices.get(device_id);
609
610 let sampler = match device.create_sampler(desc) {
611 Ok(sampler) => sampler,
612 Err(e) => break 'error e,
613 };
614
615 #[cfg(feature = "trace")]
616 if let Some(ref mut trace) = *device.trace.lock() {
617 trace.add(trace::Action::CreateSampler(
618 sampler.to_trace(),
619 desc.clone(),
620 ));
621 }
622
623 let id = fid.assign(Fallible::Valid(sampler));
624 api_log!("Device::create_sampler -> {id:?}");
625
626 return (id, None);
627 };
628
629 let id = fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string())));
630 (id, Some(error))
631 }
632
633 pub fn sampler_drop(&self, sampler_id: id::SamplerId) {
634 profiling::scope!("Sampler::drop");
635 api_log!("Sampler::drop {sampler_id:?}");
636
637 let hub = &self.hub;
638
639 let _sampler = hub.samplers.remove(sampler_id);
640
641 #[cfg(feature = "trace")]
642 if let Ok(sampler) = _sampler.get() {
643 if let Some(t) = sampler.device.trace.lock().as_mut() {
644 t.add(trace::Action::DestroySampler(sampler.to_trace()));
645 }
646 }
647 }
648
649 pub fn device_create_bind_group_layout(
650 &self,
651 device_id: DeviceId,
652 desc: &binding_model::BindGroupLayoutDescriptor,
653 id_in: Option<id::BindGroupLayoutId>,
654 ) -> (
655 id::BindGroupLayoutId,
656 Option<binding_model::CreateBindGroupLayoutError>,
657 ) {
658 profiling::scope!("Device::create_bind_group_layout");
659
660 let hub = &self.hub;
661 let fid = hub.bind_group_layouts.prepare(id_in);
662
663 let error = 'error: {
664 let device = self.hub.devices.get(device_id);
665
666 let layout = match device.create_bind_group_layout(desc) {
667 Ok(layout) => layout,
668 Err(e) => break 'error e,
669 };
670
671 #[cfg(feature = "trace")]
672 if let Some(ref mut trace) = *device.trace.lock() {
673 trace.add(trace::Action::CreateBindGroupLayout(
674 layout.to_trace(),
675 desc.clone(),
676 ));
677 }
678
679 let id = fid.assign(Fallible::Valid(layout.clone()));
680
681 api_log!("Device::create_bind_group_layout -> {id:?}");
682 return (id, None);
683 };
684
685 let id = fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string())));
686 (id, Some(error))
687 }
688
689 pub fn bind_group_layout_drop(&self, bind_group_layout_id: id::BindGroupLayoutId) {
690 profiling::scope!("BindGroupLayout::drop");
691 api_log!("BindGroupLayout::drop {bind_group_layout_id:?}");
692
693 let hub = &self.hub;
694
695 let _layout = hub.bind_group_layouts.remove(bind_group_layout_id);
696
697 #[cfg(feature = "trace")]
698 if let Ok(layout) = _layout.get() {
699 if let Some(t) = layout.device.trace.lock().as_mut() {
700 t.add(trace::Action::DestroyBindGroupLayout(layout.to_trace()));
701 }
702 }
703 }
704
705 pub fn device_create_pipeline_layout(
706 &self,
707 device_id: DeviceId,
708 desc: &binding_model::PipelineLayoutDescriptor,
709 id_in: Option<id::PipelineLayoutId>,
710 ) -> (
711 id::PipelineLayoutId,
712 Option<binding_model::CreatePipelineLayoutError>,
713 ) {
714 profiling::scope!("Device::create_pipeline_layout");
715
716 let hub = &self.hub;
717 let fid = hub.pipeline_layouts.prepare(id_in);
718
719 let error = 'error: {
720 let device = self.hub.devices.get(device_id);
721
722 if let Err(e) = device.check_is_valid() {
723 break 'error e.into();
724 }
725
726 let bind_group_layouts = {
727 let bind_group_layouts_guard = hub.bind_group_layouts.read();
728 desc.bind_group_layouts
729 .iter()
730 .map(|bgl_id| bind_group_layouts_guard.get(*bgl_id).get())
731 .collect::<Result<Vec<_>, _>>()
732 };
733
734 let bind_group_layouts = match bind_group_layouts {
735 Ok(bind_group_layouts) => bind_group_layouts,
736 Err(e) => break 'error e.into(),
737 };
738
739 let desc = binding_model::ResolvedPipelineLayoutDescriptor {
740 label: desc.label.clone(),
741 bind_group_layouts: Cow::Owned(bind_group_layouts),
742 immediates_ranges: desc.immediates_ranges.clone(),
743 };
744
745 let layout = match device.create_pipeline_layout(&desc) {
746 Ok(layout) => layout,
747 Err(e) => break 'error e,
748 };
749
750 #[cfg(feature = "trace")]
751 if let Some(ref mut trace) = *device.trace.lock() {
752 trace.add(trace::Action::CreatePipelineLayout(
753 layout.to_trace(),
754 desc.to_trace(),
755 ));
756 }
757
758 let id = fid.assign(Fallible::Valid(layout));
759 api_log!("Device::create_pipeline_layout -> {id:?}");
760 return (id, None);
761 };
762
763 let id = fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string())));
764 (id, Some(error))
765 }
766
767 pub fn pipeline_layout_drop(&self, pipeline_layout_id: id::PipelineLayoutId) {
768 profiling::scope!("PipelineLayout::drop");
769 api_log!("PipelineLayout::drop {pipeline_layout_id:?}");
770
771 let hub = &self.hub;
772
773 let _layout = hub.pipeline_layouts.remove(pipeline_layout_id);
774
775 #[cfg(feature = "trace")]
776 if let Ok(layout) = _layout.get() {
777 if let Some(t) = layout.device.trace.lock().as_mut() {
778 t.add(trace::Action::DestroyPipelineLayout(layout.to_trace()));
779 }
780 }
781 }
782
783 pub fn device_create_bind_group(
784 &self,
785 device_id: DeviceId,
786 desc: &binding_model::BindGroupDescriptor,
787 id_in: Option<id::BindGroupId>,
788 ) -> (id::BindGroupId, Option<binding_model::CreateBindGroupError>) {
789 profiling::scope!("Device::create_bind_group");
790
791 let hub = &self.hub;
792 let fid = hub.bind_groups.prepare(id_in);
793
794 let error = 'error: {
795 let device = self.hub.devices.get(device_id);
796
797 if let Err(e) = device.check_is_valid() {
798 break 'error e.into();
799 }
800
801 let layout = match hub.bind_group_layouts.get(desc.layout).get() {
802 Ok(layout) => layout,
803 Err(e) => break 'error e.into(),
804 };
805
806 fn resolve_entry<'a>(
807 e: &BindGroupEntry<'a>,
808 buffer_storage: &Storage<Fallible<resource::Buffer>>,
809 sampler_storage: &Storage<Fallible<resource::Sampler>>,
810 texture_view_storage: &Storage<Fallible<resource::TextureView>>,
811 tlas_storage: &Storage<Fallible<resource::Tlas>>,
812 external_texture_storage: &Storage<Fallible<resource::ExternalTexture>>,
813 ) -> Result<ResolvedBindGroupEntry<'a>, binding_model::CreateBindGroupError>
814 {
815 let resolve_buffer = |bb: &BufferBinding| {
816 buffer_storage
817 .get(bb.buffer)
818 .get()
819 .map(|buffer| ResolvedBufferBinding {
820 buffer,
821 offset: bb.offset,
822 size: bb.size,
823 })
824 .map_err(binding_model::CreateBindGroupError::from)
825 };
826 let resolve_sampler = |id: &id::SamplerId| {
827 sampler_storage
828 .get(*id)
829 .get()
830 .map_err(binding_model::CreateBindGroupError::from)
831 };
832 let resolve_view = |id: &id::TextureViewId| {
833 texture_view_storage
834 .get(*id)
835 .get()
836 .map_err(binding_model::CreateBindGroupError::from)
837 };
838 let resolve_tlas = |id: &id::TlasId| {
839 tlas_storage
840 .get(*id)
841 .get()
842 .map_err(binding_model::CreateBindGroupError::from)
843 };
844 let resolve_external_texture = |id: &id::ExternalTextureId| {
845 external_texture_storage
846 .get(*id)
847 .get()
848 .map_err(binding_model::CreateBindGroupError::from)
849 };
850 let resource = match e.resource {
851 BindingResource::Buffer(ref buffer) => {
852 ResolvedBindingResource::Buffer(resolve_buffer(buffer)?)
853 }
854 BindingResource::BufferArray(ref buffers) => {
855 let buffers = buffers
856 .iter()
857 .map(resolve_buffer)
858 .collect::<Result<Vec<_>, _>>()?;
859 ResolvedBindingResource::BufferArray(Cow::Owned(buffers))
860 }
861 BindingResource::Sampler(ref sampler) => {
862 ResolvedBindingResource::Sampler(resolve_sampler(sampler)?)
863 }
864 BindingResource::SamplerArray(ref samplers) => {
865 let samplers = samplers
866 .iter()
867 .map(resolve_sampler)
868 .collect::<Result<Vec<_>, _>>()?;
869 ResolvedBindingResource::SamplerArray(Cow::Owned(samplers))
870 }
871 BindingResource::TextureView(ref view) => {
872 ResolvedBindingResource::TextureView(resolve_view(view)?)
873 }
874 BindingResource::TextureViewArray(ref views) => {
875 let views = views
876 .iter()
877 .map(resolve_view)
878 .collect::<Result<Vec<_>, _>>()?;
879 ResolvedBindingResource::TextureViewArray(Cow::Owned(views))
880 }
881 BindingResource::AccelerationStructure(ref tlas) => {
882 ResolvedBindingResource::AccelerationStructure(resolve_tlas(tlas)?)
883 }
884 BindingResource::ExternalTexture(ref et) => {
885 ResolvedBindingResource::ExternalTexture(resolve_external_texture(et)?)
886 }
887 };
888 Ok(ResolvedBindGroupEntry {
889 binding: e.binding,
890 resource,
891 })
892 }
893
894 let entries = {
895 let buffer_guard = hub.buffers.read();
896 let texture_view_guard = hub.texture_views.read();
897 let sampler_guard = hub.samplers.read();
898 let tlas_guard = hub.tlas_s.read();
899 let external_texture_guard = hub.external_textures.read();
900 desc.entries
901 .iter()
902 .map(|e| {
903 resolve_entry(
904 e,
905 &buffer_guard,
906 &sampler_guard,
907 &texture_view_guard,
908 &tlas_guard,
909 &external_texture_guard,
910 )
911 })
912 .collect::<Result<Vec<_>, _>>()
913 };
914 let entries = match entries {
915 Ok(entries) => Cow::Owned(entries),
916 Err(e) => break 'error e,
917 };
918
919 let desc = ResolvedBindGroupDescriptor {
920 label: desc.label.clone(),
921 layout,
922 entries,
923 };
924 #[cfg(feature = "trace")]
925 let trace_desc = (&desc).to_trace();
926
927 let bind_group = match device.create_bind_group(desc) {
928 Ok(bind_group) => bind_group,
929 Err(e) => break 'error e,
930 };
931
932 #[cfg(feature = "trace")]
933 if let Some(ref mut trace) = *device.trace.lock() {
934 trace.add(trace::Action::CreateBindGroup(
935 bind_group.to_trace(),
936 trace_desc,
937 ));
938 }
939
940 let id = fid.assign(Fallible::Valid(bind_group));
941
942 api_log!("Device::create_bind_group -> {id:?}");
943
944 return (id, None);
945 };
946
947 let id = fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string())));
948 (id, Some(error))
949 }
950
951 pub fn bind_group_drop(&self, bind_group_id: id::BindGroupId) {
952 profiling::scope!("BindGroup::drop");
953 api_log!("BindGroup::drop {bind_group_id:?}");
954
955 let hub = &self.hub;
956
957 let _bind_group = hub.bind_groups.remove(bind_group_id);
958
959 #[cfg(feature = "trace")]
960 if let Ok(bind_group) = _bind_group.get() {
961 if let Some(t) = bind_group.device.trace.lock().as_mut() {
962 t.add(trace::Action::DestroyBindGroup(bind_group.to_trace()));
963 }
964 }
965 }
966
967 pub fn device_create_shader_module(
982 &self,
983 device_id: DeviceId,
984 desc: &pipeline::ShaderModuleDescriptor,
985 source: pipeline::ShaderModuleSource,
986 id_in: Option<id::ShaderModuleId>,
987 ) -> (
988 id::ShaderModuleId,
989 Option<pipeline::CreateShaderModuleError>,
990 ) {
991 profiling::scope!("Device::create_shader_module");
992
993 let hub = &self.hub;
994 let fid = hub.shader_modules.prepare(id_in);
995
996 let error = 'error: {
997 let device = self.hub.devices.get(device_id);
998
999 #[cfg(feature = "trace")]
1000 let data = device.trace.lock().as_mut().map(|trace| match source {
1001 #[cfg(feature = "wgsl")]
1002 pipeline::ShaderModuleSource::Wgsl(ref code) => {
1003 trace.make_binary("wgsl", code.as_bytes())
1004 }
1005 #[cfg(feature = "glsl")]
1006 pipeline::ShaderModuleSource::Glsl(ref code, _) => {
1007 trace.make_binary("glsl", code.as_bytes())
1008 }
1009 #[cfg(feature = "spirv")]
1010 pipeline::ShaderModuleSource::SpirV(ref code, _) => {
1011 trace.make_binary("spirv", bytemuck::cast_slice::<u32, u8>(code))
1012 }
1013 pipeline::ShaderModuleSource::Naga(ref module) => {
1014 let string =
1015 ron::ser::to_string_pretty(module, ron::ser::PrettyConfig::default())
1016 .unwrap();
1017 trace.make_binary("ron", string.as_bytes())
1018 }
1019 pipeline::ShaderModuleSource::Dummy(_) => {
1020 panic!("found `ShaderModuleSource::Dummy`")
1021 }
1022 });
1023
1024 let shader = match device.create_shader_module(desc, source) {
1025 Ok(shader) => shader,
1026 Err(e) => break 'error e,
1027 };
1028
1029 #[cfg(feature = "trace")]
1030 if let Some(data) = data {
1031 device
1033 .trace
1034 .lock()
1035 .as_mut()
1036 .expect("trace went away during create_shader_module?")
1037 .add(trace::Action::CreateShaderModule {
1038 id: shader.to_trace(),
1039 desc: desc.clone(),
1040 data,
1041 });
1042 };
1043
1044 let id = fid.assign(Fallible::Valid(shader));
1045 api_log!("Device::create_shader_module -> {id:?}");
1046 return (id, None);
1047 };
1048
1049 let id = fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string())));
1050 (id, Some(error))
1051 }
1052
1053 #[allow(unused_unsafe)]
1054 pub unsafe fn device_create_shader_module_passthrough(
1059 &self,
1060 device_id: DeviceId,
1061 desc: &pipeline::ShaderModuleDescriptorPassthrough<'_>,
1062 id_in: Option<id::ShaderModuleId>,
1063 ) -> (
1064 id::ShaderModuleId,
1065 Option<pipeline::CreateShaderModuleError>,
1066 ) {
1067 profiling::scope!("Device::create_shader_module_passthrough");
1068
1069 let hub = &self.hub;
1070 let fid = hub.shader_modules.prepare(id_in);
1071
1072 let error = 'error: {
1073 let device = self.hub.devices.get(device_id);
1074
1075 let result = unsafe { device.create_shader_module_passthrough(desc) };
1076
1077 let shader = match result {
1078 Ok(shader) => shader,
1079 Err(e) => break 'error e,
1080 };
1081
1082 #[cfg(feature = "trace")]
1083 if let Some(ref mut trace) = *device.trace.lock() {
1084 let mut file_names = Vec::new();
1085 for (data, ext) in [
1086 (desc.spirv.as_ref().map(|a| bytemuck::cast_slice(a)), "spv"),
1087 (desc.dxil.as_deref(), "dxil"),
1088 (desc.hlsl.as_ref().map(|a| a.as_bytes()), "hlsl"),
1089 (desc.msl.as_ref().map(|a| a.as_bytes()), "msl"),
1090 (desc.glsl.as_ref().map(|a| a.as_bytes()), "glsl"),
1091 (desc.wgsl.as_ref().map(|a| a.as_bytes()), "wgsl"),
1092 ] {
1093 if let Some(data) = data {
1094 file_names.push(trace.make_binary(ext, data));
1095 }
1096 }
1097 trace.add(trace::Action::CreateShaderModulePassthrough {
1098 id: shader.to_trace(),
1099 data: file_names,
1100
1101 entry_point: desc.entry_point.clone(),
1102 label: desc.label.clone(),
1103 num_workgroups: desc.num_workgroups,
1104 runtime_checks: desc.runtime_checks,
1105 });
1106 };
1107
1108 let id = fid.assign(Fallible::Valid(shader));
1109 api_log!("Device::create_shader_module_spirv -> {id:?}");
1110 return (id, None);
1111 };
1112
1113 let id = fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string())));
1114 (id, Some(error))
1115 }
1116
1117 pub fn shader_module_drop(&self, shader_module_id: id::ShaderModuleId) {
1118 profiling::scope!("ShaderModule::drop");
1119 api_log!("ShaderModule::drop {shader_module_id:?}");
1120
1121 let hub = &self.hub;
1122
1123 let _shader_module = hub.shader_modules.remove(shader_module_id);
1124
1125 #[cfg(feature = "trace")]
1126 if let Ok(shader_module) = _shader_module.get() {
1127 if let Some(t) = shader_module.device.trace.lock().as_mut() {
1128 t.add(trace::Action::DestroyShaderModule(shader_module.to_trace()));
1129 }
1130 }
1131 }
1132
1133 pub fn device_create_command_encoder(
1134 &self,
1135 device_id: DeviceId,
1136 desc: &wgt::CommandEncoderDescriptor<Label>,
1137 id_in: Option<id::CommandEncoderId>,
1138 ) -> (id::CommandEncoderId, Option<DeviceError>) {
1139 profiling::scope!("Device::create_command_encoder");
1140
1141 let hub = &self.hub;
1142 let fid = hub.command_encoders.prepare(id_in);
1143
1144 let device = self.hub.devices.get(device_id);
1145
1146 let error = 'error: {
1147 let cmd_enc = match device.create_command_encoder(&desc.label) {
1148 Ok(cmd_enc) => cmd_enc,
1149 Err(e) => break 'error e,
1150 };
1151
1152 let id = fid.assign(cmd_enc);
1153 api_log!("Device::create_command_encoder -> {id:?}");
1154 return (id, None);
1155 };
1156
1157 let id = fid.assign(Arc::new(CommandEncoder::new_invalid(
1158 &device,
1159 &desc.label,
1160 error.clone().into(),
1161 )));
1162 (id, Some(error))
1163 }
1164
1165 pub fn command_encoder_drop(&self, command_encoder_id: id::CommandEncoderId) {
1166 profiling::scope!("CommandEncoder::drop");
1167 api_log!("CommandEncoder::drop {command_encoder_id:?}");
1168 let _cmd_enc = self.hub.command_encoders.remove(command_encoder_id);
1169 }
1170
1171 pub fn command_buffer_drop(&self, command_buffer_id: id::CommandBufferId) {
1172 profiling::scope!("CommandBuffer::drop");
1173 api_log!("CommandBuffer::drop {command_buffer_id:?}");
1174 let _cmd_buf = self.hub.command_buffers.remove(command_buffer_id);
1175 }
1176
1177 pub fn device_create_render_bundle_encoder(
1178 &self,
1179 device_id: DeviceId,
1180 desc: &command::RenderBundleEncoderDescriptor,
1181 ) -> (
1182 *mut command::RenderBundleEncoder,
1183 Option<command::CreateRenderBundleError>,
1184 ) {
1185 profiling::scope!("Device::create_render_bundle_encoder");
1186 api_log!("Device::device_create_render_bundle_encoder");
1187 let (encoder, error) = match command::RenderBundleEncoder::new(desc, device_id) {
1188 Ok(encoder) => (encoder, None),
1189 Err(e) => (command::RenderBundleEncoder::dummy(device_id), Some(e)),
1190 };
1191 (Box::into_raw(Box::new(encoder)), error)
1192 }
1193
1194 pub fn render_bundle_encoder_finish(
1195 &self,
1196 bundle_encoder: command::RenderBundleEncoder,
1197 desc: &command::RenderBundleDescriptor,
1198 id_in: Option<id::RenderBundleId>,
1199 ) -> (id::RenderBundleId, Option<command::RenderBundleError>) {
1200 profiling::scope!("RenderBundleEncoder::finish");
1201
1202 let hub = &self.hub;
1203
1204 let fid = hub.render_bundles.prepare(id_in);
1205
1206 let error = 'error: {
1207 let device = self.hub.devices.get(bundle_encoder.parent());
1208
1209 #[cfg(feature = "trace")]
1210 let trace_desc = trace::new_render_bundle_encoder_descriptor(
1211 desc.label.clone(),
1212 &bundle_encoder.context,
1213 bundle_encoder.is_depth_read_only,
1214 bundle_encoder.is_stencil_read_only,
1215 );
1216
1217 let render_bundle = match bundle_encoder.finish(desc, &device, hub) {
1218 Ok(bundle) => bundle,
1219 Err(e) => break 'error e,
1220 };
1221
1222 #[cfg(feature = "trace")]
1223 if let Some(ref mut trace) = *device.trace.lock() {
1224 trace.add(trace::Action::CreateRenderBundle {
1225 id: render_bundle.to_trace(),
1226 desc: trace_desc,
1227 base: render_bundle.to_base_pass().to_trace(),
1228 });
1229 }
1230
1231 let id = fid.assign(Fallible::Valid(render_bundle));
1232 api_log!("RenderBundleEncoder::finish -> {id:?}");
1233
1234 return (id, None);
1235 };
1236
1237 let id = fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string())));
1238 (id, Some(error))
1239 }
1240
1241 pub fn render_bundle_drop(&self, render_bundle_id: id::RenderBundleId) {
1242 profiling::scope!("RenderBundle::drop");
1243 api_log!("RenderBundle::drop {render_bundle_id:?}");
1244
1245 let hub = &self.hub;
1246
1247 let _bundle = hub.render_bundles.remove(render_bundle_id);
1248
1249 #[cfg(feature = "trace")]
1250 if let Ok(bundle) = _bundle.get() {
1251 if let Some(t) = bundle.device.trace.lock().as_mut() {
1252 t.add(trace::Action::DestroyRenderBundle(bundle.to_trace()));
1253 }
1254 }
1255 }
1256
1257 pub fn device_create_query_set(
1258 &self,
1259 device_id: DeviceId,
1260 desc: &resource::QuerySetDescriptor,
1261 id_in: Option<id::QuerySetId>,
1262 ) -> (id::QuerySetId, Option<resource::CreateQuerySetError>) {
1263 profiling::scope!("Device::create_query_set");
1264
1265 let hub = &self.hub;
1266 let fid = hub.query_sets.prepare(id_in);
1267
1268 let error = 'error: {
1269 let device = self.hub.devices.get(device_id);
1270
1271 let query_set = match device.create_query_set(desc) {
1272 Ok(query_set) => query_set,
1273 Err(err) => break 'error err,
1274 };
1275
1276 #[cfg(feature = "trace")]
1277 if let Some(ref mut trace) = *device.trace.lock() {
1278 trace.add(trace::Action::CreateQuerySet {
1279 id: query_set.to_trace(),
1280 desc: desc.clone(),
1281 });
1282 }
1283
1284 let id = fid.assign(Fallible::Valid(query_set));
1285 api_log!("Device::create_query_set -> {id:?}");
1286
1287 return (id, None);
1288 };
1289
1290 let id = fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string())));
1291 (id, Some(error))
1292 }
1293
1294 pub fn query_set_drop(&self, query_set_id: id::QuerySetId) {
1295 profiling::scope!("QuerySet::drop");
1296 api_log!("QuerySet::drop {query_set_id:?}");
1297
1298 let hub = &self.hub;
1299
1300 let _query_set = hub.query_sets.remove(query_set_id);
1301
1302 #[cfg(feature = "trace")]
1303 if let Ok(query_set) = _query_set.get() {
1304 if let Some(trace) = query_set.device.trace.lock().as_mut() {
1305 trace.add(trace::Action::DestroyQuerySet(query_set.to_trace()));
1306 }
1307 }
1308 }
1309
1310 pub fn device_create_render_pipeline(
1311 &self,
1312 device_id: DeviceId,
1313 desc: &pipeline::RenderPipelineDescriptor,
1314 id_in: Option<id::RenderPipelineId>,
1315 ) -> (
1316 id::RenderPipelineId,
1317 Option<pipeline::CreateRenderPipelineError>,
1318 ) {
1319 profiling::scope!("Device::create_render_pipeline");
1320
1321 let hub = &self.hub;
1322
1323 let fid = hub.render_pipelines.prepare(id_in);
1324
1325 let device = self.hub.devices.get(device_id);
1326
1327 self.device_create_general_render_pipeline(desc.clone().into(), device, fid)
1328 }
1329
1330 pub fn device_create_mesh_pipeline(
1331 &self,
1332 device_id: DeviceId,
1333 desc: &pipeline::MeshPipelineDescriptor,
1334 id_in: Option<id::RenderPipelineId>,
1335 ) -> (
1336 id::RenderPipelineId,
1337 Option<pipeline::CreateRenderPipelineError>,
1338 ) {
1339 let hub = &self.hub;
1340
1341 let fid = hub.render_pipelines.prepare(id_in);
1342
1343 let device = self.hub.devices.get(device_id);
1344 self.device_create_general_render_pipeline(desc.clone().into(), device, fid)
1345 }
1346
1347 fn device_create_general_render_pipeline(
1348 &self,
1349 desc: pipeline::GeneralRenderPipelineDescriptor,
1350 device: Arc<crate::device::resource::Device>,
1351 fid: crate::registry::FutureId<Fallible<pipeline::RenderPipeline>>,
1352 ) -> (
1353 id::RenderPipelineId,
1354 Option<pipeline::CreateRenderPipelineError>,
1355 ) {
1356 profiling::scope!("Device::create_general_render_pipeline");
1357
1358 let hub = &self.hub;
1359
1360 let error = 'error: {
1361 if let Err(e) = device.check_is_valid() {
1362 break 'error e.into();
1363 }
1364
1365 let layout = desc
1366 .layout
1367 .map(|layout| hub.pipeline_layouts.get(layout).get())
1368 .transpose();
1369 let layout = match layout {
1370 Ok(layout) => layout,
1371 Err(e) => break 'error e.into(),
1372 };
1373
1374 let cache = desc
1375 .cache
1376 .map(|cache| hub.pipeline_caches.get(cache).get())
1377 .transpose();
1378 let cache = match cache {
1379 Ok(cache) => cache,
1380 Err(e) => break 'error e.into(),
1381 };
1382
1383 let vertex = match desc.vertex {
1384 RenderPipelineVertexProcessor::Vertex(ref vertex) => {
1385 let module = hub
1386 .shader_modules
1387 .get(vertex.stage.module)
1388 .get()
1389 .map_err(|e| pipeline::CreateRenderPipelineError::Stage {
1390 stage: wgt::ShaderStages::VERTEX,
1391 error: e.into(),
1392 });
1393 let module = match module {
1394 Ok(module) => module,
1395 Err(e) => break 'error e,
1396 };
1397 let stage = ResolvedProgrammableStageDescriptor {
1398 module,
1399 entry_point: vertex.stage.entry_point.clone(),
1400 constants: vertex.stage.constants.clone(),
1401 zero_initialize_workgroup_memory: vertex
1402 .stage
1403 .zero_initialize_workgroup_memory,
1404 };
1405 RenderPipelineVertexProcessor::Vertex(ResolvedVertexState {
1406 stage,
1407 buffers: vertex.buffers.clone(),
1408 })
1409 }
1410 RenderPipelineVertexProcessor::Mesh(ref task, ref mesh) => {
1411 let task_module = if let Some(task) = task {
1412 let module = hub
1413 .shader_modules
1414 .get(task.stage.module)
1415 .get()
1416 .map_err(|e| pipeline::CreateRenderPipelineError::Stage {
1417 stage: wgt::ShaderStages::VERTEX,
1418 error: e.into(),
1419 });
1420 let module = match module {
1421 Ok(module) => module,
1422 Err(e) => break 'error e,
1423 };
1424 let state = ResolvedProgrammableStageDescriptor {
1425 module,
1426 entry_point: task.stage.entry_point.clone(),
1427 constants: task.stage.constants.clone(),
1428 zero_initialize_workgroup_memory: task
1429 .stage
1430 .zero_initialize_workgroup_memory,
1431 };
1432 Some(ResolvedTaskState { stage: state })
1433 } else {
1434 None
1435 };
1436 let mesh_module =
1437 hub.shader_modules
1438 .get(mesh.stage.module)
1439 .get()
1440 .map_err(|e| pipeline::CreateRenderPipelineError::Stage {
1441 stage: wgt::ShaderStages::MESH,
1442 error: e.into(),
1443 });
1444 let mesh_module = match mesh_module {
1445 Ok(module) => module,
1446 Err(e) => break 'error e,
1447 };
1448 let mesh_stage = ResolvedProgrammableStageDescriptor {
1449 module: mesh_module,
1450 entry_point: mesh.stage.entry_point.clone(),
1451 constants: mesh.stage.constants.clone(),
1452 zero_initialize_workgroup_memory: mesh
1453 .stage
1454 .zero_initialize_workgroup_memory,
1455 };
1456 RenderPipelineVertexProcessor::Mesh(
1457 task_module,
1458 ResolvedMeshState { stage: mesh_stage },
1459 )
1460 }
1461 };
1462
1463 let fragment = if let Some(ref state) = desc.fragment {
1464 let module = hub
1465 .shader_modules
1466 .get(state.stage.module)
1467 .get()
1468 .map_err(|e| pipeline::CreateRenderPipelineError::Stage {
1469 stage: wgt::ShaderStages::FRAGMENT,
1470 error: e.into(),
1471 });
1472 let module = match module {
1473 Ok(module) => module,
1474 Err(e) => break 'error e,
1475 };
1476 let stage = ResolvedProgrammableStageDescriptor {
1477 module,
1478 entry_point: state.stage.entry_point.clone(),
1479 constants: state.stage.constants.clone(),
1480 zero_initialize_workgroup_memory: state.stage.zero_initialize_workgroup_memory,
1481 };
1482 Some(ResolvedFragmentState {
1483 stage,
1484 targets: state.targets.clone(),
1485 })
1486 } else {
1487 None
1488 };
1489
1490 let desc = ResolvedGeneralRenderPipelineDescriptor {
1491 label: desc.label.clone(),
1492 layout,
1493 vertex,
1494 primitive: desc.primitive,
1495 depth_stencil: desc.depth_stencil.clone(),
1496 multisample: desc.multisample,
1497 fragment,
1498 multiview_mask: desc.multiview_mask,
1499 cache,
1500 };
1501
1502 #[cfg(feature = "trace")]
1503 let trace_desc = desc.clone().into_trace();
1504
1505 let pipeline = match device.create_render_pipeline(desc) {
1506 Ok(pair) => pair,
1507 Err(e) => break 'error e,
1508 };
1509
1510 #[cfg(feature = "trace")]
1511 if let Some(ref mut trace) = *device.trace.lock() {
1512 trace.add(trace::Action::CreateGeneralRenderPipeline {
1513 id: pipeline.to_trace(),
1514 desc: trace_desc,
1515 });
1516 }
1517
1518 let id = fid.assign(Fallible::Valid(pipeline));
1519 api_log!("Device::create_render_pipeline -> {id:?}");
1520
1521 return (id, None);
1522 };
1523
1524 let id = fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string())));
1525
1526 (id, Some(error))
1527 }
1528
1529 pub fn render_pipeline_get_bind_group_layout(
1532 &self,
1533 pipeline_id: id::RenderPipelineId,
1534 index: u32,
1535 id_in: Option<id::BindGroupLayoutId>,
1536 ) -> (
1537 id::BindGroupLayoutId,
1538 Option<binding_model::GetBindGroupLayoutError>,
1539 ) {
1540 let hub = &self.hub;
1541
1542 let fid = hub.bind_group_layouts.prepare(id_in);
1543
1544 let error = 'error: {
1545 let pipeline = match hub.render_pipelines.get(pipeline_id).get() {
1546 Ok(pipeline) => pipeline,
1547 Err(e) => break 'error e.into(),
1548 };
1549 let id = match pipeline.layout.bind_group_layouts.get(index as usize) {
1550 Some(bg) => fid.assign(Fallible::Valid(bg.clone())),
1551 None => {
1552 break 'error binding_model::GetBindGroupLayoutError::InvalidGroupIndex(index)
1553 }
1554 };
1555 return (id, None);
1556 };
1557
1558 let id = fid.assign(Fallible::Invalid(Arc::new(String::new())));
1559 (id, Some(error))
1560 }
1561
1562 pub fn render_pipeline_drop(&self, render_pipeline_id: id::RenderPipelineId) {
1563 profiling::scope!("RenderPipeline::drop");
1564 api_log!("RenderPipeline::drop {render_pipeline_id:?}");
1565
1566 let hub = &self.hub;
1567
1568 let _pipeline = hub.render_pipelines.remove(render_pipeline_id);
1569
1570 #[cfg(feature = "trace")]
1571 if let Ok(pipeline) = _pipeline.get() {
1572 if let Some(t) = pipeline.device.trace.lock().as_mut() {
1573 t.add(trace::Action::DestroyRenderPipeline(pipeline.to_trace()));
1574 }
1575 }
1576 }
1577
1578 pub fn device_create_compute_pipeline(
1579 &self,
1580 device_id: DeviceId,
1581 desc: &pipeline::ComputePipelineDescriptor,
1582 id_in: Option<id::ComputePipelineId>,
1583 ) -> (
1584 id::ComputePipelineId,
1585 Option<pipeline::CreateComputePipelineError>,
1586 ) {
1587 profiling::scope!("Device::create_compute_pipeline");
1588
1589 let hub = &self.hub;
1590
1591 let fid = hub.compute_pipelines.prepare(id_in);
1592
1593 let error = 'error: {
1594 let device = self.hub.devices.get(device_id);
1595
1596 if let Err(e) = device.check_is_valid() {
1597 break 'error e.into();
1598 }
1599
1600 let layout = desc
1601 .layout
1602 .map(|layout| hub.pipeline_layouts.get(layout).get())
1603 .transpose();
1604 let layout = match layout {
1605 Ok(layout) => layout,
1606 Err(e) => break 'error e.into(),
1607 };
1608
1609 let cache = desc
1610 .cache
1611 .map(|cache| hub.pipeline_caches.get(cache).get())
1612 .transpose();
1613 let cache = match cache {
1614 Ok(cache) => cache,
1615 Err(e) => break 'error e.into(),
1616 };
1617
1618 let module = hub.shader_modules.get(desc.stage.module).get();
1619 let module = match module {
1620 Ok(module) => module,
1621 Err(e) => break 'error e.into(),
1622 };
1623 let stage = ResolvedProgrammableStageDescriptor {
1624 module,
1625 entry_point: desc.stage.entry_point.clone(),
1626 constants: desc.stage.constants.clone(),
1627 zero_initialize_workgroup_memory: desc.stage.zero_initialize_workgroup_memory,
1628 };
1629
1630 let desc = ResolvedComputePipelineDescriptor {
1631 label: desc.label.clone(),
1632 layout,
1633 stage,
1634 cache,
1635 };
1636
1637 #[cfg(feature = "trace")]
1638 let trace_desc = desc.clone().into_trace();
1639
1640 let pipeline = match device.create_compute_pipeline(desc) {
1641 Ok(pair) => pair,
1642 Err(e) => break 'error e,
1643 };
1644
1645 #[cfg(feature = "trace")]
1646 if let Some(ref mut trace) = *device.trace.lock() {
1647 trace.add(trace::Action::CreateComputePipeline {
1648 id: pipeline.to_trace(),
1649 desc: trace_desc,
1650 });
1651 }
1652
1653 let id = fid.assign(Fallible::Valid(pipeline));
1654 api_log!("Device::create_compute_pipeline -> {id:?}");
1655
1656 return (id, None);
1657 };
1658
1659 let id = fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string())));
1660
1661 (id, Some(error))
1662 }
1663
1664 pub fn compute_pipeline_get_bind_group_layout(
1667 &self,
1668 pipeline_id: id::ComputePipelineId,
1669 index: u32,
1670 id_in: Option<id::BindGroupLayoutId>,
1671 ) -> (
1672 id::BindGroupLayoutId,
1673 Option<binding_model::GetBindGroupLayoutError>,
1674 ) {
1675 let hub = &self.hub;
1676
1677 let fid = hub.bind_group_layouts.prepare(id_in);
1678
1679 let error = 'error: {
1680 let pipeline = match hub.compute_pipelines.get(pipeline_id).get() {
1681 Ok(pipeline) => pipeline,
1682 Err(e) => break 'error e.into(),
1683 };
1684
1685 let id = match pipeline.layout.bind_group_layouts.get(index as usize) {
1686 Some(bg) => fid.assign(Fallible::Valid(bg.clone())),
1687 None => {
1688 break 'error binding_model::GetBindGroupLayoutError::InvalidGroupIndex(index)
1689 }
1690 };
1691
1692 return (id, None);
1693 };
1694
1695 let id = fid.assign(Fallible::Invalid(Arc::new(String::new())));
1696 (id, Some(error))
1697 }
1698
1699 pub fn compute_pipeline_drop(&self, compute_pipeline_id: id::ComputePipelineId) {
1700 profiling::scope!("ComputePipeline::drop");
1701 api_log!("ComputePipeline::drop {compute_pipeline_id:?}");
1702
1703 let hub = &self.hub;
1704
1705 let _pipeline = hub.compute_pipelines.remove(compute_pipeline_id);
1706
1707 #[cfg(feature = "trace")]
1708 if let Ok(pipeline) = _pipeline.get() {
1709 if let Some(t) = pipeline.device.trace.lock().as_mut() {
1710 t.add(trace::Action::DestroyComputePipeline(pipeline.to_trace()));
1711 }
1712 }
1713 }
1714
1715 pub unsafe fn device_create_pipeline_cache(
1719 &self,
1720 device_id: DeviceId,
1721 desc: &pipeline::PipelineCacheDescriptor<'_>,
1722 id_in: Option<id::PipelineCacheId>,
1723 ) -> (
1724 id::PipelineCacheId,
1725 Option<pipeline::CreatePipelineCacheError>,
1726 ) {
1727 profiling::scope!("Device::create_pipeline_cache");
1728
1729 let hub = &self.hub;
1730
1731 let fid = hub.pipeline_caches.prepare(id_in);
1732 let error: pipeline::CreatePipelineCacheError = 'error: {
1733 let device = self.hub.devices.get(device_id);
1734
1735 let cache = unsafe { device.create_pipeline_cache(desc) };
1736 match cache {
1737 Ok(cache) => {
1738 #[cfg(feature = "trace")]
1739 if let Some(ref mut trace) = *device.trace.lock() {
1740 trace.add(trace::Action::CreatePipelineCache {
1741 id: cache.to_trace(),
1742 desc: desc.clone(),
1743 });
1744 }
1745
1746 let id = fid.assign(Fallible::Valid(cache));
1747 api_log!("Device::create_pipeline_cache -> {id:?}");
1748 return (id, None);
1749 }
1750 Err(e) => break 'error e,
1751 }
1752 };
1753
1754 let id = fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string())));
1755
1756 (id, Some(error))
1757 }
1758
1759 pub fn pipeline_cache_drop(&self, pipeline_cache_id: id::PipelineCacheId) {
1760 profiling::scope!("PipelineCache::drop");
1761 api_log!("PipelineCache::drop {pipeline_cache_id:?}");
1762
1763 let hub = &self.hub;
1764
1765 let _cache = hub.pipeline_caches.remove(pipeline_cache_id);
1766
1767 #[cfg(feature = "trace")]
1768 if let Ok(cache) = _cache.get() {
1769 if let Some(t) = cache.device.trace.lock().as_mut() {
1770 t.add(trace::Action::DestroyPipelineCache(cache.to_trace()));
1771 }
1772 }
1773 }
1774
1775 pub fn surface_configure(
1776 &self,
1777 surface_id: SurfaceId,
1778 device_id: DeviceId,
1779 config: &wgt::SurfaceConfiguration<Vec<TextureFormat>>,
1780 ) -> Option<present::ConfigureSurfaceError> {
1781 let device = self.hub.devices.get(device_id);
1782 let surface = self.surfaces.get(surface_id);
1783
1784 #[cfg(feature = "trace")]
1785 if let Some(ref mut trace) = *device.trace.lock() {
1786 trace.add(trace::Action::ConfigureSurface(
1787 surface.to_trace(),
1788 config.clone(),
1789 ));
1790 }
1791
1792 device.configure_surface(&surface, config)
1793 }
1794
1795 pub fn device_poll(
1799 &self,
1800 device_id: DeviceId,
1801 poll_type: wgt::PollType<crate::SubmissionIndex>,
1802 ) -> Result<wgt::PollStatus, WaitIdleError> {
1803 api_log!("Device::poll {poll_type:?}");
1804
1805 let device = self.hub.devices.get(device_id);
1806
1807 let (closures, result) = device.poll_and_return_closures(poll_type);
1808
1809 closures.fire();
1810
1811 result
1812 }
1813
1814 fn poll_all_devices_of_api(
1821 &self,
1822 force_wait: bool,
1823 closure_list: &mut UserClosures,
1824 ) -> Result<bool, WaitIdleError> {
1825 profiling::scope!("poll_device");
1826
1827 let hub = &self.hub;
1828 let mut all_queue_empty = true;
1829 {
1830 let device_guard = hub.devices.read();
1831
1832 for (_id, device) in device_guard.iter() {
1833 let poll_type = if force_wait {
1834 wgt::PollType::wait_indefinitely()
1836 } else {
1837 wgt::PollType::Poll
1838 };
1839
1840 let (closures, result) = device.poll_and_return_closures(poll_type);
1841
1842 let is_queue_empty = matches!(result, Ok(wgt::PollStatus::QueueEmpty));
1843
1844 all_queue_empty &= is_queue_empty;
1845
1846 closure_list.extend(closures);
1847 }
1848 }
1849
1850 Ok(all_queue_empty)
1851 }
1852
1853 pub fn poll_all_devices(&self, force_wait: bool) -> Result<bool, WaitIdleError> {
1860 api_log!("poll_all_devices");
1861 let mut closures = UserClosures::default();
1862 let all_queue_empty = self.poll_all_devices_of_api(force_wait, &mut closures)?;
1863
1864 closures.fire();
1865
1866 Ok(all_queue_empty)
1867 }
1868
1869 pub unsafe fn device_start_graphics_debugger_capture(&self, device_id: DeviceId) {
1875 unsafe {
1876 self.hub
1877 .devices
1878 .get(device_id)
1879 .start_graphics_debugger_capture();
1880 }
1881 }
1882
1883 pub unsafe fn device_stop_graphics_debugger_capture(&self, device_id: DeviceId) {
1889 unsafe {
1890 self.hub
1891 .devices
1892 .get(device_id)
1893 .stop_graphics_debugger_capture();
1894 }
1895 }
1896
1897 pub fn pipeline_cache_get_data(&self, id: id::PipelineCacheId) -> Option<Vec<u8>> {
1898 use crate::pipeline_cache;
1899 api_log!("PipelineCache::get_data");
1900 let hub = &self.hub;
1901
1902 if let Ok(cache) = hub.pipeline_caches.get(id).get() {
1903 if !cache.device.is_valid() {
1905 return None;
1906 }
1907 let mut vec = unsafe { cache.device.raw().pipeline_cache_get_data(cache.raw()) }?;
1908 let validation_key = cache.device.raw().pipeline_cache_validation_key()?;
1909
1910 let mut header_contents = [0; pipeline_cache::HEADER_LENGTH];
1911 pipeline_cache::add_cache_header(
1912 &mut header_contents,
1913 &vec,
1914 &cache.device.adapter.raw.info,
1915 validation_key,
1916 );
1917
1918 let deleted = vec.splice(..0, header_contents).collect::<Vec<_>>();
1919 debug_assert!(deleted.is_empty());
1920
1921 return Some(vec);
1922 }
1923 None
1924 }
1925
1926 pub fn device_drop(&self, device_id: DeviceId) {
1927 profiling::scope!("Device::drop");
1928 api_log!("Device::drop {device_id:?}");
1929
1930 self.hub.devices.remove(device_id);
1931 }
1932
1933 pub fn device_set_device_lost_closure(
1935 &self,
1936 device_id: DeviceId,
1937 device_lost_closure: DeviceLostClosure,
1938 ) {
1939 let device = self.hub.devices.get(device_id);
1940
1941 device
1942 .device_lost_closure
1943 .lock()
1944 .replace(device_lost_closure);
1945 }
1946
1947 pub fn device_destroy(&self, device_id: DeviceId) {
1948 api_log!("Device::destroy {device_id:?}");
1949
1950 let device = self.hub.devices.get(device_id);
1951
1952 if !device.is_valid() {
1958 return;
1959 }
1960
1961 device.valid.store(false, Ordering::Release);
1969 }
1970
1971 pub fn device_get_internal_counters(&self, device_id: DeviceId) -> wgt::InternalCounters {
1972 let device = self.hub.devices.get(device_id);
1973 wgt::InternalCounters {
1974 hal: device.get_hal_counters(),
1975 core: wgt::CoreCounters {},
1976 }
1977 }
1978
1979 pub fn device_generate_allocator_report(
1980 &self,
1981 device_id: DeviceId,
1982 ) -> Option<wgt::AllocatorReport> {
1983 let device = self.hub.devices.get(device_id);
1984 device.generate_allocator_report()
1985 }
1986
1987 pub fn queue_drop(&self, queue_id: QueueId) {
1988 profiling::scope!("Queue::drop");
1989 api_log!("Queue::drop {queue_id:?}");
1990
1991 self.hub.queues.remove(queue_id);
1992 }
1993
1994 pub fn buffer_map_async(
1996 &self,
1997 buffer_id: id::BufferId,
1998 offset: BufferAddress,
1999 size: Option<BufferAddress>,
2000 op: BufferMapOperation,
2001 ) -> Result<crate::SubmissionIndex, BufferAccessError> {
2002 profiling::scope!("Buffer::map_async");
2003 api_log!("Buffer::map_async {buffer_id:?} offset {offset:?} size {size:?} op: {op:?}");
2004
2005 let hub = &self.hub;
2006
2007 let map_result = match hub.buffers.get(buffer_id).get() {
2008 Ok(buffer) => buffer.map_async(offset, size, op),
2009 Err(e) => Err((op, e.into())),
2010 };
2011
2012 match map_result {
2013 Ok(submission_index) => Ok(submission_index),
2014 Err((mut operation, err)) => {
2015 if let Some(callback) = operation.callback.take() {
2016 callback(Err(err.clone()));
2017 }
2018 Err(err)
2019 }
2020 }
2021 }
2022
2023 pub fn buffer_get_mapped_range(
2024 &self,
2025 buffer_id: id::BufferId,
2026 offset: BufferAddress,
2027 size: Option<BufferAddress>,
2028 ) -> Result<(NonNull<u8>, u64), BufferAccessError> {
2029 profiling::scope!("Buffer::get_mapped_range");
2030 api_log!("Buffer::get_mapped_range {buffer_id:?} offset {offset:?} size {size:?}");
2031
2032 let hub = &self.hub;
2033
2034 let buffer = hub.buffers.get(buffer_id).get()?;
2035
2036 buffer.get_mapped_range(offset, size)
2037 }
2038
2039 pub fn buffer_unmap(&self, buffer_id: id::BufferId) -> BufferAccessResult {
2040 profiling::scope!("unmap", "Buffer");
2041 api_log!("Buffer::unmap {buffer_id:?}");
2042
2043 let hub = &self.hub;
2044
2045 let buffer = hub.buffers.get(buffer_id).get()?;
2046
2047 let snatch_guard = buffer.device.snatchable_lock.read();
2048 buffer.check_destroyed(&snatch_guard)?;
2049 drop(snatch_guard);
2050
2051 buffer.device.check_is_valid()?;
2052 buffer.unmap()
2053 }
2054}