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