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 device_id: DeviceId,
227 id_in: Option<id::RenderBundleId>,
228 desc: &command::RenderBundleDescriptor,
229 ) {
230 let device = self.hub.devices.get(device_id);
231 let fid = self.hub.render_bundles.prepare(id_in);
232 fid.assign(command::RenderBundle::invalid(device, desc));
233 }
234
235 pub fn create_texture_error(
239 &self,
240 device_id: DeviceId,
241 id_in: Option<id::TextureId>,
242 desc: &resource::TextureDescriptor,
243 ) -> id::TextureId {
244 let fid = self.hub.textures.prepare(id_in);
245 let device = self.hub.devices.get(device_id);
246 let texture = device.create_texture_error(desc);
247 fid.assign(texture)
248 }
249
250 pub fn create_external_texture_error(
254 &self,
255 id_in: Option<id::ExternalTextureId>,
256 desc: &resource::ExternalTextureDescriptor,
257 ) {
258 let fid = self.hub.external_textures.prepare(id_in);
259 fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string())));
260 }
261
262 pub fn create_bind_group_layout_error(
271 &self,
272 device_id: DeviceId,
273 id_in: Option<id::BindGroupLayoutId>,
274 label: Option<Cow<'_, str>>,
275 ) {
276 let fid = self.hub.bind_group_layouts.prepare(id_in);
277 let device = self.hub.devices.get(device_id);
278 fid.assign(binding_model::BindGroupLayout::invalid(
279 &device,
280 label.to_string(),
281 ));
282 }
283
284 pub fn buffer_destroy(&self, buffer_id: id::BufferId) {
285 profiling::scope!("Buffer::destroy");
286 api_log!("Buffer::destroy {buffer_id:?}");
287
288 let hub = &self.hub;
289
290 let Ok(buffer) = hub.buffers.get(buffer_id).get() else {
291 return;
293 };
294
295 #[cfg(feature = "trace")]
296 if let Some(trace) = buffer.device.trace.lock().as_mut() {
297 trace.add(trace::Action::DestroyBuffer(buffer.to_trace()));
298 }
299
300 let _ = buffer.unmap();
301
302 buffer.destroy();
303 }
304
305 pub fn buffer_drop(&self, buffer_id: id::BufferId) {
306 profiling::scope!("Buffer::drop");
307 api_log!("Buffer::drop {buffer_id:?}");
308
309 let hub = &self.hub;
310
311 let buffer = match hub.buffers.remove(buffer_id).get() {
312 Ok(buffer) => buffer,
313 Err(_) => {
314 return;
315 }
316 };
317
318 #[cfg(feature = "trace")]
319 if let Some(t) = buffer.device.trace.lock().as_mut() {
320 t.add(trace::Action::DropBuffer(buffer.to_trace()));
321 }
322
323 let _ = buffer.unmap();
324 }
325
326 pub fn device_create_texture(
327 &self,
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");
333
334 let hub = &self.hub;
335
336 let fid = hub.textures.prepare(id_in);
337
338 let device = self.hub.devices.get(device_id);
339
340 let (texture, error) = device.create_texture(desc);
341
342 let id = fid.assign(texture);
343
344 (id, error)
345 }
346
347 pub unsafe fn create_texture_from_hal(
355 &self,
356 hal_texture: Box<dyn hal::DynTexture>,
357 device_id: DeviceId,
358 desc: &resource::TextureDescriptor,
359 initial_state: wgt::TextureUses,
360 id_in: Option<id::TextureId>,
361 ) -> (id::TextureId, Option<resource::CreateTextureError>) {
362 profiling::scope!("Device::create_texture_from_hal");
363
364 let hub = &self.hub;
365
366 let fid = hub.textures.prepare(id_in);
367
368 let device = self.hub.devices.get(device_id);
369
370 let error = 'error: {
371 let texture = match device.create_texture_from_hal(hal_texture, desc, initial_state) {
372 Ok(texture) => texture,
373 Err(error) => break 'error error,
374 };
375
376 #[cfg(feature = "trace")]
379 if let Some(ref mut trace) = *device.trace.lock() {
380 trace.add(trace::Action::CreateTexture(
381 texture.to_trace(),
382 desc.clone(),
383 ));
384 }
385
386 let id = fid.assign(texture);
387 api_log!("Device::create_texture({desc:?}) -> {id:?}");
388
389 return (id, None);
390 };
391
392 let id = fid.assign(Arc::new(resource::Texture::invalid(&device, desc)));
393 (id, Some(error))
394 }
395
396 pub unsafe fn create_buffer_from_hal<A: hal::Api>(
403 &self,
404 hal_buffer: A::Buffer,
405 device_id: DeviceId,
406 desc: &resource::BufferDescriptor,
407 id_in: Option<id::BufferId>,
408 ) -> (id::BufferId, Option<CreateBufferError>) {
409 profiling::scope!("Device::create_buffer");
410
411 let hub = &self.hub;
412 let fid = hub.buffers.prepare(id_in);
413
414 let device = self.hub.devices.get(device_id);
415
416 let (buffer, err) = unsafe { device.create_buffer_from_hal(Box::new(hal_buffer), desc) };
417
418 #[cfg(feature = "trace")]
421 if let Some(trace) = device.trace.lock().as_mut() {
422 match &buffer {
423 Fallible::Valid(arc) => {
424 trace.add(trace::Action::CreateBuffer(arc.to_trace(), desc.clone()))
425 }
426 Fallible::Invalid(_) => {}
427 }
428 }
429
430 let id = fid.assign(buffer);
431 api_log!("Device::create_buffer -> {id:?}");
432
433 (id, err)
434 }
435
436 pub fn texture_destroy(&self, texture_id: id::TextureId) {
437 profiling::scope!("Texture::destroy");
438 api_log!("Texture::destroy {texture_id:?}");
439
440 let hub = &self.hub;
441
442 let texture = hub.textures.get(texture_id);
443
444 #[cfg(feature = "trace")]
445 if let Some(trace) = texture.device.trace.lock().as_mut() {
446 trace.add(trace::Action::DestroyTexture(texture.to_trace()));
447 }
448
449 texture.destroy();
450 }
451
452 pub fn texture_drop(&self, texture_id: id::TextureId) {
453 profiling::scope!("Texture::drop");
454 api_log!("Texture::drop {texture_id:?}");
455
456 let hub = &self.hub;
457
458 hub.textures.remove(texture_id);
459 }
460
461 pub fn texture_create_view(
462 &self,
463 texture_id: id::TextureId,
464 desc: &resource::TextureViewDescriptor,
465 id_in: Option<id::TextureViewId>,
466 ) -> (id::TextureViewId, Option<resource::CreateTextureViewError>) {
467 profiling::scope!("Texture::create_view");
468
469 let hub = &self.hub;
470
471 let fid = hub.texture_views.prepare(id_in);
472
473 let texture = hub.textures.get(texture_id);
474 let device = &texture.device;
475
476 let (view, error) = device.create_texture_view(&texture, desc);
477
478 let id = fid.assign(view);
479
480 (id, error)
481 }
482
483 pub fn texture_view_drop(&self, texture_view_id: id::TextureViewId) {
484 let hub = &self.hub;
485
486 let _view = hub.texture_views.remove(texture_view_id);
487 }
488
489 pub fn device_create_external_texture(
490 &self,
491 device_id: DeviceId,
492 desc: &resource::ExternalTextureDescriptor,
493 planes: &[id::TextureViewId],
494 id_in: Option<id::ExternalTextureId>,
495 ) -> (
496 id::ExternalTextureId,
497 Option<resource::CreateExternalTextureError>,
498 ) {
499 profiling::scope!("Device::create_external_texture");
500
501 let hub = &self.hub;
502
503 let fid = hub.external_textures.prepare(id_in);
504
505 let error = 'error: {
506 let device = self.hub.devices.get(device_id);
507
508 let planes = planes
509 .iter()
510 .map(|plane_id| self.hub.texture_views.get(*plane_id))
511 .collect::<Vec<_>>();
512
513 let external_texture = match device.create_external_texture(desc, &planes) {
514 Ok(external_texture) => external_texture,
515 Err(error) => break 'error error,
516 };
517
518 #[cfg(feature = "trace")]
519 if let Some(ref mut trace) = *device.trace.lock() {
520 let planes = Box::from(
521 planes
522 .into_iter()
523 .map(|plane| plane.to_trace())
524 .collect::<Vec<_>>(),
525 );
526 trace.add(trace::Action::CreateExternalTexture {
527 id: external_texture.to_trace(),
528 desc: desc.clone(),
529 planes,
530 });
531 }
532
533 let id = fid.assign(Fallible::Valid(external_texture));
534 api_log!("Device::create_external_texture({desc:?}) -> {id:?}");
535
536 return (id, None);
537 };
538
539 let id = fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string())));
540 (id, Some(error))
541 }
542
543 pub fn external_texture_destroy(&self, external_texture_id: id::ExternalTextureId) {
544 profiling::scope!("ExternalTexture::destroy");
545 api_log!("ExternalTexture::destroy {external_texture_id:?}");
546
547 let hub = &self.hub;
548
549 let Ok(external_texture) = hub.external_textures.get(external_texture_id).get() else {
550 return;
552 };
553
554 #[cfg(feature = "trace")]
555 if let Some(trace) = external_texture.device.trace.lock().as_mut() {
556 trace.add(trace::Action::DestroyExternalTexture(
557 external_texture.to_trace(),
558 ));
559 }
560
561 external_texture.destroy();
562 }
563
564 pub fn external_texture_drop(&self, external_texture_id: id::ExternalTextureId) {
565 profiling::scope!("ExternalTexture::drop");
566 api_log!("ExternalTexture::drop {external_texture_id:?}");
567
568 let hub = &self.hub;
569
570 let _external_texture = hub.external_textures.remove(external_texture_id);
571
572 #[cfg(feature = "trace")]
573 if let Ok(external_texture) = _external_texture.get() {
574 if let Some(t) = external_texture.device.trace.lock().as_mut() {
575 t.add(trace::Action::DropExternalTexture(
576 external_texture.to_trace(),
577 ));
578 }
579 }
580 }
581
582 pub fn device_create_sampler(
583 &self,
584 device_id: DeviceId,
585 desc: &resource::SamplerDescriptor,
586 id_in: Option<id::SamplerId>,
587 ) -> (id::SamplerId, Option<resource::CreateSamplerError>) {
588 let hub = &self.hub;
589 let fid = hub.samplers.prepare(id_in);
590
591 let device = self.hub.devices.get(device_id);
592
593 let (sampler, error) = device.create_sampler(desc);
594
595 let id = fid.assign(sampler);
596
597 (id, error)
598 }
599
600 pub fn sampler_drop(&self, sampler_id: id::SamplerId) {
601 let hub = &self.hub;
602
603 let _sampler = hub.samplers.remove(sampler_id);
604 }
605
606 pub fn device_create_bind_group_layout(
607 &self,
608 device_id: DeviceId,
609 desc: &binding_model::BindGroupLayoutDescriptor,
610 id_in: Option<id::BindGroupLayoutId>,
611 ) -> (
612 id::BindGroupLayoutId,
613 Option<binding_model::CreateBindGroupLayoutError>,
614 ) {
615 profiling::scope!("Device::create_bind_group_layout");
616
617 let hub = &self.hub;
618 let fid = hub.bind_group_layouts.prepare(id_in);
619
620 let device = self.hub.devices.get(device_id);
621
622 let (bgl, error) = device.create_bind_group_layout(desc);
623
624 let id = fid.assign(bgl);
625
626 api_log!("Device::create_bind_group_layout -> {id:?}");
627
628 (id, error)
629 }
630
631 pub fn bind_group_layout_drop(&self, bind_group_layout_id: id::BindGroupLayoutId) {
632 profiling::scope!("BindGroupLayout::drop");
633 api_log!("BindGroupLayout::drop {bind_group_layout_id:?}");
634
635 let hub = &self.hub;
636
637 let _layout = hub.bind_group_layouts.remove(bind_group_layout_id);
638 }
639
640 pub fn device_create_pipeline_layout(
641 &self,
642 device_id: DeviceId,
643 desc: &binding_model::PipelineLayoutDescriptor,
644 id_in: Option<id::PipelineLayoutId>,
645 ) -> (
646 id::PipelineLayoutId,
647 Option<binding_model::CreatePipelineLayoutError>,
648 ) {
649 profiling::scope!("Device::create_pipeline_layout");
650
651 let hub = &self.hub;
652 let fid = hub.pipeline_layouts.prepare(id_in);
653
654 let device = self.hub.devices.get(device_id);
655
656 let bind_group_layouts = {
657 let bind_group_layouts_guard = hub.bind_group_layouts.read();
658 desc.bind_group_layouts
659 .iter()
660 .map(|bgl_id| bgl_id.map(|bgl_id| bind_group_layouts_guard.get(bgl_id)))
661 .collect::<Vec<_>>()
662 };
663
664 let desc = binding_model::ResolvedPipelineLayoutDescriptor {
665 label: desc.label.clone(),
666 bind_group_layouts: Cow::Owned(bind_group_layouts),
667 immediate_size: desc.immediate_size,
668 };
669
670 let (layout, error) = device.create_pipeline_layout(&desc);
671 let id = fid.assign(layout);
672 (id, error)
673 }
674
675 pub fn pipeline_layout_drop(&self, pipeline_layout_id: id::PipelineLayoutId) {
676 profiling::scope!("PipelineLayout::drop");
677 api_log!("PipelineLayout::drop {pipeline_layout_id:?}");
678
679 let hub = &self.hub;
680
681 let _layout = hub.pipeline_layouts.remove(pipeline_layout_id);
682 }
683
684 pub fn device_create_bind_group(
685 &self,
686 device_id: DeviceId,
687 desc: &binding_model::BindGroupDescriptor,
688 id_in: Option<id::BindGroupId>,
689 ) -> (id::BindGroupId, Option<binding_model::CreateBindGroupError>) {
690 profiling::scope!("Device::create_bind_group");
691
692 let hub = &self.hub;
693 let fid = hub.bind_groups.prepare(id_in);
694
695 let error = 'error: {
696 let device = self.hub.devices.get(device_id);
697
698 if let Err(e) = device.check_is_valid() {
699 break 'error e.into();
700 }
701
702 let layout = hub.bind_group_layouts.get(desc.layout);
703
704 fn resolve_entry<'a>(
705 e: &BindGroupEntry<'a>,
706 buffer_storage: &Storage<Fallible<resource::Buffer>>,
707 sampler_storage: &Storage<Arc<resource::Sampler>>,
708 texture_view_storage: &Storage<Arc<resource::TextureView>>,
709 tlas_storage: &Storage<Fallible<resource::Tlas>>,
710 external_texture_storage: &Storage<Fallible<resource::ExternalTexture>>,
711 ) -> Result<ResolvedBindGroupEntry<'a>, binding_model::CreateBindGroupError>
712 {
713 let resolve_buffer = |bb: &BufferBinding| {
714 buffer_storage
715 .get(bb.buffer)
716 .get()
717 .map(|buffer| ResolvedBufferBinding {
718 buffer,
719 offset: bb.offset,
720 size: bb.size,
721 })
722 .map_err(binding_model::CreateBindGroupError::from)
723 };
724 let resolve_sampler = |id: &id::SamplerId| sampler_storage.get(*id);
725 let resolve_view = |id: &id::TextureViewId| texture_view_storage.get(*id);
726 let resolve_tlas = |id: &id::TlasId| {
727 tlas_storage
728 .get(*id)
729 .get()
730 .map_err(binding_model::CreateBindGroupError::from)
731 };
732 let resolve_external_texture = |id: &id::ExternalTextureId| {
733 external_texture_storage
734 .get(*id)
735 .get()
736 .map_err(binding_model::CreateBindGroupError::from)
737 };
738 let resource = match e.resource {
739 BindingResource::Buffer(ref buffer) => {
740 ResolvedBindingResource::Buffer(resolve_buffer(buffer)?)
741 }
742 BindingResource::BufferArray(ref buffers) => {
743 let buffers = buffers
744 .iter()
745 .map(resolve_buffer)
746 .collect::<Result<Vec<_>, _>>()?;
747 ResolvedBindingResource::BufferArray(Cow::Owned(buffers))
748 }
749 BindingResource::Sampler(ref sampler) => {
750 ResolvedBindingResource::Sampler(resolve_sampler(sampler))
751 }
752 BindingResource::SamplerArray(ref samplers) => {
753 let samplers = samplers.iter().map(resolve_sampler).collect::<Vec<_>>();
754 ResolvedBindingResource::SamplerArray(Cow::Owned(samplers))
755 }
756 BindingResource::TextureView(ref view) => {
757 ResolvedBindingResource::TextureView(resolve_view(view))
758 }
759 BindingResource::TextureViewArray(ref views) => {
760 let views = views.iter().map(resolve_view).collect::<Vec<_>>();
761 ResolvedBindingResource::TextureViewArray(Cow::Owned(views))
762 }
763 BindingResource::AccelerationStructure(ref tlas) => {
764 ResolvedBindingResource::AccelerationStructure(resolve_tlas(tlas)?)
765 }
766 BindingResource::AccelerationStructureArray(ref tlas_array) => {
767 let tlas_array = tlas_array
768 .iter()
769 .map(resolve_tlas)
770 .collect::<Result<Vec<_>, _>>()?;
771 ResolvedBindingResource::AccelerationStructureArray(Cow::Owned(tlas_array))
772 }
773 BindingResource::ExternalTexture(ref et) => {
774 ResolvedBindingResource::ExternalTexture(resolve_external_texture(et)?)
775 }
776 };
777 Ok(ResolvedBindGroupEntry {
778 binding: e.binding,
779 resource,
780 })
781 }
782
783 let entries = {
784 let buffer_guard = hub.buffers.read();
785 let texture_view_guard = hub.texture_views.read();
786 let sampler_guard = hub.samplers.read();
787 let tlas_guard = hub.tlas_s.read();
788 let external_texture_guard = hub.external_textures.read();
789 desc.entries
790 .iter()
791 .map(|e| {
792 resolve_entry(
793 e,
794 &buffer_guard,
795 &sampler_guard,
796 &texture_view_guard,
797 &tlas_guard,
798 &external_texture_guard,
799 )
800 })
801 .collect::<Result<Vec<_>, _>>()
802 };
803 let entries = match entries {
804 Ok(entries) => Cow::Owned(entries),
805 Err(e) => break 'error e,
806 };
807
808 let desc = ResolvedBindGroupDescriptor {
809 label: desc.label.clone(),
810 layout,
811 entries,
812 };
813 #[cfg(feature = "trace")]
814 let trace_desc = (&desc).to_trace();
815
816 let bind_group = match device.create_bind_group(desc) {
817 Ok(bind_group) => bind_group,
818 Err(e) => break 'error e,
819 };
820
821 #[cfg(feature = "trace")]
822 if let Some(ref mut trace) = *device.trace.lock() {
823 trace.add(trace::Action::CreateBindGroup(
824 bind_group.to_trace(),
825 trace_desc,
826 ));
827 }
828
829 let id = fid.assign(Fallible::Valid(bind_group));
830
831 api_log!("Device::create_bind_group -> {id:?}");
832
833 return (id, None);
834 };
835
836 let id = fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string())));
837 (id, Some(error))
838 }
839
840 pub fn bind_group_drop(&self, bind_group_id: id::BindGroupId) {
841 profiling::scope!("BindGroup::drop");
842 api_log!("BindGroup::drop {bind_group_id:?}");
843
844 let hub = &self.hub;
845
846 let _bind_group = hub.bind_groups.remove(bind_group_id);
847
848 #[cfg(feature = "trace")]
849 if let Ok(bind_group) = _bind_group.get() {
850 if let Some(t) = bind_group.device.trace.lock().as_mut() {
851 t.add(trace::Action::DropBindGroup(bind_group.to_trace()));
852 }
853 }
854 }
855
856 pub fn device_create_shader_module(
871 &self,
872 device_id: DeviceId,
873 desc: &pipeline::ShaderModuleDescriptor,
874 source: pipeline::ShaderModuleSource,
875 id_in: Option<id::ShaderModuleId>,
876 ) -> (
877 id::ShaderModuleId,
878 Option<pipeline::CreateShaderModuleError>,
879 ) {
880 profiling::scope!("Device::create_shader_module");
881
882 let hub = &self.hub;
883 let fid = hub.shader_modules.prepare(id_in);
884
885 let device = self.hub.devices.get(device_id);
886
887 let (shader, error) = device.create_shader_module(desc, source);
888
889 let id = fid.assign(shader);
890
891 (id, error)
892 }
893
894 pub unsafe fn device_create_shader_module_passthrough(
899 &self,
900 device_id: DeviceId,
901 desc: &pipeline::ShaderModuleDescriptorPassthrough<'_>,
902 id_in: Option<id::ShaderModuleId>,
903 ) -> (
904 id::ShaderModuleId,
905 Option<pipeline::CreateShaderModuleError>,
906 ) {
907 let hub = &self.hub;
908 let fid = hub.shader_modules.prepare(id_in);
909
910 let device = self.hub.devices.get(device_id);
911
912 let (shader, error) = unsafe { device.create_shader_module_passthrough(desc) };
913
914 let id = fid.assign(shader);
915
916 (id, error)
917 }
918
919 pub fn shader_module_drop(&self, shader_module_id: id::ShaderModuleId) {
920 profiling::scope!("ShaderModule::drop");
921 api_log!("ShaderModule::drop {shader_module_id:?}");
922
923 let hub = &self.hub;
924
925 let _shader_module = hub.shader_modules.remove(shader_module_id);
926 }
927
928 pub fn device_create_command_encoder(
929 &self,
930 device_id: DeviceId,
931 desc: &wgt::CommandEncoderDescriptor<Label>,
932 id_in: Option<id::CommandEncoderId>,
933 ) -> (id::CommandEncoderId, Option<DeviceError>) {
934 profiling::scope!("Device::create_command_encoder");
935
936 let hub = &self.hub;
937 let fid = hub.command_encoders.prepare(id_in);
938
939 let device = self.hub.devices.get(device_id);
940
941 let error = 'error: {
942 let cmd_enc = match device.create_command_encoder(&desc.label) {
943 Ok(cmd_enc) => cmd_enc,
944 Err(e) => break 'error e,
945 };
946
947 let id = fid.assign(cmd_enc);
948 api_log!("Device::create_command_encoder -> {id:?}");
949 return (id, None);
950 };
951
952 let id = fid.assign(Arc::new(CommandEncoder::new_invalid(
953 &device,
954 &desc.label,
955 error.clone().into(),
956 )));
957 (id, Some(error))
958 }
959
960 pub fn command_encoder_drop(&self, command_encoder_id: id::CommandEncoderId) {
961 profiling::scope!("CommandEncoder::drop");
962 api_log!("CommandEncoder::drop {command_encoder_id:?}");
963 let _cmd_enc = self.hub.command_encoders.remove(command_encoder_id);
964 }
965
966 pub fn command_buffer_drop(&self, command_buffer_id: id::CommandBufferId) {
967 profiling::scope!("CommandBuffer::drop");
968 api_log!("CommandBuffer::drop {command_buffer_id:?}");
969 let _cmd_buf = self.hub.command_buffers.remove(command_buffer_id);
970 }
971
972 pub fn device_create_render_bundle_encoder(
973 &self,
974 device_id: DeviceId,
975 desc: &command::RenderBundleEncoderDescriptor,
976 ) -> (
977 Box<command::RenderBundleEncoder>,
978 Option<command::CreateRenderBundleError>,
979 ) {
980 profiling::scope!("Device::create_render_bundle_encoder");
981 api_log!("Device::device_create_render_bundle_encoder");
982 let device = self.hub.devices.get(device_id);
983 let (encoder, error) =
984 match command::RenderBundleEncoder::new(desc, Some(&device), device_id) {
985 Ok(encoder) => (encoder, None),
986 Err(e) => (command::RenderBundleEncoder::dummy(device_id), Some(e)),
987 };
988 (Box::new(encoder), error)
989 }
990
991 pub fn device_create_render_bundle_encoder_with_id(
992 &self,
993 device_id: DeviceId,
994 desc: &command::RenderBundleEncoderDescriptor,
995 id_in: Option<id::RenderBundleEncoderId>,
996 ) -> (
997 id::RenderBundleEncoderId,
998 Option<command::CreateRenderBundleError>,
999 ) {
1000 let fid = self.hub.render_bundle_encoders.prepare(id_in);
1001
1002 let (render_bundle_encoder, error) =
1003 self.device_create_render_bundle_encoder(device_id, desc);
1004
1005 let id = fid.assign(Arc::new(parking_lot::Mutex::new(*render_bundle_encoder)));
1009
1010 (id, error)
1011 }
1012
1013 pub fn render_bundle_encoder_finish(
1014 &self,
1015 bundle_encoder: &mut command::RenderBundleEncoder,
1016 desc: &command::RenderBundleDescriptor,
1017 id_in: Option<id::RenderBundleId>,
1018 ) -> (id::RenderBundleId, Option<command::RenderBundleError>) {
1019 profiling::scope!("RenderBundleEncoder::finish");
1020
1021 let hub = &self.hub;
1022
1023 let fid = hub.render_bundles.prepare(id_in);
1024
1025 let device = self.hub.devices.get(bundle_encoder.parent());
1026
1027 let (render_bundle, error) = bundle_encoder.finish(desc, &device, hub);
1028
1029 let id = fid.assign(render_bundle);
1030
1031 (id, error)
1032 }
1033
1034 pub fn render_bundle_encoder_finish_with_id(
1035 &self,
1036 render_bundle_encoder_id: id::RenderBundleEncoderId,
1037 desc: &command::RenderBundleDescriptor,
1038 id_in: Option<id::RenderBundleId>,
1039 ) -> (id::RenderBundleId, Option<command::RenderBundleError>) {
1040 let bundle_encoder = self
1041 .hub
1042 .render_bundle_encoders
1043 .get(render_bundle_encoder_id);
1044
1045 let mut bundle_encoder = bundle_encoder
1046 .try_lock()
1047 .expect("RenderBundleEncoders should not be accessed concurrently");
1048
1049 let (id, error) = self.render_bundle_encoder_finish(&mut bundle_encoder, desc, id_in);
1050
1051 (id, error)
1052 }
1053
1054 pub fn render_bundle_encoder_drop(&self, render_bundle_encoder_id: id::RenderBundleEncoderId) {
1055 let hub = &self.hub;
1056
1057 let _bundle_encoder = hub.render_bundle_encoders.remove(render_bundle_encoder_id);
1058 }
1059
1060 pub fn render_bundle_drop(&self, render_bundle_id: id::RenderBundleId) {
1061 let hub = &self.hub;
1062
1063 let _bundle = hub.render_bundles.remove(render_bundle_id);
1064 }
1065
1066 pub fn device_create_query_set(
1067 &self,
1068 device_id: DeviceId,
1069 desc: &resource::QuerySetDescriptor,
1070 id_in: Option<id::QuerySetId>,
1071 ) -> (id::QuerySetId, Option<resource::CreateQuerySetError>) {
1072 profiling::scope!("Device::create_query_set");
1073
1074 let hub = &self.hub;
1075 let fid = hub.query_sets.prepare(id_in);
1076
1077 let device = self.hub.devices.get(device_id);
1078
1079 let (query_set, error) = device.create_query_set(desc);
1080
1081 let id = fid.assign(query_set);
1082
1083 (id, error)
1084 }
1085
1086 pub fn query_set_destroy(&self, query_set_id: id::QuerySetId) {
1087 let hub = &self.hub;
1088
1089 let query_set = hub.query_sets.get(query_set_id);
1090
1091 query_set.destroy();
1092 }
1093
1094 pub fn query_set_drop(&self, query_set_id: id::QuerySetId) {
1095 profiling::scope!("QuerySet::drop");
1096 api_log!("QuerySet::drop {query_set_id:?}");
1097
1098 let hub = &self.hub;
1099
1100 let _query_set = hub.query_sets.remove(query_set_id);
1101 }
1102
1103 pub fn device_create_render_pipeline(
1104 &self,
1105 device_id: DeviceId,
1106 desc: &pipeline::RenderPipelineDescriptor,
1107 id_in: Option<id::RenderPipelineId>,
1108 ) -> (
1109 id::RenderPipelineId,
1110 Option<pipeline::CreateRenderPipelineError>,
1111 ) {
1112 profiling::scope!("Device::create_render_pipeline");
1113
1114 let hub = &self.hub;
1115
1116 let fid = hub.render_pipelines.prepare(id_in);
1117
1118 let device = self.hub.devices.get(device_id);
1119
1120 self.device_create_general_render_pipeline(desc.clone().into(), device, fid)
1121 }
1122
1123 pub fn device_create_mesh_pipeline(
1124 &self,
1125 device_id: DeviceId,
1126 desc: &pipeline::MeshPipelineDescriptor,
1127 id_in: Option<id::RenderPipelineId>,
1128 ) -> (
1129 id::RenderPipelineId,
1130 Option<pipeline::CreateRenderPipelineError>,
1131 ) {
1132 let hub = &self.hub;
1133
1134 let fid = hub.render_pipelines.prepare(id_in);
1135
1136 let device = self.hub.devices.get(device_id);
1137 self.device_create_general_render_pipeline(desc.clone().into(), device, fid)
1138 }
1139
1140 fn device_create_general_render_pipeline(
1141 &self,
1142 desc: pipeline::GeneralRenderPipelineDescriptor,
1143 device: Arc<crate::device::resource::Device>,
1144 fid: crate::registry::FutureId<Arc<pipeline::RenderPipeline>>,
1145 ) -> (
1146 id::RenderPipelineId,
1147 Option<pipeline::CreateRenderPipelineError>,
1148 ) {
1149 profiling::scope!("Device::create_general_render_pipeline");
1150
1151 let hub = &self.hub;
1152
1153 let error = 'error: {
1155 if let Err(e) = device.check_is_valid() {
1157 break 'error e.into();
1158 }
1159
1160 let layout = desc.layout.map(|layout| hub.pipeline_layouts.get(layout));
1161
1162 let cache = desc.cache.map(|cache| hub.pipeline_caches.get(cache));
1163
1164 let vertex = match desc.vertex {
1165 RenderPipelineVertexProcessor::Vertex(ref vertex) => {
1166 let module = hub.shader_modules.get(vertex.stage.module);
1167 let stage = ResolvedProgrammableStageDescriptor {
1168 module,
1169 entry_point: vertex.stage.entry_point.clone(),
1170 constants: vertex.stage.constants.clone(),
1171 zero_initialize_workgroup_memory: vertex
1172 .stage
1173 .zero_initialize_workgroup_memory,
1174 };
1175 RenderPipelineVertexProcessor::Vertex(ResolvedVertexState {
1176 stage,
1177 buffers: vertex.buffers.clone(),
1178 })
1179 }
1180 RenderPipelineVertexProcessor::Mesh(ref task, ref mesh) => {
1181 let task_module = if let Some(task) = task {
1182 let module = hub.shader_modules.get(task.stage.module);
1183
1184 let state = ResolvedProgrammableStageDescriptor {
1185 module,
1186 entry_point: task.stage.entry_point.clone(),
1187 constants: task.stage.constants.clone(),
1188 zero_initialize_workgroup_memory: task
1189 .stage
1190 .zero_initialize_workgroup_memory,
1191 };
1192 Some(ResolvedTaskState { stage: state })
1193 } else {
1194 None
1195 };
1196 let mesh_module = hub.shader_modules.get(mesh.stage.module);
1197 let mesh_stage = ResolvedProgrammableStageDescriptor {
1198 module: mesh_module,
1199 entry_point: mesh.stage.entry_point.clone(),
1200 constants: mesh.stage.constants.clone(),
1201 zero_initialize_workgroup_memory: mesh
1202 .stage
1203 .zero_initialize_workgroup_memory,
1204 };
1205 RenderPipelineVertexProcessor::Mesh(
1206 task_module,
1207 ResolvedMeshState { stage: mesh_stage },
1208 )
1209 }
1210 };
1211
1212 let fragment = if let Some(ref state) = desc.fragment {
1213 let module = hub.shader_modules.get(state.stage.module);
1214
1215 let stage = ResolvedProgrammableStageDescriptor {
1216 module,
1217 entry_point: state.stage.entry_point.clone(),
1218 constants: state.stage.constants.clone(),
1219 zero_initialize_workgroup_memory: state.stage.zero_initialize_workgroup_memory,
1220 };
1221 Some(ResolvedFragmentState {
1222 stage,
1223 targets: state.targets.clone(),
1224 })
1225 } else {
1226 None
1227 };
1228
1229 let desc = ResolvedGeneralRenderPipelineDescriptor {
1230 label: desc.label.clone(),
1231 layout,
1232 vertex,
1233 primitive: desc.primitive,
1234 depth_stencil: desc.depth_stencil.clone(),
1235 multisample: desc.multisample,
1236 fragment,
1237 multiview_mask: desc.multiview_mask,
1238 cache,
1239 };
1240
1241 let (pipeline, error) = device.create_render_pipeline(desc);
1242
1243 let id = fid.assign(pipeline);
1244 api_log!("Device::create_render_pipeline -> {id:?}");
1245
1246 return (id, error);
1247 };
1248
1249 let id = fid.assign(pipeline::RenderPipeline::invalid(
1250 device.clone(),
1251 desc.label.to_string(),
1252 ));
1253
1254 (id, Some(error))
1255 }
1256
1257 pub fn render_pipeline_get_bind_group_layout(
1260 &self,
1261 pipeline_id: id::RenderPipelineId,
1262 index: u32,
1263 id_in: Option<id::BindGroupLayoutId>,
1264 ) -> (
1265 id::BindGroupLayoutId,
1266 Option<binding_model::GetBindGroupLayoutError>,
1267 ) {
1268 let hub = &self.hub;
1269
1270 let fid = hub.bind_group_layouts.prepare(id_in);
1271
1272 let pipeline = hub.render_pipelines.get(pipeline_id);
1273
1274 let (bgl, error) = pipeline.get_bind_group_layout(index);
1275
1276 let id = fid.assign(bgl);
1277
1278 (id, error)
1279 }
1280
1281 pub fn render_pipeline_drop(&self, render_pipeline_id: id::RenderPipelineId) {
1282 profiling::scope!("RenderPipeline::drop");
1283 api_log!("RenderPipeline::drop {render_pipeline_id:?}");
1284
1285 let hub = &self.hub;
1286
1287 let _pipeline = hub.render_pipelines.remove(render_pipeline_id);
1288 }
1289
1290 pub fn device_create_compute_pipeline(
1291 &self,
1292 device_id: DeviceId,
1293 desc: &pipeline::ComputePipelineDescriptor,
1294 id_in: Option<id::ComputePipelineId>,
1295 ) -> (
1296 id::ComputePipelineId,
1297 Option<pipeline::CreateComputePipelineError>,
1298 ) {
1299 profiling::scope!("Device::create_compute_pipeline");
1300
1301 let hub = &self.hub;
1302
1303 let fid = hub.compute_pipelines.prepare(id_in);
1304
1305 let device = self.hub.devices.get(device_id);
1306
1307 let error = 'error: {
1309 if let Err(e) = device.check_is_valid() {
1311 break 'error e.into();
1312 }
1313
1314 let layout = desc.layout.map(|layout| hub.pipeline_layouts.get(layout));
1315
1316 let cache = desc.cache.map(|cache| hub.pipeline_caches.get(cache));
1317
1318 let module = hub.shader_modules.get(desc.stage.module);
1319
1320 let stage = ResolvedProgrammableStageDescriptor {
1321 module,
1322 entry_point: desc.stage.entry_point.clone(),
1323 constants: desc.stage.constants.clone(),
1324 zero_initialize_workgroup_memory: desc.stage.zero_initialize_workgroup_memory,
1325 };
1326
1327 let desc = ResolvedComputePipelineDescriptor {
1328 label: desc.label.clone(),
1329 layout,
1330 stage,
1331 cache,
1332 };
1333
1334 let (pipeline, error) = device.create_compute_pipeline(desc);
1335
1336 let id = fid.assign(pipeline);
1337 api_log!("Device::create_compute_pipeline -> {id:?}");
1338
1339 return (id, error);
1340 };
1341
1342 let id = fid.assign(pipeline::ComputePipeline::invalid(
1343 device,
1344 desc.label.to_string(),
1345 ));
1346
1347 (id, Some(error))
1348 }
1349
1350 pub fn compute_pipeline_get_bind_group_layout(
1353 &self,
1354 pipeline_id: id::ComputePipelineId,
1355 index: u32,
1356 id_in: Option<id::BindGroupLayoutId>,
1357 ) -> (
1358 id::BindGroupLayoutId,
1359 Option<binding_model::GetBindGroupLayoutError>,
1360 ) {
1361 let hub = &self.hub;
1362
1363 let fid = hub.bind_group_layouts.prepare(id_in);
1364
1365 let pipeline = hub.compute_pipelines.get(pipeline_id);
1366
1367 let (bgl, error) = pipeline.get_bind_group_layout(index);
1368
1369 let id = fid.assign(bgl);
1370
1371 (id, error)
1372 }
1373
1374 pub fn compute_pipeline_drop(&self, compute_pipeline_id: id::ComputePipelineId) {
1375 profiling::scope!("ComputePipeline::drop");
1376 api_log!("ComputePipeline::drop {compute_pipeline_id:?}");
1377
1378 let hub = &self.hub;
1379
1380 let _pipeline = hub.compute_pipelines.remove(compute_pipeline_id);
1381 }
1382
1383 pub unsafe fn device_create_pipeline_cache(
1387 &self,
1388 device_id: DeviceId,
1389 desc: &pipeline::PipelineCacheDescriptor<'_>,
1390 id_in: Option<id::PipelineCacheId>,
1391 ) -> (
1392 id::PipelineCacheId,
1393 Option<pipeline::CreatePipelineCacheError>,
1394 ) {
1395 profiling::scope!("Device::create_pipeline_cache");
1396
1397 let hub = &self.hub;
1398
1399 let fid = hub.pipeline_caches.prepare(id_in);
1400 let device = self.hub.devices.get(device_id);
1401
1402 let (cache, error) = unsafe { device.create_pipeline_cache(desc) };
1403
1404 let id = fid.assign(cache);
1405
1406 (id, error)
1407 }
1408
1409 pub fn pipeline_cache_drop(&self, pipeline_cache_id: id::PipelineCacheId) {
1410 let hub = &self.hub;
1411
1412 let _cache = hub.pipeline_caches.remove(pipeline_cache_id);
1413 }
1414
1415 pub fn surface_configure(
1416 &self,
1417 surface_id: SurfaceId,
1418 device_id: DeviceId,
1419 config: &wgt::SurfaceConfiguration<Vec<TextureFormat>>,
1420 ) -> Option<present::ConfigureSurfaceError> {
1421 let device = self.hub.devices.get(device_id);
1422 let surface = self.surfaces.get(surface_id);
1423
1424 #[cfg(feature = "trace")]
1425 if let Some(ref mut trace) = *device.trace.lock() {
1426 trace.add(trace::Action::ConfigureSurface(
1427 surface.to_trace(),
1428 config.clone(),
1429 ));
1430 }
1431
1432 device.configure_surface(&surface, config)
1433 }
1434
1435 pub fn device_poll(
1439 &self,
1440 device_id: DeviceId,
1441 poll_type: wgt::PollType<crate::SubmissionIndex>,
1442 ) -> Result<wgt::PollStatus, WaitIdleError> {
1443 api_log!("Device::poll {poll_type:?}");
1444
1445 let device = self.hub.devices.get(device_id);
1446
1447 let (closures, result) = device.poll_and_return_closures(poll_type);
1448
1449 closures.fire();
1450
1451 result
1452 }
1453
1454 fn poll_all_devices_of_api(
1461 &self,
1462 force_wait: bool,
1463 closure_list: &mut UserClosures,
1464 ) -> Result<bool, WaitIdleError> {
1465 profiling::scope!("poll_device");
1466
1467 let hub = &self.hub;
1468 let mut all_queue_empty = true;
1469 {
1470 let device_guard = hub.devices.read();
1471
1472 for (_id, device) in device_guard.iter() {
1473 let poll_type = if force_wait {
1474 wgt::PollType::wait_indefinitely()
1476 } else {
1477 wgt::PollType::Poll
1478 };
1479
1480 let (closures, result) = device.poll_and_return_closures(poll_type);
1481
1482 let is_queue_empty = matches!(result, Ok(wgt::PollStatus::QueueEmpty));
1483
1484 all_queue_empty &= is_queue_empty;
1485
1486 closure_list.extend(closures);
1487 }
1488 }
1489
1490 Ok(all_queue_empty)
1491 }
1492
1493 pub fn poll_all_devices(&self, force_wait: bool) -> Result<bool, WaitIdleError> {
1500 api_log!("poll_all_devices");
1501 let mut closures = UserClosures::default();
1502 let all_queue_empty = self.poll_all_devices_of_api(force_wait, &mut closures)?;
1503
1504 closures.fire();
1505
1506 Ok(all_queue_empty)
1507 }
1508
1509 pub unsafe fn device_start_graphics_debugger_capture(&self, device_id: DeviceId) {
1515 unsafe {
1516 self.hub
1517 .devices
1518 .get(device_id)
1519 .start_graphics_debugger_capture();
1520 }
1521 }
1522
1523 pub unsafe fn device_stop_graphics_debugger_capture(&self, device_id: DeviceId) {
1529 unsafe {
1530 self.hub
1531 .devices
1532 .get(device_id)
1533 .stop_graphics_debugger_capture();
1534 }
1535 }
1536
1537 pub fn pipeline_cache_get_data(&self, id: id::PipelineCacheId) -> Option<Vec<u8>> {
1538 let hub = &self.hub;
1539
1540 hub.pipeline_caches.get(id).get_data()
1541 }
1542
1543 pub fn device_drop(&self, device_id: DeviceId) {
1544 profiling::scope!("Device::drop");
1545 api_log!("Device::drop {device_id:?}");
1546
1547 self.hub.devices.remove(device_id);
1548 }
1549
1550 pub fn device_set_device_lost_closure(
1552 &self,
1553 device_id: DeviceId,
1554 device_lost_closure: DeviceLostClosure,
1555 ) {
1556 let device = self.hub.devices.get(device_id);
1557
1558 device
1559 .device_lost_closure
1560 .lock()
1561 .replace(device_lost_closure);
1562 }
1563
1564 pub fn device_destroy(&self, device_id: DeviceId) {
1565 api_log!("Device::destroy {device_id:?}");
1566
1567 let device = self.hub.devices.get(device_id);
1568
1569 if !device.is_valid() {
1575 return;
1576 }
1577
1578 device.valid.store(false, Ordering::Release);
1586 }
1587
1588 pub fn device_get_internal_counters(&self, device_id: DeviceId) -> wgt::InternalCounters {
1589 let device = self.hub.devices.get(device_id);
1590 wgt::InternalCounters {
1591 hal: device.get_hal_counters(),
1592 core: wgt::CoreCounters {},
1593 }
1594 }
1595
1596 pub fn device_generate_allocator_report(
1597 &self,
1598 device_id: DeviceId,
1599 ) -> Option<wgt::AllocatorReport> {
1600 let device = self.hub.devices.get(device_id);
1601 device.generate_allocator_report()
1602 }
1603
1604 #[cfg(feature = "trace")]
1605 pub fn device_take_trace(
1606 &self,
1607 device_id: DeviceId,
1608 ) -> Option<Box<dyn trace::Trace + Send + Sync + 'static>> {
1609 let device = self.hub.devices.get(device_id);
1610 device.take_trace()
1611 }
1612
1613 pub fn queue_drop(&self, queue_id: QueueId) {
1614 profiling::scope!("Queue::drop");
1615 api_log!("Queue::drop {queue_id:?}");
1616
1617 self.hub.queues.remove(queue_id);
1618 }
1619
1620 pub fn buffer_map_async(
1622 &self,
1623 buffer_id: id::BufferId,
1624 offset: BufferAddress,
1625 size: Option<BufferAddress>,
1626 op: BufferMapOperation,
1627 ) -> Result<crate::SubmissionIndex, BufferAccessError> {
1628 profiling::scope!("Buffer::map_async");
1629 api_log!("Buffer::map_async {buffer_id:?} offset {offset:?} size {size:?} op: {op:?}");
1630
1631 let hub = &self.hub;
1632
1633 let buffer = match hub.buffers.get(buffer_id).get() {
1634 Ok(buffer) => buffer,
1635 Err(err) => {
1636 if let Some(callback) = op.callback {
1637 callback(Err(err.clone().into()));
1638 }
1639 return Err(err.into());
1640 }
1641 };
1642
1643 buffer.map_async(offset, size, op)
1644 }
1645
1646 pub fn buffer_get_mapped_range(
1647 &self,
1648 buffer_id: id::BufferId,
1649 offset: BufferAddress,
1650 size: Option<BufferAddress>,
1651 ) -> Result<(NonNull<u8>, u64), BufferAccessError> {
1652 profiling::scope!("Buffer::get_mapped_range");
1653 api_log!("Buffer::get_mapped_range {buffer_id:?} offset {offset:?} size {size:?}");
1654
1655 let hub = &self.hub;
1656
1657 let buffer = hub.buffers.get(buffer_id).get()?;
1658
1659 buffer.get_mapped_range(offset, size)
1660 }
1661
1662 pub fn buffer_unmap(&self, buffer_id: id::BufferId) -> BufferAccessResult {
1663 profiling::scope!("unmap", "Buffer");
1664 api_log!("Buffer::unmap {buffer_id:?}");
1665
1666 let hub = &self.hub;
1667
1668 let buffer = hub.buffers.get(buffer_id).get()?;
1669
1670 let snatch_guard = buffer.device.snatchable_lock.read();
1671 buffer.check_destroyed(&snatch_guard)?;
1672 drop(snatch_guard);
1673
1674 buffer.device.check_is_valid()?;
1675 buffer.unmap()
1676 }
1677}