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