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(&self, texture_view_id: id::TextureViewId) {
485 profiling::scope!("TextureView::drop");
486 api_log!("TextureView::drop {texture_view_id:?}");
487
488 let hub = &self.hub;
489
490 let _view = hub.texture_views.remove(texture_view_id);
491
492 #[cfg(feature = "trace")]
493 if let Ok(view) = _view.get() {
494 if let Some(t) = view.device.trace.lock().as_mut() {
495 t.add(trace::Action::DestroyTextureView(view.to_trace()));
496 }
497 }
498 }
499
500 pub fn device_create_external_texture(
501 &self,
502 device_id: DeviceId,
503 desc: &resource::ExternalTextureDescriptor,
504 planes: &[id::TextureViewId],
505 id_in: Option<id::ExternalTextureId>,
506 ) -> (
507 id::ExternalTextureId,
508 Option<resource::CreateExternalTextureError>,
509 ) {
510 profiling::scope!("Device::create_external_texture");
511
512 let hub = &self.hub;
513
514 let fid = hub.external_textures.prepare(id_in);
515
516 let error = 'error: {
517 let device = self.hub.devices.get(device_id);
518
519 let planes = planes
520 .iter()
521 .map(|plane_id| self.hub.texture_views.get(*plane_id).get())
522 .collect::<Result<Vec<_>, _>>();
523 let planes = match planes {
524 Ok(planes) => planes,
525 Err(error) => break 'error error.into(),
526 };
527
528 let external_texture = match device.create_external_texture(desc, &planes) {
529 Ok(external_texture) => external_texture,
530 Err(error) => break 'error error,
531 };
532
533 #[cfg(feature = "trace")]
534 if let Some(ref mut trace) = *device.trace.lock() {
535 let planes = Box::from(
536 planes
537 .into_iter()
538 .map(|plane| plane.to_trace())
539 .collect::<Vec<_>>(),
540 );
541 trace.add(trace::Action::CreateExternalTexture {
542 id: external_texture.to_trace(),
543 desc: desc.clone(),
544 planes,
545 });
546 }
547
548 let id = fid.assign(Fallible::Valid(external_texture));
549 api_log!("Device::create_external_texture({desc:?}) -> {id:?}");
550
551 return (id, None);
552 };
553
554 let id = fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string())));
555 (id, Some(error))
556 }
557
558 pub fn external_texture_destroy(&self, external_texture_id: id::ExternalTextureId) {
559 profiling::scope!("ExternalTexture::destroy");
560 api_log!("ExternalTexture::destroy {external_texture_id:?}");
561
562 let hub = &self.hub;
563
564 let Ok(external_texture) = hub.external_textures.get(external_texture_id).get() else {
565 return;
567 };
568
569 #[cfg(feature = "trace")]
570 if let Some(trace) = external_texture.device.trace.lock().as_mut() {
571 trace.add(trace::Action::FreeExternalTexture(
572 external_texture.to_trace(),
573 ));
574 }
575
576 external_texture.destroy();
577 }
578
579 pub fn external_texture_drop(&self, external_texture_id: id::ExternalTextureId) {
580 profiling::scope!("ExternalTexture::drop");
581 api_log!("ExternalTexture::drop {external_texture_id:?}");
582
583 let hub = &self.hub;
584
585 let _external_texture = hub.external_textures.remove(external_texture_id);
586
587 #[cfg(feature = "trace")]
588 if let Ok(external_texture) = _external_texture.get() {
589 if let Some(t) = external_texture.device.trace.lock().as_mut() {
590 t.add(trace::Action::DestroyExternalTexture(
591 external_texture.to_trace(),
592 ));
593 }
594 }
595 }
596
597 pub fn device_create_sampler(
598 &self,
599 device_id: DeviceId,
600 desc: &resource::SamplerDescriptor,
601 id_in: Option<id::SamplerId>,
602 ) -> (id::SamplerId, Option<resource::CreateSamplerError>) {
603 profiling::scope!("Device::create_sampler");
604
605 let hub = &self.hub;
606 let fid = hub.samplers.prepare(id_in);
607
608 let error = 'error: {
609 let device = self.hub.devices.get(device_id);
610
611 let sampler = match device.create_sampler(desc) {
612 Ok(sampler) => sampler,
613 Err(e) => break 'error e,
614 };
615
616 #[cfg(feature = "trace")]
617 if let Some(ref mut trace) = *device.trace.lock() {
618 trace.add(trace::Action::CreateSampler(
619 sampler.to_trace(),
620 desc.clone(),
621 ));
622 }
623
624 let id = fid.assign(Fallible::Valid(sampler));
625 api_log!("Device::create_sampler -> {id:?}");
626
627 return (id, None);
628 };
629
630 let id = fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string())));
631 (id, Some(error))
632 }
633
634 pub fn sampler_drop(&self, sampler_id: id::SamplerId) {
635 profiling::scope!("Sampler::drop");
636 api_log!("Sampler::drop {sampler_id:?}");
637
638 let hub = &self.hub;
639
640 let _sampler = hub.samplers.remove(sampler_id);
641
642 #[cfg(feature = "trace")]
643 if let Ok(sampler) = _sampler.get() {
644 if let Some(t) = sampler.device.trace.lock().as_mut() {
645 t.add(trace::Action::DestroySampler(sampler.to_trace()));
646 }
647 }
648 }
649
650 pub fn device_create_bind_group_layout(
651 &self,
652 device_id: DeviceId,
653 desc: &binding_model::BindGroupLayoutDescriptor,
654 id_in: Option<id::BindGroupLayoutId>,
655 ) -> (
656 id::BindGroupLayoutId,
657 Option<binding_model::CreateBindGroupLayoutError>,
658 ) {
659 profiling::scope!("Device::create_bind_group_layout");
660
661 let hub = &self.hub;
662 let fid = hub.bind_group_layouts.prepare(id_in);
663
664 let error = 'error: {
665 let device = self.hub.devices.get(device_id);
666
667 let layout = match device.create_bind_group_layout(desc) {
668 Ok(layout) => layout,
669 Err(e) => break 'error e,
670 };
671
672 #[cfg(feature = "trace")]
673 if let Some(ref mut trace) = *device.trace.lock() {
674 trace.add(trace::Action::CreateBindGroupLayout(
675 layout.to_trace(),
676 desc.clone(),
677 ));
678 }
679
680 let id = fid.assign(Fallible::Valid(layout.clone()));
681
682 api_log!("Device::create_bind_group_layout -> {id:?}");
683 return (id, None);
684 };
685
686 let id = fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string())));
687 (id, Some(error))
688 }
689
690 pub fn bind_group_layout_drop(&self, bind_group_layout_id: id::BindGroupLayoutId) {
691 profiling::scope!("BindGroupLayout::drop");
692 api_log!("BindGroupLayout::drop {bind_group_layout_id:?}");
693
694 let hub = &self.hub;
695
696 let _layout = hub.bind_group_layouts.remove(bind_group_layout_id);
697
698 #[cfg(feature = "trace")]
699 if let Ok(layout) = _layout.get() {
700 if let Some(t) = layout.device.trace.lock().as_mut() {
701 t.add(trace::Action::DestroyBindGroupLayout(layout.to_trace()));
702 }
703 }
704 }
705
706 pub fn device_create_pipeline_layout(
707 &self,
708 device_id: DeviceId,
709 desc: &binding_model::PipelineLayoutDescriptor,
710 id_in: Option<id::PipelineLayoutId>,
711 ) -> (
712 id::PipelineLayoutId,
713 Option<binding_model::CreatePipelineLayoutError>,
714 ) {
715 profiling::scope!("Device::create_pipeline_layout");
716
717 let hub = &self.hub;
718 let fid = hub.pipeline_layouts.prepare(id_in);
719
720 let error = 'error: {
721 let device = self.hub.devices.get(device_id);
722
723 if let Err(e) = device.check_is_valid() {
724 break 'error e.into();
725 }
726
727 let bind_group_layouts = {
728 let bind_group_layouts_guard = hub.bind_group_layouts.read();
729 desc.bind_group_layouts
730 .iter()
731 .map(|bgl_id| match bgl_id {
732 Some(bgl_id) => bind_group_layouts_guard.get(*bgl_id).get().map(Some),
733 None => Ok(None),
734 })
735 .collect::<Result<Vec<_>, _>>()
736 };
737
738 let bind_group_layouts = match bind_group_layouts {
739 Ok(bind_group_layouts) => bind_group_layouts,
740 Err(e) => break 'error e.into(),
741 };
742
743 let desc = binding_model::ResolvedPipelineLayoutDescriptor {
744 label: desc.label.clone(),
745 bind_group_layouts: Cow::Owned(bind_group_layouts),
746 immediate_size: desc.immediate_size,
747 };
748
749 let layout = match device.create_pipeline_layout(&desc) {
750 Ok(layout) => layout,
751 Err(e) => break 'error e,
752 };
753
754 #[cfg(feature = "trace")]
755 if let Some(ref mut trace) = *device.trace.lock() {
756 trace.add(trace::Action::CreatePipelineLayout(
757 layout.to_trace(),
758 desc.to_trace(),
759 ));
760 }
761
762 let id = fid.assign(Fallible::Valid(layout));
763 api_log!("Device::create_pipeline_layout -> {id:?}");
764 return (id, None);
765 };
766
767 let id = fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string())));
768 (id, Some(error))
769 }
770
771 pub fn pipeline_layout_drop(&self, pipeline_layout_id: id::PipelineLayoutId) {
772 profiling::scope!("PipelineLayout::drop");
773 api_log!("PipelineLayout::drop {pipeline_layout_id:?}");
774
775 let hub = &self.hub;
776
777 let _layout = hub.pipeline_layouts.remove(pipeline_layout_id);
778
779 #[cfg(feature = "trace")]
780 if let Ok(layout) = _layout.get() {
781 if let Some(t) = layout.device.trace.lock().as_mut() {
782 t.add(trace::Action::DestroyPipelineLayout(layout.to_trace()));
783 }
784 }
785 }
786
787 pub fn device_create_bind_group(
788 &self,
789 device_id: DeviceId,
790 desc: &binding_model::BindGroupDescriptor,
791 id_in: Option<id::BindGroupId>,
792 ) -> (id::BindGroupId, Option<binding_model::CreateBindGroupError>) {
793 profiling::scope!("Device::create_bind_group");
794
795 let hub = &self.hub;
796 let fid = hub.bind_groups.prepare(id_in);
797
798 let error = 'error: {
799 let device = self.hub.devices.get(device_id);
800
801 if let Err(e) = device.check_is_valid() {
802 break 'error e.into();
803 }
804
805 let layout = match hub.bind_group_layouts.get(desc.layout).get() {
806 Ok(layout) => layout,
807 Err(e) => break 'error e.into(),
808 };
809
810 fn resolve_entry<'a>(
811 e: &BindGroupEntry<'a>,
812 buffer_storage: &Storage<Fallible<resource::Buffer>>,
813 sampler_storage: &Storage<Fallible<resource::Sampler>>,
814 texture_view_storage: &Storage<Fallible<resource::TextureView>>,
815 tlas_storage: &Storage<Fallible<resource::Tlas>>,
816 external_texture_storage: &Storage<Fallible<resource::ExternalTexture>>,
817 ) -> Result<ResolvedBindGroupEntry<'a>, binding_model::CreateBindGroupError>
818 {
819 let resolve_buffer = |bb: &BufferBinding| {
820 buffer_storage
821 .get(bb.buffer)
822 .get()
823 .map(|buffer| ResolvedBufferBinding {
824 buffer,
825 offset: bb.offset,
826 size: bb.size,
827 })
828 .map_err(binding_model::CreateBindGroupError::from)
829 };
830 let resolve_sampler = |id: &id::SamplerId| {
831 sampler_storage
832 .get(*id)
833 .get()
834 .map_err(binding_model::CreateBindGroupError::from)
835 };
836 let resolve_view = |id: &id::TextureViewId| {
837 texture_view_storage
838 .get(*id)
839 .get()
840 .map_err(binding_model::CreateBindGroupError::from)
841 };
842 let resolve_tlas = |id: &id::TlasId| {
843 tlas_storage
844 .get(*id)
845 .get()
846 .map_err(binding_model::CreateBindGroupError::from)
847 };
848 let resolve_external_texture = |id: &id::ExternalTextureId| {
849 external_texture_storage
850 .get(*id)
851 .get()
852 .map_err(binding_model::CreateBindGroupError::from)
853 };
854 let resource = match e.resource {
855 BindingResource::Buffer(ref buffer) => {
856 ResolvedBindingResource::Buffer(resolve_buffer(buffer)?)
857 }
858 BindingResource::BufferArray(ref buffers) => {
859 let buffers = buffers
860 .iter()
861 .map(resolve_buffer)
862 .collect::<Result<Vec<_>, _>>()?;
863 ResolvedBindingResource::BufferArray(Cow::Owned(buffers))
864 }
865 BindingResource::Sampler(ref sampler) => {
866 ResolvedBindingResource::Sampler(resolve_sampler(sampler)?)
867 }
868 BindingResource::SamplerArray(ref samplers) => {
869 let samplers = samplers
870 .iter()
871 .map(resolve_sampler)
872 .collect::<Result<Vec<_>, _>>()?;
873 ResolvedBindingResource::SamplerArray(Cow::Owned(samplers))
874 }
875 BindingResource::TextureView(ref view) => {
876 ResolvedBindingResource::TextureView(resolve_view(view)?)
877 }
878 BindingResource::TextureViewArray(ref views) => {
879 let views = views
880 .iter()
881 .map(resolve_view)
882 .collect::<Result<Vec<_>, _>>()?;
883 ResolvedBindingResource::TextureViewArray(Cow::Owned(views))
884 }
885 BindingResource::AccelerationStructure(ref tlas) => {
886 ResolvedBindingResource::AccelerationStructure(resolve_tlas(tlas)?)
887 }
888 BindingResource::AccelerationStructureArray(ref tlas_array) => {
889 let tlas_array = tlas_array
890 .iter()
891 .map(resolve_tlas)
892 .collect::<Result<Vec<_>, _>>()?;
893 ResolvedBindingResource::AccelerationStructureArray(Cow::Owned(tlas_array))
894 }
895 BindingResource::ExternalTexture(ref et) => {
896 ResolvedBindingResource::ExternalTexture(resolve_external_texture(et)?)
897 }
898 };
899 Ok(ResolvedBindGroupEntry {
900 binding: e.binding,
901 resource,
902 })
903 }
904
905 let entries = {
906 let buffer_guard = hub.buffers.read();
907 let texture_view_guard = hub.texture_views.read();
908 let sampler_guard = hub.samplers.read();
909 let tlas_guard = hub.tlas_s.read();
910 let external_texture_guard = hub.external_textures.read();
911 desc.entries
912 .iter()
913 .map(|e| {
914 resolve_entry(
915 e,
916 &buffer_guard,
917 &sampler_guard,
918 &texture_view_guard,
919 &tlas_guard,
920 &external_texture_guard,
921 )
922 })
923 .collect::<Result<Vec<_>, _>>()
924 };
925 let entries = match entries {
926 Ok(entries) => Cow::Owned(entries),
927 Err(e) => break 'error e,
928 };
929
930 let desc = ResolvedBindGroupDescriptor {
931 label: desc.label.clone(),
932 layout,
933 entries,
934 };
935 #[cfg(feature = "trace")]
936 let trace_desc = (&desc).to_trace();
937
938 let bind_group = match device.create_bind_group(desc) {
939 Ok(bind_group) => bind_group,
940 Err(e) => break 'error e,
941 };
942
943 #[cfg(feature = "trace")]
944 if let Some(ref mut trace) = *device.trace.lock() {
945 trace.add(trace::Action::CreateBindGroup(
946 bind_group.to_trace(),
947 trace_desc,
948 ));
949 }
950
951 let id = fid.assign(Fallible::Valid(bind_group));
952
953 api_log!("Device::create_bind_group -> {id:?}");
954
955 return (id, None);
956 };
957
958 let id = fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string())));
959 (id, Some(error))
960 }
961
962 pub fn bind_group_drop(&self, bind_group_id: id::BindGroupId) {
963 profiling::scope!("BindGroup::drop");
964 api_log!("BindGroup::drop {bind_group_id:?}");
965
966 let hub = &self.hub;
967
968 let _bind_group = hub.bind_groups.remove(bind_group_id);
969
970 #[cfg(feature = "trace")]
971 if let Ok(bind_group) = _bind_group.get() {
972 if let Some(t) = bind_group.device.trace.lock().as_mut() {
973 t.add(trace::Action::DestroyBindGroup(bind_group.to_trace()));
974 }
975 }
976 }
977
978 pub fn device_create_shader_module(
993 &self,
994 device_id: DeviceId,
995 desc: &pipeline::ShaderModuleDescriptor,
996 source: pipeline::ShaderModuleSource,
997 id_in: Option<id::ShaderModuleId>,
998 ) -> (
999 id::ShaderModuleId,
1000 Option<pipeline::CreateShaderModuleError>,
1001 ) {
1002 profiling::scope!("Device::create_shader_module");
1003
1004 let hub = &self.hub;
1005 let fid = hub.shader_modules.prepare(id_in);
1006
1007 let error = 'error: {
1008 let device = self.hub.devices.get(device_id);
1009
1010 #[cfg(feature = "trace")]
1011 let data = device.trace.lock().as_mut().map(|trace| {
1012 use crate::device::trace::DataKind;
1013
1014 match source {
1015 #[cfg(feature = "wgsl")]
1016 pipeline::ShaderModuleSource::Wgsl(ref code) => {
1017 trace.make_binary(DataKind::Wgsl, code.as_bytes())
1018 }
1019 #[cfg(feature = "glsl")]
1020 pipeline::ShaderModuleSource::Glsl(ref code, _) => {
1021 trace.make_binary(DataKind::Glsl, code.as_bytes())
1022 }
1023 #[cfg(feature = "spirv")]
1024 pipeline::ShaderModuleSource::SpirV(ref code, _) => {
1025 trace.make_binary(DataKind::Spv, bytemuck::cast_slice::<u32, u8>(code))
1026 }
1027 pipeline::ShaderModuleSource::Naga(ref module) => {
1028 let string =
1029 ron::ser::to_string_pretty(module, ron::ser::PrettyConfig::default())
1030 .unwrap();
1031 trace.make_binary(DataKind::Ron, string.as_bytes())
1032 }
1033 pipeline::ShaderModuleSource::Dummy(_) => {
1034 panic!("found `ShaderModuleSource::Dummy`")
1035 }
1036 }
1037 });
1038
1039 let shader = match device.create_shader_module(desc, source) {
1040 Ok(shader) => shader,
1041 Err(e) => break 'error e,
1042 };
1043
1044 #[cfg(feature = "trace")]
1045 if let Some(data) = data {
1046 device
1048 .trace
1049 .lock()
1050 .as_mut()
1051 .expect("trace went away during create_shader_module?")
1052 .add(trace::Action::CreateShaderModule {
1053 id: shader.to_trace(),
1054 desc: desc.clone(),
1055 data,
1056 });
1057 };
1058
1059 let id = fid.assign(Fallible::Valid(shader));
1060 api_log!("Device::create_shader_module -> {id:?}");
1061 return (id, None);
1062 };
1063
1064 let id = fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string())));
1065 (id, Some(error))
1066 }
1067
1068 pub unsafe fn device_create_shader_module_passthrough(
1073 &self,
1074 device_id: DeviceId,
1075 desc: &pipeline::ShaderModuleDescriptorPassthrough<'_>,
1076 id_in: Option<id::ShaderModuleId>,
1077 ) -> (
1078 id::ShaderModuleId,
1079 Option<pipeline::CreateShaderModuleError>,
1080 ) {
1081 profiling::scope!("Device::create_shader_module_passthrough");
1082
1083 let hub = &self.hub;
1084 let fid = hub.shader_modules.prepare(id_in);
1085
1086 let error = 'error: {
1087 let device = self.hub.devices.get(device_id);
1088
1089 let result = unsafe { device.create_shader_module_passthrough(desc) };
1090
1091 let shader = match result {
1092 Ok(shader) => shader,
1093 Err(e) => break 'error e,
1094 };
1095
1096 #[cfg(feature = "trace")]
1097 if let Some(ref mut trace) = *device.trace.lock() {
1098 use crate::device::trace::DataKind;
1099
1100 let mut file_names = Vec::new();
1101 for (data, kind) in [
1102 (
1103 desc.spirv.as_ref().map(|a| bytemuck::cast_slice(a)),
1104 DataKind::Spv,
1105 ),
1106 (desc.dxil.as_deref(), DataKind::Dxil),
1107 (desc.hlsl.as_ref().map(|a| a.as_bytes()), DataKind::Hlsl),
1108 (desc.metallib.as_deref(), DataKind::MetalLib),
1109 (desc.msl.as_ref().map(|a| a.as_bytes()), DataKind::Msl),
1110 (desc.glsl.as_ref().map(|a| a.as_bytes()), DataKind::Glsl),
1111 (desc.wgsl.as_ref().map(|a| a.as_bytes()), DataKind::Wgsl),
1112 ] {
1113 if let Some(data) = data {
1114 file_names.push(trace.make_binary(kind, data));
1115 }
1116 }
1117 trace.add(trace::Action::CreateShaderModulePassthrough {
1118 id: shader.to_trace(),
1119 data: file_names,
1120 label: desc.label.clone(),
1121 num_workgroups: desc.num_workgroups,
1122 });
1123 };
1124
1125 let id = fid.assign(Fallible::Valid(shader));
1126 api_log!("Device::create_shader_module_spirv -> {id:?}");
1127 return (id, None);
1128 };
1129
1130 let id = fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string())));
1131 (id, Some(error))
1132 }
1133
1134 pub fn shader_module_drop(&self, shader_module_id: id::ShaderModuleId) {
1135 profiling::scope!("ShaderModule::drop");
1136 api_log!("ShaderModule::drop {shader_module_id:?}");
1137
1138 let hub = &self.hub;
1139
1140 let _shader_module = hub.shader_modules.remove(shader_module_id);
1141
1142 #[cfg(feature = "trace")]
1143 if let Ok(shader_module) = _shader_module.get() {
1144 if let Some(t) = shader_module.device.trace.lock().as_mut() {
1145 t.add(trace::Action::DestroyShaderModule(shader_module.to_trace()));
1146 }
1147 }
1148 }
1149
1150 pub fn device_create_command_encoder(
1151 &self,
1152 device_id: DeviceId,
1153 desc: &wgt::CommandEncoderDescriptor<Label>,
1154 id_in: Option<id::CommandEncoderId>,
1155 ) -> (id::CommandEncoderId, Option<DeviceError>) {
1156 profiling::scope!("Device::create_command_encoder");
1157
1158 let hub = &self.hub;
1159 let fid = hub.command_encoders.prepare(id_in);
1160
1161 let device = self.hub.devices.get(device_id);
1162
1163 let error = 'error: {
1164 let cmd_enc = match device.create_command_encoder(&desc.label) {
1165 Ok(cmd_enc) => cmd_enc,
1166 Err(e) => break 'error e,
1167 };
1168
1169 let id = fid.assign(cmd_enc);
1170 api_log!("Device::create_command_encoder -> {id:?}");
1171 return (id, None);
1172 };
1173
1174 let id = fid.assign(Arc::new(CommandEncoder::new_invalid(
1175 &device,
1176 &desc.label,
1177 error.clone().into(),
1178 )));
1179 (id, Some(error))
1180 }
1181
1182 pub fn command_encoder_drop(&self, command_encoder_id: id::CommandEncoderId) {
1183 profiling::scope!("CommandEncoder::drop");
1184 api_log!("CommandEncoder::drop {command_encoder_id:?}");
1185 let _cmd_enc = self.hub.command_encoders.remove(command_encoder_id);
1186 }
1187
1188 pub fn command_buffer_drop(&self, command_buffer_id: id::CommandBufferId) {
1189 profiling::scope!("CommandBuffer::drop");
1190 api_log!("CommandBuffer::drop {command_buffer_id:?}");
1191 let _cmd_buf = self.hub.command_buffers.remove(command_buffer_id);
1192 }
1193
1194 pub fn device_create_render_bundle_encoder(
1195 &self,
1196 device_id: DeviceId,
1197 desc: &command::RenderBundleEncoderDescriptor,
1198 ) -> (
1199 *mut command::RenderBundleEncoder,
1200 Option<command::CreateRenderBundleError>,
1201 ) {
1202 profiling::scope!("Device::create_render_bundle_encoder");
1203 api_log!("Device::device_create_render_bundle_encoder");
1204 let (encoder, error) = match command::RenderBundleEncoder::new(desc, device_id) {
1205 Ok(encoder) => (encoder, None),
1206 Err(e) => (command::RenderBundleEncoder::dummy(device_id), Some(e)),
1207 };
1208 (Box::into_raw(Box::new(encoder)), error)
1209 }
1210
1211 pub fn render_bundle_encoder_finish(
1212 &self,
1213 bundle_encoder: command::RenderBundleEncoder,
1214 desc: &command::RenderBundleDescriptor,
1215 id_in: Option<id::RenderBundleId>,
1216 ) -> (id::RenderBundleId, Option<command::RenderBundleError>) {
1217 profiling::scope!("RenderBundleEncoder::finish");
1218
1219 let hub = &self.hub;
1220
1221 let fid = hub.render_bundles.prepare(id_in);
1222
1223 let error = 'error: {
1224 let device = self.hub.devices.get(bundle_encoder.parent());
1225
1226 #[cfg(feature = "trace")]
1227 let trace_desc = trace::new_render_bundle_encoder_descriptor(
1228 desc.label.clone(),
1229 &bundle_encoder.context,
1230 bundle_encoder.is_depth_read_only,
1231 bundle_encoder.is_stencil_read_only,
1232 );
1233
1234 let render_bundle = match bundle_encoder.finish(desc, &device, hub) {
1235 Ok(bundle) => bundle,
1236 Err(e) => break 'error e,
1237 };
1238
1239 #[cfg(feature = "trace")]
1240 if let Some(ref mut trace) = *device.trace.lock() {
1241 trace.add(trace::Action::CreateRenderBundle {
1242 id: render_bundle.to_trace(),
1243 desc: trace_desc,
1244 base: render_bundle.to_base_pass().to_trace(),
1245 });
1246 }
1247
1248 let id = fid.assign(Fallible::Valid(render_bundle));
1249 api_log!("RenderBundleEncoder::finish -> {id:?}");
1250
1251 return (id, None);
1252 };
1253
1254 let id = fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string())));
1255 (id, Some(error))
1256 }
1257
1258 pub fn render_bundle_drop(&self, render_bundle_id: id::RenderBundleId) {
1259 profiling::scope!("RenderBundle::drop");
1260 api_log!("RenderBundle::drop {render_bundle_id:?}");
1261
1262 let hub = &self.hub;
1263
1264 let _bundle = hub.render_bundles.remove(render_bundle_id);
1265
1266 #[cfg(feature = "trace")]
1267 if let Ok(bundle) = _bundle.get() {
1268 if let Some(t) = bundle.device.trace.lock().as_mut() {
1269 t.add(trace::Action::DestroyRenderBundle(bundle.to_trace()));
1270 }
1271 }
1272 }
1273
1274 pub fn device_create_query_set(
1275 &self,
1276 device_id: DeviceId,
1277 desc: &resource::QuerySetDescriptor,
1278 id_in: Option<id::QuerySetId>,
1279 ) -> (id::QuerySetId, Option<resource::CreateQuerySetError>) {
1280 profiling::scope!("Device::create_query_set");
1281
1282 let hub = &self.hub;
1283 let fid = hub.query_sets.prepare(id_in);
1284
1285 let error = 'error: {
1286 let device = self.hub.devices.get(device_id);
1287
1288 let query_set = match device.create_query_set(desc) {
1289 Ok(query_set) => query_set,
1290 Err(err) => break 'error err,
1291 };
1292
1293 #[cfg(feature = "trace")]
1294 if let Some(ref mut trace) = *device.trace.lock() {
1295 trace.add(trace::Action::CreateQuerySet {
1296 id: query_set.to_trace(),
1297 desc: desc.clone(),
1298 });
1299 }
1300
1301 let id = fid.assign(Fallible::Valid(query_set));
1302 api_log!("Device::create_query_set -> {id:?}");
1303
1304 return (id, None);
1305 };
1306
1307 let id = fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string())));
1308 (id, Some(error))
1309 }
1310
1311 pub fn query_set_drop(&self, query_set_id: id::QuerySetId) {
1312 profiling::scope!("QuerySet::drop");
1313 api_log!("QuerySet::drop {query_set_id:?}");
1314
1315 let hub = &self.hub;
1316
1317 let _query_set = hub.query_sets.remove(query_set_id);
1318
1319 #[cfg(feature = "trace")]
1320 if let Ok(query_set) = _query_set.get() {
1321 if let Some(trace) = query_set.device.trace.lock().as_mut() {
1322 trace.add(trace::Action::DestroyQuerySet(query_set.to_trace()));
1323 }
1324 }
1325 }
1326
1327 pub fn device_create_render_pipeline(
1328 &self,
1329 device_id: DeviceId,
1330 desc: &pipeline::RenderPipelineDescriptor,
1331 id_in: Option<id::RenderPipelineId>,
1332 ) -> (
1333 id::RenderPipelineId,
1334 Option<pipeline::CreateRenderPipelineError>,
1335 ) {
1336 profiling::scope!("Device::create_render_pipeline");
1337
1338 let hub = &self.hub;
1339
1340 let fid = hub.render_pipelines.prepare(id_in);
1341
1342 let device = self.hub.devices.get(device_id);
1343
1344 self.device_create_general_render_pipeline(desc.clone().into(), device, fid)
1345 }
1346
1347 pub fn device_create_mesh_pipeline(
1348 &self,
1349 device_id: DeviceId,
1350 desc: &pipeline::MeshPipelineDescriptor,
1351 id_in: Option<id::RenderPipelineId>,
1352 ) -> (
1353 id::RenderPipelineId,
1354 Option<pipeline::CreateRenderPipelineError>,
1355 ) {
1356 let hub = &self.hub;
1357
1358 let fid = hub.render_pipelines.prepare(id_in);
1359
1360 let device = self.hub.devices.get(device_id);
1361 self.device_create_general_render_pipeline(desc.clone().into(), device, fid)
1362 }
1363
1364 fn device_create_general_render_pipeline(
1365 &self,
1366 desc: pipeline::GeneralRenderPipelineDescriptor,
1367 device: Arc<crate::device::resource::Device>,
1368 fid: crate::registry::FutureId<Fallible<pipeline::RenderPipeline>>,
1369 ) -> (
1370 id::RenderPipelineId,
1371 Option<pipeline::CreateRenderPipelineError>,
1372 ) {
1373 profiling::scope!("Device::create_general_render_pipeline");
1374
1375 let hub = &self.hub;
1376
1377 let error = 'error: {
1378 if let Err(e) = device.check_is_valid() {
1379 break 'error e.into();
1380 }
1381
1382 let layout = desc
1383 .layout
1384 .map(|layout| hub.pipeline_layouts.get(layout).get())
1385 .transpose();
1386 let layout = match layout {
1387 Ok(layout) => layout,
1388 Err(e) => break 'error e.into(),
1389 };
1390
1391 let cache = desc
1392 .cache
1393 .map(|cache| hub.pipeline_caches.get(cache).get())
1394 .transpose();
1395 let cache = match cache {
1396 Ok(cache) => cache,
1397 Err(e) => break 'error e.into(),
1398 };
1399 let mut passthrough_stages = wgt::ShaderStages::empty();
1400
1401 let vertex = match desc.vertex {
1402 RenderPipelineVertexProcessor::Vertex(ref vertex) => {
1403 let module = hub
1404 .shader_modules
1405 .get(vertex.stage.module)
1406 .get()
1407 .map_err(|e| pipeline::CreateRenderPipelineError::Stage {
1408 stage: wgt::ShaderStages::VERTEX,
1409 error: e.into(),
1410 });
1411 let module = match module {
1412 Ok(module) => module,
1413 Err(e) => break 'error e,
1414 };
1415 if module.interface.is_none() {
1416 passthrough_stages |= wgt::ShaderStages::VERTEX;
1417 }
1418 let stage = ResolvedProgrammableStageDescriptor {
1419 module,
1420 entry_point: vertex.stage.entry_point.clone(),
1421 constants: vertex.stage.constants.clone(),
1422 zero_initialize_workgroup_memory: vertex
1423 .stage
1424 .zero_initialize_workgroup_memory,
1425 };
1426 RenderPipelineVertexProcessor::Vertex(ResolvedVertexState {
1427 stage,
1428 buffers: vertex.buffers.clone(),
1429 })
1430 }
1431 RenderPipelineVertexProcessor::Mesh(ref task, ref mesh) => {
1432 let task_module = if let Some(task) = task {
1433 let module = hub
1434 .shader_modules
1435 .get(task.stage.module)
1436 .get()
1437 .map_err(|e| pipeline::CreateRenderPipelineError::Stage {
1438 stage: wgt::ShaderStages::VERTEX,
1439 error: e.into(),
1440 });
1441 let module = match module {
1442 Ok(module) => module,
1443 Err(e) => break 'error e,
1444 };
1445 if module.interface.is_none() {
1446 passthrough_stages |= wgt::ShaderStages::TASK;
1447 }
1448 let state = ResolvedProgrammableStageDescriptor {
1449 module,
1450 entry_point: task.stage.entry_point.clone(),
1451 constants: task.stage.constants.clone(),
1452 zero_initialize_workgroup_memory: task
1453 .stage
1454 .zero_initialize_workgroup_memory,
1455 };
1456 Some(ResolvedTaskState { stage: state })
1457 } else {
1458 None
1459 };
1460 let mesh_module =
1461 hub.shader_modules
1462 .get(mesh.stage.module)
1463 .get()
1464 .map_err(|e| pipeline::CreateRenderPipelineError::Stage {
1465 stage: wgt::ShaderStages::MESH,
1466 error: e.into(),
1467 });
1468 let mesh_module = match mesh_module {
1469 Ok(module) => module,
1470 Err(e) => break 'error e,
1471 };
1472 if mesh_module.interface.is_none() {
1473 passthrough_stages |= wgt::ShaderStages::VERTEX;
1474 }
1475 let mesh_stage = ResolvedProgrammableStageDescriptor {
1476 module: mesh_module,
1477 entry_point: mesh.stage.entry_point.clone(),
1478 constants: mesh.stage.constants.clone(),
1479 zero_initialize_workgroup_memory: mesh
1480 .stage
1481 .zero_initialize_workgroup_memory,
1482 };
1483 RenderPipelineVertexProcessor::Mesh(
1484 task_module,
1485 ResolvedMeshState { stage: mesh_stage },
1486 )
1487 }
1488 };
1489
1490 let fragment = if let Some(ref state) = desc.fragment {
1491 let module = hub
1492 .shader_modules
1493 .get(state.stage.module)
1494 .get()
1495 .map_err(|e| pipeline::CreateRenderPipelineError::Stage {
1496 stage: wgt::ShaderStages::FRAGMENT,
1497 error: e.into(),
1498 });
1499 let module = match module {
1500 Ok(module) => module,
1501 Err(e) => break 'error e,
1502 };
1503 if module.interface.is_none() {
1504 passthrough_stages |= wgt::ShaderStages::FRAGMENT;
1505 }
1506 let stage = ResolvedProgrammableStageDescriptor {
1507 module,
1508 entry_point: state.stage.entry_point.clone(),
1509 constants: state.stage.constants.clone(),
1510 zero_initialize_workgroup_memory: state.stage.zero_initialize_workgroup_memory,
1511 };
1512 Some(ResolvedFragmentState {
1513 stage,
1514 targets: state.targets.clone(),
1515 })
1516 } else {
1517 None
1518 };
1519
1520 if !passthrough_stages.is_empty() && layout.is_none() {
1521 break 'error pipeline::CreateRenderPipelineError::Implicit(
1522 pipeline::ImplicitLayoutError::Passthrough(passthrough_stages),
1523 );
1524 }
1525
1526 let desc = ResolvedGeneralRenderPipelineDescriptor {
1527 label: desc.label.clone(),
1528 layout,
1529 vertex,
1530 primitive: desc.primitive,
1531 depth_stencil: desc.depth_stencil.clone(),
1532 multisample: desc.multisample,
1533 fragment,
1534 multiview_mask: desc.multiview_mask,
1535 cache,
1536 };
1537
1538 #[cfg(feature = "trace")]
1539 let trace_desc = desc.clone().into_trace();
1540
1541 let res = device.create_render_pipeline(desc);
1542
1543 #[cfg(feature = "trace")]
1544 if let Some(ref mut trace) = *device.trace.lock() {
1545 trace.add(trace::Action::CreateGeneralRenderPipeline {
1546 id: res.as_ref().ok().map(IntoTrace::to_trace),
1547 desc: trace_desc,
1548 });
1549 }
1550
1551 let pipeline = match res {
1552 Ok(pair) => pair,
1553 Err(e) => break 'error e,
1554 };
1555
1556 let id = fid.assign(Fallible::Valid(pipeline));
1557 api_log!("Device::create_render_pipeline -> {id:?}");
1558
1559 return (id, None);
1560 };
1561
1562 let id = fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string())));
1563
1564 (id, Some(error))
1565 }
1566
1567 pub fn render_pipeline_get_bind_group_layout(
1570 &self,
1571 pipeline_id: id::RenderPipelineId,
1572 index: u32,
1573 id_in: Option<id::BindGroupLayoutId>,
1574 ) -> (
1575 id::BindGroupLayoutId,
1576 Option<binding_model::GetBindGroupLayoutError>,
1577 ) {
1578 let hub = &self.hub;
1579
1580 let fid = hub.bind_group_layouts.prepare(id_in);
1581
1582 let error = 'error: {
1583 let pipeline = match hub.render_pipelines.get(pipeline_id).get() {
1584 Ok(pipeline) => pipeline,
1585 Err(e) => break 'error e.into(),
1586 };
1587 match pipeline.get_bind_group_layout(index) {
1588 Ok(bgl) => {
1589 #[cfg(feature = "trace")]
1590 if let Some(ref mut trace) = *pipeline.device.trace.lock() {
1591 trace.add(trace::Action::GetRenderPipelineBindGroupLayout {
1592 id: bgl.to_trace(),
1593 pipeline: pipeline.to_trace(),
1594 index,
1595 });
1596 }
1597
1598 let id = fid.assign(Fallible::Valid(bgl.clone()));
1599 return (id, None);
1600 }
1601 Err(err) => break 'error err,
1602 };
1603 };
1604
1605 let id = fid.assign(Fallible::Invalid(Arc::new(String::new())));
1606 (id, Some(error))
1607 }
1608
1609 pub fn render_pipeline_drop(&self, render_pipeline_id: id::RenderPipelineId) {
1610 profiling::scope!("RenderPipeline::drop");
1611 api_log!("RenderPipeline::drop {render_pipeline_id:?}");
1612
1613 let hub = &self.hub;
1614
1615 let _pipeline = hub.render_pipelines.remove(render_pipeline_id);
1616
1617 #[cfg(feature = "trace")]
1618 if let Ok(pipeline) = _pipeline.get() {
1619 if let Some(t) = pipeline.device.trace.lock().as_mut() {
1620 t.add(trace::Action::DestroyRenderPipeline(pipeline.to_trace()));
1621 }
1622 }
1623 }
1624
1625 pub fn device_create_compute_pipeline(
1626 &self,
1627 device_id: DeviceId,
1628 desc: &pipeline::ComputePipelineDescriptor,
1629 id_in: Option<id::ComputePipelineId>,
1630 ) -> (
1631 id::ComputePipelineId,
1632 Option<pipeline::CreateComputePipelineError>,
1633 ) {
1634 profiling::scope!("Device::create_compute_pipeline");
1635
1636 let hub = &self.hub;
1637
1638 let fid = hub.compute_pipelines.prepare(id_in);
1639
1640 let error = 'error: {
1641 let device = self.hub.devices.get(device_id);
1642
1643 if let Err(e) = device.check_is_valid() {
1644 break 'error e.into();
1645 }
1646
1647 let layout = desc
1648 .layout
1649 .map(|layout| hub.pipeline_layouts.get(layout).get())
1650 .transpose();
1651 let layout = match layout {
1652 Ok(layout) => layout,
1653 Err(e) => break 'error e.into(),
1654 };
1655
1656 let cache = desc
1657 .cache
1658 .map(|cache| hub.pipeline_caches.get(cache).get())
1659 .transpose();
1660 let cache = match cache {
1661 Ok(cache) => cache,
1662 Err(e) => break 'error e.into(),
1663 };
1664
1665 let module = hub.shader_modules.get(desc.stage.module).get();
1666 let module = match module {
1667 Ok(module) => module,
1668 Err(e) => break 'error e.into(),
1669 };
1670 if module.interface.is_none() && layout.is_none() {
1671 break 'error pipeline::CreateComputePipelineError::Implicit(
1672 pipeline::ImplicitLayoutError::Passthrough(wgt::ShaderStages::COMPUTE),
1673 );
1674 }
1675 let stage = ResolvedProgrammableStageDescriptor {
1676 module,
1677 entry_point: desc.stage.entry_point.clone(),
1678 constants: desc.stage.constants.clone(),
1679 zero_initialize_workgroup_memory: desc.stage.zero_initialize_workgroup_memory,
1680 };
1681
1682 let desc = ResolvedComputePipelineDescriptor {
1683 label: desc.label.clone(),
1684 layout,
1685 stage,
1686 cache,
1687 };
1688
1689 #[cfg(feature = "trace")]
1690 let trace_desc = desc.clone().into_trace();
1691
1692 let res = device.create_compute_pipeline(desc);
1693
1694 #[cfg(feature = "trace")]
1695 if let Some(ref mut trace) = *device.trace.lock() {
1696 trace.add(trace::Action::CreateComputePipeline {
1697 id: res.as_ref().ok().map(IntoTrace::to_trace),
1698 desc: trace_desc,
1699 });
1700 }
1701
1702 let pipeline = match res {
1703 Ok(pair) => pair,
1704 Err(e) => break 'error e,
1705 };
1706
1707 let id = fid.assign(Fallible::Valid(pipeline));
1708 api_log!("Device::create_compute_pipeline -> {id:?}");
1709
1710 return (id, None);
1711 };
1712
1713 let id = fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string())));
1714
1715 (id, Some(error))
1716 }
1717
1718 pub fn compute_pipeline_get_bind_group_layout(
1721 &self,
1722 pipeline_id: id::ComputePipelineId,
1723 index: u32,
1724 id_in: Option<id::BindGroupLayoutId>,
1725 ) -> (
1726 id::BindGroupLayoutId,
1727 Option<binding_model::GetBindGroupLayoutError>,
1728 ) {
1729 let hub = &self.hub;
1730
1731 let fid = hub.bind_group_layouts.prepare(id_in);
1732
1733 let error = 'error: {
1734 let pipeline = match hub.compute_pipelines.get(pipeline_id).get() {
1735 Ok(pipeline) => pipeline,
1736 Err(e) => break 'error e.into(),
1737 };
1738
1739 match pipeline.get_bind_group_layout(index) {
1740 Ok(bgl) => {
1741 #[cfg(feature = "trace")]
1742 if let Some(ref mut trace) = *pipeline.device.trace.lock() {
1743 trace.add(trace::Action::GetComputePipelineBindGroupLayout {
1744 id: bgl.to_trace(),
1745 pipeline: pipeline.to_trace(),
1746 index,
1747 });
1748 }
1749
1750 let id = fid.assign(Fallible::Valid(bgl.clone()));
1751 return (id, None);
1752 }
1753 Err(err) => break 'error err,
1754 };
1755 };
1756
1757 let id = fid.assign(Fallible::Invalid(Arc::new(String::new())));
1758 (id, Some(error))
1759 }
1760
1761 pub fn compute_pipeline_drop(&self, compute_pipeline_id: id::ComputePipelineId) {
1762 profiling::scope!("ComputePipeline::drop");
1763 api_log!("ComputePipeline::drop {compute_pipeline_id:?}");
1764
1765 let hub = &self.hub;
1766
1767 let _pipeline = hub.compute_pipelines.remove(compute_pipeline_id);
1768
1769 #[cfg(feature = "trace")]
1770 if let Ok(pipeline) = _pipeline.get() {
1771 if let Some(t) = pipeline.device.trace.lock().as_mut() {
1772 t.add(trace::Action::DestroyComputePipeline(pipeline.to_trace()));
1773 }
1774 }
1775 }
1776
1777 pub unsafe fn device_create_pipeline_cache(
1781 &self,
1782 device_id: DeviceId,
1783 desc: &pipeline::PipelineCacheDescriptor<'_>,
1784 id_in: Option<id::PipelineCacheId>,
1785 ) -> (
1786 id::PipelineCacheId,
1787 Option<pipeline::CreatePipelineCacheError>,
1788 ) {
1789 profiling::scope!("Device::create_pipeline_cache");
1790
1791 let hub = &self.hub;
1792
1793 let fid = hub.pipeline_caches.prepare(id_in);
1794 let error: pipeline::CreatePipelineCacheError = 'error: {
1795 let device = self.hub.devices.get(device_id);
1796
1797 let cache = unsafe { device.create_pipeline_cache(desc) };
1798 match cache {
1799 Ok(cache) => {
1800 #[cfg(feature = "trace")]
1801 if let Some(ref mut trace) = *device.trace.lock() {
1802 trace.add(trace::Action::CreatePipelineCache {
1803 id: cache.to_trace(),
1804 desc: desc.clone(),
1805 });
1806 }
1807
1808 let id = fid.assign(Fallible::Valid(cache));
1809 api_log!("Device::create_pipeline_cache -> {id:?}");
1810 return (id, None);
1811 }
1812 Err(e) => break 'error e,
1813 }
1814 };
1815
1816 let id = fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string())));
1817
1818 (id, Some(error))
1819 }
1820
1821 pub fn pipeline_cache_drop(&self, pipeline_cache_id: id::PipelineCacheId) {
1822 profiling::scope!("PipelineCache::drop");
1823 api_log!("PipelineCache::drop {pipeline_cache_id:?}");
1824
1825 let hub = &self.hub;
1826
1827 let _cache = hub.pipeline_caches.remove(pipeline_cache_id);
1828
1829 #[cfg(feature = "trace")]
1830 if let Ok(cache) = _cache.get() {
1831 if let Some(t) = cache.device.trace.lock().as_mut() {
1832 t.add(trace::Action::DestroyPipelineCache(cache.to_trace()));
1833 }
1834 }
1835 }
1836
1837 pub fn surface_configure(
1838 &self,
1839 surface_id: SurfaceId,
1840 device_id: DeviceId,
1841 config: &wgt::SurfaceConfiguration<Vec<TextureFormat>>,
1842 ) -> Option<present::ConfigureSurfaceError> {
1843 let device = self.hub.devices.get(device_id);
1844 let surface = self.surfaces.get(surface_id);
1845
1846 #[cfg(feature = "trace")]
1847 if let Some(ref mut trace) = *device.trace.lock() {
1848 trace.add(trace::Action::ConfigureSurface(
1849 surface.to_trace(),
1850 config.clone(),
1851 ));
1852 }
1853
1854 device.configure_surface(&surface, config)
1855 }
1856
1857 pub fn device_poll(
1861 &self,
1862 device_id: DeviceId,
1863 poll_type: wgt::PollType<crate::SubmissionIndex>,
1864 ) -> Result<wgt::PollStatus, WaitIdleError> {
1865 api_log!("Device::poll {poll_type:?}");
1866
1867 let device = self.hub.devices.get(device_id);
1868
1869 let (closures, result) = device.poll_and_return_closures(poll_type);
1870
1871 closures.fire();
1872
1873 result
1874 }
1875
1876 fn poll_all_devices_of_api(
1883 &self,
1884 force_wait: bool,
1885 closure_list: &mut UserClosures,
1886 ) -> Result<bool, WaitIdleError> {
1887 profiling::scope!("poll_device");
1888
1889 let hub = &self.hub;
1890 let mut all_queue_empty = true;
1891 {
1892 let device_guard = hub.devices.read();
1893
1894 for (_id, device) in device_guard.iter() {
1895 let poll_type = if force_wait {
1896 wgt::PollType::wait_indefinitely()
1898 } else {
1899 wgt::PollType::Poll
1900 };
1901
1902 let (closures, result) = device.poll_and_return_closures(poll_type);
1903
1904 let is_queue_empty = matches!(result, Ok(wgt::PollStatus::QueueEmpty));
1905
1906 all_queue_empty &= is_queue_empty;
1907
1908 closure_list.extend(closures);
1909 }
1910 }
1911
1912 Ok(all_queue_empty)
1913 }
1914
1915 pub fn poll_all_devices(&self, force_wait: bool) -> Result<bool, WaitIdleError> {
1922 api_log!("poll_all_devices");
1923 let mut closures = UserClosures::default();
1924 let all_queue_empty = self.poll_all_devices_of_api(force_wait, &mut closures)?;
1925
1926 closures.fire();
1927
1928 Ok(all_queue_empty)
1929 }
1930
1931 pub unsafe fn device_start_graphics_debugger_capture(&self, device_id: DeviceId) {
1937 unsafe {
1938 self.hub
1939 .devices
1940 .get(device_id)
1941 .start_graphics_debugger_capture();
1942 }
1943 }
1944
1945 pub unsafe fn device_stop_graphics_debugger_capture(&self, device_id: DeviceId) {
1951 unsafe {
1952 self.hub
1953 .devices
1954 .get(device_id)
1955 .stop_graphics_debugger_capture();
1956 }
1957 }
1958
1959 pub fn pipeline_cache_get_data(&self, id: id::PipelineCacheId) -> Option<Vec<u8>> {
1960 use crate::pipeline_cache;
1961 api_log!("PipelineCache::get_data");
1962 let hub = &self.hub;
1963
1964 if let Ok(cache) = hub.pipeline_caches.get(id).get() {
1965 if !cache.device.is_valid() {
1967 return None;
1968 }
1969 let mut vec = unsafe { cache.device.raw().pipeline_cache_get_data(cache.raw()) }?;
1970 let validation_key = cache.device.raw().pipeline_cache_validation_key()?;
1971
1972 let mut header_contents = [0; pipeline_cache::HEADER_LENGTH];
1973 pipeline_cache::add_cache_header(
1974 &mut header_contents,
1975 &vec,
1976 &cache.device.adapter.raw.info,
1977 validation_key,
1978 );
1979
1980 let deleted = vec.splice(..0, header_contents).collect::<Vec<_>>();
1981 debug_assert!(deleted.is_empty());
1982
1983 return Some(vec);
1984 }
1985 None
1986 }
1987
1988 pub fn device_drop(&self, device_id: DeviceId) {
1989 profiling::scope!("Device::drop");
1990 api_log!("Device::drop {device_id:?}");
1991
1992 self.hub.devices.remove(device_id);
1993 }
1994
1995 pub fn device_set_device_lost_closure(
1997 &self,
1998 device_id: DeviceId,
1999 device_lost_closure: DeviceLostClosure,
2000 ) {
2001 let device = self.hub.devices.get(device_id);
2002
2003 device
2004 .device_lost_closure
2005 .lock()
2006 .replace(device_lost_closure);
2007 }
2008
2009 pub fn device_destroy(&self, device_id: DeviceId) {
2010 api_log!("Device::destroy {device_id:?}");
2011
2012 let device = self.hub.devices.get(device_id);
2013
2014 if !device.is_valid() {
2020 return;
2021 }
2022
2023 device.valid.store(false, Ordering::Release);
2031 }
2032
2033 pub fn device_get_internal_counters(&self, device_id: DeviceId) -> wgt::InternalCounters {
2034 let device = self.hub.devices.get(device_id);
2035 wgt::InternalCounters {
2036 hal: device.get_hal_counters(),
2037 core: wgt::CoreCounters {},
2038 }
2039 }
2040
2041 pub fn device_generate_allocator_report(
2042 &self,
2043 device_id: DeviceId,
2044 ) -> Option<wgt::AllocatorReport> {
2045 let device = self.hub.devices.get(device_id);
2046 device.generate_allocator_report()
2047 }
2048
2049 #[cfg(feature = "trace")]
2050 pub fn device_take_trace(
2051 &self,
2052 device_id: DeviceId,
2053 ) -> Option<Box<dyn trace::Trace + Send + Sync + 'static>> {
2054 let device = self.hub.devices.get(device_id);
2055 device.take_trace()
2056 }
2057
2058 pub fn queue_drop(&self, queue_id: QueueId) {
2059 profiling::scope!("Queue::drop");
2060 api_log!("Queue::drop {queue_id:?}");
2061
2062 self.hub.queues.remove(queue_id);
2063 }
2064
2065 pub fn buffer_map_async(
2067 &self,
2068 buffer_id: id::BufferId,
2069 offset: BufferAddress,
2070 size: Option<BufferAddress>,
2071 op: BufferMapOperation,
2072 ) -> Result<crate::SubmissionIndex, BufferAccessError> {
2073 profiling::scope!("Buffer::map_async");
2074 api_log!("Buffer::map_async {buffer_id:?} offset {offset:?} size {size:?} op: {op:?}");
2075
2076 let hub = &self.hub;
2077
2078 let map_result = match hub.buffers.get(buffer_id).get() {
2079 Ok(buffer) => buffer.map_async(offset, size, op),
2080 Err(e) => Err((op, e.into())),
2081 };
2082
2083 match map_result {
2084 Ok(submission_index) => Ok(submission_index),
2085 Err((mut operation, err)) => {
2086 if let Some(callback) = operation.callback.take() {
2087 callback(Err(err.clone()));
2088 }
2089 Err(err)
2090 }
2091 }
2092 }
2093
2094 pub fn buffer_get_mapped_range(
2095 &self,
2096 buffer_id: id::BufferId,
2097 offset: BufferAddress,
2098 size: Option<BufferAddress>,
2099 ) -> Result<(NonNull<u8>, u64), BufferAccessError> {
2100 profiling::scope!("Buffer::get_mapped_range");
2101 api_log!("Buffer::get_mapped_range {buffer_id:?} offset {offset:?} size {size:?}");
2102
2103 let hub = &self.hub;
2104
2105 let buffer = hub.buffers.get(buffer_id).get()?;
2106
2107 buffer.get_mapped_range(offset, size)
2108 }
2109
2110 pub fn buffer_unmap(&self, buffer_id: id::BufferId) -> BufferAccessResult {
2111 profiling::scope!("unmap", "Buffer");
2112 api_log!("Buffer::unmap {buffer_id:?}");
2113
2114 let hub = &self.hub;
2115
2116 let buffer = hub.buffers.get(buffer_id).get()?;
2117
2118 let snatch_guard = buffer.device.snatchable_lock.read();
2119 buffer.check_destroyed(&snatch_guard)?;
2120 drop(snatch_guard);
2121
2122 buffer.device.check_is_valid()?;
2123 buffer.unmap()
2124 }
2125}