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