wgpu_core/device/
global.rs

1use alloc::{borrow::Cow, boxed::Box, sync::Arc, vec::Vec};
2use core::ptr::NonNull;
3
4#[cfg(feature = "trace")]
5use crate::device::trace;
6use crate::{
7    binding_model::{
8        self, BindGroupEntry, BindingResource, BufferBinding, ResolvedBindGroupDescriptor,
9        ResolvedBindGroupEntry, ResolvedBindingResource, ResolvedBufferBinding,
10    },
11    command,
12    device::{life::WaitIdleError, DeviceError, DeviceLostClosure},
13    global::Global,
14    id::{self, AdapterId, DeviceId, QueueId, SurfaceId},
15    instance::{self, Adapter, Surface},
16    pipeline::{
17        self, RenderPipelineVertexProcessor, ResolvedComputePipelineDescriptor,
18        ResolvedFragmentState, ResolvedGeneralRenderPipelineDescriptor, ResolvedMeshState,
19        ResolvedProgrammableStageDescriptor, ResolvedTaskState, ResolvedVertexState,
20    },
21    present,
22    resource::{
23        self, BufferAccessError, BufferAccessResult, BufferMapOperation, CreateBufferError,
24    },
25    storage::Storage,
26    Label, LabelHelpers,
27};
28
29use wgt::{BufferAddress, TextureFormat};
30
31impl Global {
32    pub fn adapter_is_surface_supported(
33        &self,
34        adapter_id: AdapterId,
35        surface_id: SurfaceId,
36    ) -> bool {
37        let surface = self.surfaces.get(surface_id);
38        let adapter = self.hub.adapters.get(adapter_id);
39        adapter.is_surface_supported(&surface)
40    }
41
42    pub fn surface_get_capabilities(
43        &self,
44        surface_id: SurfaceId,
45        adapter_id: AdapterId,
46    ) -> Result<wgt::SurfaceCapabilities, instance::GetSurfaceSupportError> {
47        self.fetch_adapter_and_surface::<_, _>(surface_id, adapter_id, |adapter, surface| {
48            surface.get_capabilities(adapter)
49        })
50    }
51
52    /// Returns the HDR and luminance characteristics of the display backing
53    /// `surface_id` on `adapter_id`.
54    ///
55    /// Reports the raw display state, independent of the surface's configured
56    /// color space; see [`wgt::DisplayHdrInfo`] for per-field platform coverage.
57    /// Returns [`wgt::DisplayHdrInfo::default`] (all fields `None`) when nothing
58    /// is known: the surface is not on `adapter_id`'s backend, the backend has
59    /// no display-query path, or the Metal backend is queried off the main
60    /// thread.
61    pub fn surface_display_hdr_info(
62        &self,
63        surface_id: SurfaceId,
64        adapter_id: AdapterId,
65    ) -> wgt::DisplayHdrInfo {
66        self.fetch_adapter_and_surface(surface_id, adapter_id, |adapter, surface| {
67            surface.display_hdr_info(adapter)
68        })
69    }
70
71    fn fetch_adapter_and_surface<F: FnOnce(&Adapter, &Surface) -> B, B>(
72        &self,
73        surface_id: SurfaceId,
74        adapter_id: AdapterId,
75        get_supported_callback: F,
76    ) -> B {
77        let surface = self.surfaces.get(surface_id);
78        let adapter = self.hub.adapters.get(adapter_id);
79        get_supported_callback(&adapter, &surface)
80    }
81
82    pub fn device_features(&self, device_id: DeviceId) -> wgt::Features {
83        let device = self.hub.devices.get(device_id);
84        *device.features()
85    }
86
87    pub fn device_limits(&self, device_id: DeviceId) -> wgt::Limits {
88        let device = self.hub.devices.get(device_id);
89        device.limits().clone()
90    }
91
92    pub fn device_adapter_info(&self, device_id: DeviceId) -> wgt::AdapterInfo {
93        let device = self.hub.devices.get(device_id);
94        device.adapter.get_info()
95    }
96
97    pub fn device_downlevel_properties(&self, device_id: DeviceId) -> wgt::DownlevelCapabilities {
98        let device = self.hub.devices.get(device_id);
99        device.downlevel().clone()
100    }
101
102    pub fn device_create_buffer(
103        &self,
104        device_id: DeviceId,
105        desc: &resource::BufferDescriptor,
106        id_in: Option<id::BufferId>,
107    ) -> (id::BufferId, Option<CreateBufferError>) {
108        let hub = &self.hub;
109        let fid = hub.buffers.prepare(id_in);
110
111        let device = self.hub.devices.get(device_id);
112
113        let (buffer, error) = device.create_buffer(desc);
114
115        let id = fid.assign(buffer);
116
117        (id, error)
118    }
119
120    /// Assign `id_in` an error with the given `label`.
121    ///
122    /// Ensure that future attempts to use `id_in` as a buffer ID will propagate
123    /// the error, following the WebGPU ["contagious invalidity"] style.
124    ///
125    /// Firefox uses this function to comply strictly with the WebGPU spec,
126    /// which requires [`GPUBufferDescriptor`] validation to be generated on the
127    /// Device timeline and leave the newly created [`GPUBuffer`] invalid.
128    ///
129    /// Ideally, we would simply let [`Device::create_buffer`] take care of all
130    /// of this, but some errors must be detected before we can even construct a
131    /// [`wgpu_types::BufferDescriptor`] to give it. For example, the WebGPU API
132    /// allows a `GPUBufferDescriptor`'s [`usage`] property to be any WebIDL
133    /// `unsigned long` value, but we can't construct a
134    /// [`wgpu_types::BufferUsages`] value from values with unassigned bits
135    /// set. This means we must validate `usage` before we can call
136    /// `Device::create_buffer`.
137    ///
138    /// When that validation fails, we must arrange for the buffer id to be
139    /// considered invalid. This method provides the means to do so.
140    ///
141    /// ["contagious invalidity"]: https://www.w3.org/TR/webgpu/#invalidity
142    /// [`GPUBufferDescriptor`]: https://www.w3.org/TR/webgpu/#dictdef-gpubufferdescriptor
143    /// [`GPUBuffer`]: https://www.w3.org/TR/webgpu/#gpubuffer
144    /// [`wgpu_types::BufferDescriptor`]: wgt::BufferDescriptor
145    /// [`Device::create_buffer`]: crate::device::Device::create_buffer
146    /// [`usage`]: https://www.w3.org/TR/webgpu/#dom-gputexturedescriptor-usage
147    /// [`wgpu_types::BufferUsages`]: wgt::BufferUsages
148    pub fn create_buffer_error(
149        &self,
150        device_id: DeviceId,
151        id_in: Option<id::BufferId>,
152        desc: &resource::BufferDescriptor,
153    ) {
154        let fid = self.hub.buffers.prepare(id_in);
155        let device = self.hub.devices.get(device_id);
156        fid.assign(resource::Buffer::invalid(device, desc));
157    }
158
159    /// Assign `id_in` an error with the given `label`.
160    ///
161    /// See [`Self::create_buffer_error`] for more context and explanation.
162    pub fn create_render_bundle_error(
163        &self,
164        device_id: DeviceId,
165        id_in: Option<id::RenderBundleId>,
166        desc: &command::RenderBundleDescriptor,
167    ) {
168        let device = self.hub.devices.get(device_id);
169        let fid = self.hub.render_bundles.prepare(id_in);
170        fid.assign(command::RenderBundle::invalid(device, desc));
171    }
172
173    /// Assign `id_in` an error with the given `label`.
174    ///
175    /// See [`Self::create_buffer_error`] for more context and explanation.
176    pub fn create_texture_error(
177        &self,
178        device_id: DeviceId,
179        id_in: Option<id::TextureId>,
180        desc: &resource::TextureDescriptor,
181    ) -> id::TextureId {
182        let fid = self.hub.textures.prepare(id_in);
183        let device = self.hub.devices.get(device_id);
184        let texture = device.create_texture_error(desc);
185        fid.assign(texture)
186    }
187
188    /// Assign `id_in` an error with the given `label`.
189    ///
190    /// See [`Self::create_buffer_error`] for more context and explanation.
191    pub fn create_external_texture_error(
192        &self,
193        device_id: DeviceId,
194        id_in: Option<id::ExternalTextureId>,
195        desc: &resource::ExternalTextureDescriptor,
196    ) {
197        let fid = self.hub.external_textures.prepare(id_in);
198        let device = self.hub.devices.get(device_id);
199        fid.assign(resource::ExternalTexture::invalid(device, desc));
200    }
201
202    /// Assign `id_in` an error with the given `label`.
203    ///
204    /// In JavaScript environments, it is possible to call `GPUDevice.createBindGroupLayout` with
205    /// entries that are invalid. Because our Rust's types for bind group layouts prevent even
206    /// calling [`Self::device_create_bind_group`], we let standards-compliant environments
207    /// register an invalid bind group layout so this crate's API can still be consistently used.
208    ///
209    /// See [`Self::create_buffer_error`] for additional context and explanation.
210    pub fn create_bind_group_layout_error(
211        &self,
212        device_id: DeviceId,
213        id_in: Option<id::BindGroupLayoutId>,
214        label: Option<Cow<'_, str>>,
215    ) {
216        let fid = self.hub.bind_group_layouts.prepare(id_in);
217        let device = self.hub.devices.get(device_id);
218        fid.assign(binding_model::BindGroupLayout::invalid(
219            &device,
220            label.to_string(),
221        ));
222    }
223
224    pub fn buffer_destroy(&self, buffer_id: id::BufferId) {
225        let hub = &self.hub;
226
227        let buffer = hub.buffers.get(buffer_id);
228
229        buffer.destroy();
230    }
231
232    pub fn buffer_drop(&self, buffer_id: id::BufferId) {
233        let hub = &self.hub;
234
235        let _buffer = hub.buffers.remove(buffer_id);
236    }
237
238    pub fn device_create_texture(
239        &self,
240        device_id: DeviceId,
241        desc: &resource::TextureDescriptor,
242        id_in: Option<id::TextureId>,
243    ) -> (id::TextureId, Option<resource::CreateTextureError>) {
244        let hub = &self.hub;
245
246        let fid = hub.textures.prepare(id_in);
247
248        let device = self.hub.devices.get(device_id);
249
250        let (texture, error) = device.create_texture(desc);
251
252        let id = fid.assign(texture);
253
254        (id, error)
255    }
256
257    /// # Safety
258    ///
259    /// - `hal_texture` must be created from `device_id` corresponding raw handle.
260    /// - `hal_texture` must be created respecting `desc`
261    /// - `hal_texture` must be initialized
262    /// - The `initial_state` must match the actual driver-side state of
263    ///   the wrapped resource at the moment of wrap.
264    pub unsafe fn create_texture_from_hal(
265        &self,
266        hal_texture: Box<dyn hal::DynTexture>,
267        device_id: DeviceId,
268        desc: &resource::TextureDescriptor,
269        initial_state: wgt::TextureUses,
270        id_in: Option<id::TextureId>,
271    ) -> (id::TextureId, Option<resource::CreateTextureError>) {
272        let hub = &self.hub;
273
274        let fid = hub.textures.prepare(id_in);
275
276        let device = self.hub.devices.get(device_id);
277
278        let (texture, error) =
279            unsafe { device.create_texture_from_hal(hal_texture, desc, initial_state) };
280
281        let id = fid.assign(texture);
282        (id, error)
283    }
284
285    /// # Safety
286    ///
287    /// - `hal_buffer` must be created from `device_id` corresponding raw handle.
288    /// - `hal_buffer` must be created respecting `desc`
289    /// - `hal_buffer` must be initialized
290    /// - `hal_buffer` must not have zero size.
291    pub unsafe fn create_buffer_from_hal<A: hal::Api>(
292        &self,
293        hal_buffer: A::Buffer,
294        device_id: DeviceId,
295        desc: &resource::BufferDescriptor,
296        id_in: Option<id::BufferId>,
297    ) -> (id::BufferId, Option<CreateBufferError>) {
298        let hub = &self.hub;
299        let fid = hub.buffers.prepare(id_in);
300
301        let device = self.hub.devices.get(device_id);
302
303        let (buffer, err) = unsafe { device.create_buffer_from_hal(Box::new(hal_buffer), desc) };
304
305        let id = fid.assign(buffer);
306
307        (id, err)
308    }
309
310    pub fn texture_destroy(&self, texture_id: id::TextureId) {
311        let hub = &self.hub;
312
313        let texture = hub.textures.get(texture_id);
314
315        texture.destroy();
316    }
317
318    pub fn texture_drop(&self, texture_id: id::TextureId) {
319        let hub = &self.hub;
320
321        hub.textures.remove(texture_id);
322    }
323
324    pub fn texture_create_view(
325        &self,
326        texture_id: id::TextureId,
327        desc: &resource::TextureViewDescriptor,
328        id_in: Option<id::TextureViewId>,
329    ) -> (id::TextureViewId, Option<resource::CreateTextureViewError>) {
330        let hub = &self.hub;
331
332        let fid = hub.texture_views.prepare(id_in);
333
334        let texture = hub.textures.get(texture_id);
335        let device = &texture.device;
336
337        let (view, error) = device.create_texture_view(&texture, desc);
338
339        let id = fid.assign(view);
340
341        (id, error)
342    }
343
344    pub fn texture_view_drop(&self, texture_view_id: id::TextureViewId) {
345        let hub = &self.hub;
346
347        let _view = hub.texture_views.remove(texture_view_id);
348    }
349
350    pub fn device_create_external_texture(
351        &self,
352        device_id: DeviceId,
353        desc: &resource::ExternalTextureDescriptor,
354        planes: &[id::TextureViewId],
355        id_in: Option<id::ExternalTextureId>,
356    ) -> (
357        id::ExternalTextureId,
358        Option<resource::CreateExternalTextureError>,
359    ) {
360        let hub = &self.hub;
361
362        let fid = hub.external_textures.prepare(id_in);
363
364        let device = self.hub.devices.get(device_id);
365
366        let planes = planes
367            .iter()
368            .map(|plane_id| self.hub.texture_views.get(*plane_id))
369            .collect::<Vec<_>>();
370
371        let (external_texture, error) = device.create_external_texture(desc, &planes);
372
373        let id = fid.assign(external_texture);
374
375        (id, error)
376    }
377
378    pub fn external_texture_destroy(&self, external_texture_id: id::ExternalTextureId) {
379        let hub = &self.hub;
380
381        let external_texture = hub.external_textures.get(external_texture_id);
382
383        external_texture.destroy();
384    }
385
386    pub fn external_texture_drop(&self, external_texture_id: id::ExternalTextureId) {
387        let hub = &self.hub;
388
389        let _external_texture = hub.external_textures.remove(external_texture_id);
390    }
391
392    pub fn device_create_sampler(
393        &self,
394        device_id: DeviceId,
395        desc: &resource::SamplerDescriptor,
396        id_in: Option<id::SamplerId>,
397    ) -> (id::SamplerId, Option<resource::CreateSamplerError>) {
398        let hub = &self.hub;
399        let fid = hub.samplers.prepare(id_in);
400
401        let device = self.hub.devices.get(device_id);
402
403        let (sampler, error) = device.create_sampler(desc);
404
405        let id = fid.assign(sampler);
406
407        (id, error)
408    }
409
410    pub fn sampler_drop(&self, sampler_id: id::SamplerId) {
411        let hub = &self.hub;
412
413        let _sampler = hub.samplers.remove(sampler_id);
414    }
415
416    pub fn device_create_bind_group_layout(
417        &self,
418        device_id: DeviceId,
419        desc: &binding_model::BindGroupLayoutDescriptor,
420        id_in: Option<id::BindGroupLayoutId>,
421    ) -> (
422        id::BindGroupLayoutId,
423        Option<binding_model::CreateBindGroupLayoutError>,
424    ) {
425        let hub = &self.hub;
426        let fid = hub.bind_group_layouts.prepare(id_in);
427
428        let device = self.hub.devices.get(device_id);
429
430        let (bgl, error) = device.create_bind_group_layout(desc);
431
432        let id = fid.assign(bgl);
433
434        (id, error)
435    }
436
437    pub fn bind_group_layout_drop(&self, bind_group_layout_id: id::BindGroupLayoutId) {
438        let hub = &self.hub;
439
440        let _layout = hub.bind_group_layouts.remove(bind_group_layout_id);
441    }
442
443    pub fn device_create_pipeline_layout(
444        &self,
445        device_id: DeviceId,
446        desc: &binding_model::PipelineLayoutDescriptor,
447        id_in: Option<id::PipelineLayoutId>,
448    ) -> (
449        id::PipelineLayoutId,
450        Option<binding_model::CreatePipelineLayoutError>,
451    ) {
452        let hub = &self.hub;
453        let fid = hub.pipeline_layouts.prepare(id_in);
454
455        let device = self.hub.devices.get(device_id);
456
457        let bind_group_layouts = {
458            let bind_group_layouts_guard = hub.bind_group_layouts.read();
459            desc.bind_group_layouts
460                .iter()
461                .map(|bgl_id| bgl_id.map(|bgl_id| bind_group_layouts_guard.get(bgl_id)))
462                .collect::<Vec<_>>()
463        };
464
465        let desc = binding_model::ResolvedPipelineLayoutDescriptor {
466            label: desc.label.clone(),
467            bind_group_layouts: Cow::Owned(bind_group_layouts),
468            immediate_size: desc.immediate_size,
469        };
470
471        let (layout, error) = device.create_pipeline_layout(&desc);
472        let id = fid.assign(layout);
473        (id, error)
474    }
475
476    pub fn pipeline_layout_drop(&self, pipeline_layout_id: id::PipelineLayoutId) {
477        let hub = &self.hub;
478
479        let _layout = hub.pipeline_layouts.remove(pipeline_layout_id);
480    }
481
482    pub fn device_create_bind_group(
483        &self,
484        device_id: DeviceId,
485        desc: &binding_model::BindGroupDescriptor,
486        id_in: Option<id::BindGroupId>,
487    ) -> (id::BindGroupId, Option<binding_model::CreateBindGroupError>) {
488        let hub = &self.hub;
489        let fid = hub.bind_groups.prepare(id_in);
490
491        let device = hub.devices.get(device_id);
492
493        let layout = hub.bind_group_layouts.get(desc.layout);
494
495        fn resolve_entry<'a>(
496            e: &BindGroupEntry<'a>,
497            buffer_storage: &Storage<Arc<resource::Buffer>>,
498            sampler_storage: &Storage<Arc<resource::Sampler>>,
499            texture_view_storage: &Storage<Arc<resource::TextureView>>,
500            tlas_storage: &Storage<Arc<resource::Tlas>>,
501            external_texture_storage: &Storage<Arc<resource::ExternalTexture>>,
502        ) -> ResolvedBindGroupEntry<'a> {
503            let resolve_buffer = |bb: &BufferBinding| {
504                let buffer = buffer_storage.get(bb.buffer);
505                ResolvedBufferBinding {
506                    buffer,
507                    offset: bb.offset,
508                    size: bb.size,
509                }
510            };
511            let resolve_sampler = |id: &id::SamplerId| sampler_storage.get(*id);
512            let resolve_view = |id: &id::TextureViewId| texture_view_storage.get(*id);
513            let resolve_tlas = |id: &id::TlasId| tlas_storage.get(*id);
514            let resolve_external_texture =
515                |id: &id::ExternalTextureId| external_texture_storage.get(*id);
516            let resource = match e.resource {
517                BindingResource::Buffer(ref buffer) => {
518                    ResolvedBindingResource::Buffer(resolve_buffer(buffer))
519                }
520                BindingResource::BufferArray(ref buffers) => {
521                    let buffers = buffers.iter().map(resolve_buffer).collect::<Vec<_>>();
522                    ResolvedBindingResource::BufferArray(Cow::Owned(buffers))
523                }
524                BindingResource::Sampler(ref sampler) => {
525                    ResolvedBindingResource::Sampler(resolve_sampler(sampler))
526                }
527                BindingResource::SamplerArray(ref samplers) => {
528                    let samplers = samplers.iter().map(resolve_sampler).collect::<Vec<_>>();
529                    ResolvedBindingResource::SamplerArray(Cow::Owned(samplers))
530                }
531                BindingResource::TextureView(ref view) => {
532                    ResolvedBindingResource::TextureView(resolve_view(view))
533                }
534                BindingResource::TextureViewArray(ref views) => {
535                    let views = views.iter().map(resolve_view).collect::<Vec<_>>();
536                    ResolvedBindingResource::TextureViewArray(Cow::Owned(views))
537                }
538                BindingResource::AccelerationStructure(ref tlas) => {
539                    ResolvedBindingResource::AccelerationStructure(resolve_tlas(tlas))
540                }
541                BindingResource::AccelerationStructureArray(ref tlas_array) => {
542                    let tlas_array = tlas_array.iter().map(resolve_tlas).collect::<Vec<_>>();
543                    ResolvedBindingResource::AccelerationStructureArray(Cow::Owned(tlas_array))
544                }
545                BindingResource::ExternalTexture(ref et) => {
546                    ResolvedBindingResource::ExternalTexture(resolve_external_texture(et))
547                }
548            };
549            ResolvedBindGroupEntry {
550                binding: e.binding,
551                resource,
552            }
553        }
554
555        let entries = {
556            let buffer_guard = hub.buffers.read();
557            let texture_view_guard = hub.texture_views.read();
558            let sampler_guard = hub.samplers.read();
559            let tlas_guard = hub.tlas_s.read();
560            let external_texture_guard = hub.external_textures.read();
561            desc.entries
562                .iter()
563                .map(|e| {
564                    resolve_entry(
565                        e,
566                        &buffer_guard,
567                        &sampler_guard,
568                        &texture_view_guard,
569                        &tlas_guard,
570                        &external_texture_guard,
571                    )
572                })
573                .collect::<Vec<_>>()
574        };
575        let entries = Cow::Owned(entries);
576
577        let desc = ResolvedBindGroupDescriptor {
578            label: desc.label.clone(),
579            layout,
580            entries,
581        };
582
583        let (bind_group, error) = device.create_bind_group(&desc);
584
585        let id = fid.assign(bind_group);
586        (id, error)
587    }
588
589    pub fn bind_group_drop(&self, bind_group_id: id::BindGroupId) {
590        let hub = &self.hub;
591
592        let _bind_group = hub.bind_groups.remove(bind_group_id);
593    }
594
595    /// Create a shader module with the given `source`.
596    ///
597    /// <div class="warning">
598    // NOTE: Keep this in sync with `naga::front::wgsl::parse_str`!
599    // NOTE: Keep this in sync with `wgpu::Device::create_shader_module`!
600    ///
601    /// This function may consume a lot of stack space. Compiler-enforced limits for parsing
602    /// recursion exist; if shader compilation runs into them, it will return an error gracefully.
603    /// However, on some build profiles and platforms, the default stack size for a thread may be
604    /// exceeded before this limit is reached during parsing. Callers should ensure that there is
605    /// enough stack space for this, particularly if calls to this method are exposed to user
606    /// input.
607    ///
608    /// </div>
609    pub fn device_create_shader_module(
610        &self,
611        device_id: DeviceId,
612        desc: &pipeline::ShaderModuleDescriptor,
613        source: pipeline::ShaderModuleSource,
614        id_in: Option<id::ShaderModuleId>,
615    ) -> (
616        id::ShaderModuleId,
617        Option<pipeline::CreateShaderModuleError>,
618    ) {
619        let hub = &self.hub;
620        let fid = hub.shader_modules.prepare(id_in);
621
622        let device = self.hub.devices.get(device_id);
623
624        let (shader, error) = device.create_shader_module(desc, source);
625
626        let id = fid.assign(shader);
627
628        (id, error)
629    }
630
631    /// # Safety
632    ///
633    /// This function passes source code or binary to the backend as-is and can potentially result in a
634    /// driver crash.
635    pub unsafe fn device_create_shader_module_passthrough(
636        &self,
637        device_id: DeviceId,
638        desc: &pipeline::ShaderModuleDescriptorPassthrough<'_>,
639        id_in: Option<id::ShaderModuleId>,
640    ) -> (
641        id::ShaderModuleId,
642        Option<pipeline::CreateShaderModuleError>,
643    ) {
644        let hub = &self.hub;
645        let fid = hub.shader_modules.prepare(id_in);
646
647        let device = self.hub.devices.get(device_id);
648
649        let (shader, error) = unsafe { device.create_shader_module_passthrough(desc) };
650
651        let id = fid.assign(shader);
652
653        (id, error)
654    }
655
656    pub fn shader_module_drop(&self, shader_module_id: id::ShaderModuleId) {
657        let hub = &self.hub;
658
659        let _shader_module = hub.shader_modules.remove(shader_module_id);
660    }
661
662    pub fn device_create_command_encoder(
663        &self,
664        device_id: DeviceId,
665        desc: &wgt::CommandEncoderDescriptor<Label>,
666        id_in: Option<id::CommandEncoderId>,
667    ) -> (id::CommandEncoderId, Option<DeviceError>) {
668        let hub = &self.hub;
669        let fid = hub.command_encoders.prepare(id_in);
670
671        let device = self.hub.devices.get(device_id);
672
673        let (cmd_enc, error) = device.create_command_encoder(desc);
674
675        let id = fid.assign(cmd_enc);
676        (id, error)
677    }
678
679    pub fn command_encoder_drop(&self, command_encoder_id: id::CommandEncoderId) {
680        let _cmd_enc = self.hub.command_encoders.remove(command_encoder_id);
681    }
682
683    pub fn command_buffer_drop(&self, command_buffer_id: id::CommandBufferId) {
684        let _cmd_buf = self.hub.command_buffers.remove(command_buffer_id);
685    }
686
687    pub fn device_create_render_bundle_encoder(
688        &self,
689        device_id: DeviceId,
690        desc: &command::RenderBundleEncoderDescriptor,
691    ) -> (
692        Box<command::RenderBundleEncoder>,
693        Option<command::CreateRenderBundleError>,
694    ) {
695        let device = self.hub.devices.get(device_id);
696        device.create_render_bundle_encoder(desc)
697    }
698
699    pub fn device_create_render_bundle_encoder_with_id(
700        &self,
701        device_id: DeviceId,
702        desc: &command::RenderBundleEncoderDescriptor,
703        id_in: Option<id::RenderBundleEncoderId>,
704    ) -> (
705        id::RenderBundleEncoderId,
706        Option<command::CreateRenderBundleError>,
707    ) {
708        let fid = self.hub.render_bundle_encoders.prepare(id_in);
709
710        let (render_bundle_encoder, error) =
711            self.device_create_render_bundle_encoder(device_id, desc);
712
713        // no lock rank here because only one thread should be using compute pass
714        // and it's only used by id variants of compute pass methods on global
715        // so no deadlock (or concurrent lock) should happen in practise
716        let id = fid.assign(Arc::new(parking_lot::Mutex::new(*render_bundle_encoder)));
717
718        (id, error)
719    }
720
721    pub fn render_bundle_encoder_finish(
722        &self,
723        bundle_encoder: &mut command::RenderBundleEncoder,
724        desc: &command::RenderBundleDescriptor,
725        id_in: Option<id::RenderBundleId>,
726    ) -> (id::RenderBundleId, Option<command::RenderBundleError>) {
727        let hub = &self.hub;
728
729        let fid = hub.render_bundles.prepare(id_in);
730
731        let (render_bundle, error) = bundle_encoder.finish(desc);
732
733        let id = fid.assign(render_bundle);
734
735        (id, error)
736    }
737
738    pub fn render_bundle_encoder_finish_with_id(
739        &self,
740        render_bundle_encoder_id: id::RenderBundleEncoderId,
741        desc: &command::RenderBundleDescriptor,
742        id_in: Option<id::RenderBundleId>,
743    ) -> (id::RenderBundleId, Option<command::RenderBundleError>) {
744        let bundle_encoder = self
745            .hub
746            .render_bundle_encoders
747            .get(render_bundle_encoder_id);
748
749        let mut bundle_encoder = bundle_encoder
750            .try_lock()
751            .expect("RenderBundleEncoders should not be accessed concurrently");
752
753        let (id, error) = self.render_bundle_encoder_finish(&mut bundle_encoder, desc, id_in);
754
755        (id, error)
756    }
757
758    pub fn render_bundle_encoder_drop(&self, render_bundle_encoder_id: id::RenderBundleEncoderId) {
759        let hub = &self.hub;
760
761        let _bundle_encoder = hub.render_bundle_encoders.remove(render_bundle_encoder_id);
762    }
763
764    pub fn render_bundle_drop(&self, render_bundle_id: id::RenderBundleId) {
765        let hub = &self.hub;
766
767        let _bundle = hub.render_bundles.remove(render_bundle_id);
768    }
769
770    pub fn device_create_query_set(
771        &self,
772        device_id: DeviceId,
773        desc: &resource::QuerySetDescriptor,
774        id_in: Option<id::QuerySetId>,
775    ) -> (id::QuerySetId, Option<resource::CreateQuerySetError>) {
776        let hub = &self.hub;
777        let fid = hub.query_sets.prepare(id_in);
778
779        let device = self.hub.devices.get(device_id);
780
781        let (query_set, error) = device.create_query_set(desc);
782
783        let id = fid.assign(query_set);
784
785        (id, error)
786    }
787
788    pub fn query_set_destroy(&self, query_set_id: id::QuerySetId) {
789        let hub = &self.hub;
790
791        let query_set = hub.query_sets.get(query_set_id);
792
793        query_set.destroy();
794    }
795
796    pub fn query_set_drop(&self, query_set_id: id::QuerySetId) {
797        let hub = &self.hub;
798
799        let _query_set = hub.query_sets.remove(query_set_id);
800    }
801
802    pub fn device_create_render_pipeline(
803        &self,
804        device_id: DeviceId,
805        desc: &pipeline::RenderPipelineDescriptor,
806        id_in: Option<id::RenderPipelineId>,
807    ) -> (
808        id::RenderPipelineId,
809        Option<pipeline::CreateRenderPipelineError>,
810    ) {
811        let hub = &self.hub;
812
813        let fid = hub.render_pipelines.prepare(id_in);
814
815        let device = self.hub.devices.get(device_id);
816
817        self.device_create_general_render_pipeline(desc.clone().into(), device, fid)
818    }
819
820    pub fn device_create_mesh_pipeline(
821        &self,
822        device_id: DeviceId,
823        desc: &pipeline::MeshPipelineDescriptor,
824        id_in: Option<id::RenderPipelineId>,
825    ) -> (
826        id::RenderPipelineId,
827        Option<pipeline::CreateRenderPipelineError>,
828    ) {
829        let hub = &self.hub;
830
831        let fid = hub.render_pipelines.prepare(id_in);
832
833        let device = self.hub.devices.get(device_id);
834        self.device_create_general_render_pipeline(desc.clone().into(), device, fid)
835    }
836
837    fn device_create_general_render_pipeline(
838        &self,
839        desc: pipeline::GeneralRenderPipelineDescriptor,
840        device: Arc<crate::device::resource::Device>,
841        fid: crate::registry::FutureId<Arc<pipeline::RenderPipeline>>,
842    ) -> (
843        id::RenderPipelineId,
844        Option<pipeline::CreateRenderPipelineError>,
845    ) {
846        let hub = &self.hub;
847
848        let layout = desc.layout.map(|layout| hub.pipeline_layouts.get(layout));
849
850        let cache = desc.cache.map(|cache| hub.pipeline_caches.get(cache));
851
852        let vertex = match desc.vertex {
853            RenderPipelineVertexProcessor::Vertex(ref vertex) => {
854                let module = hub.shader_modules.get(vertex.stage.module);
855                let stage = ResolvedProgrammableStageDescriptor {
856                    module,
857                    entry_point: vertex.stage.entry_point.clone(),
858                    constants: vertex.stage.constants.clone(),
859                    zero_initialize_workgroup_memory: vertex.stage.zero_initialize_workgroup_memory,
860                };
861                RenderPipelineVertexProcessor::Vertex(ResolvedVertexState {
862                    stage,
863                    buffers: vertex.buffers.clone(),
864                })
865            }
866            RenderPipelineVertexProcessor::Mesh(ref task, ref mesh) => {
867                let task_module = if let Some(task) = task {
868                    let module = hub.shader_modules.get(task.stage.module);
869
870                    let state = ResolvedProgrammableStageDescriptor {
871                        module,
872                        entry_point: task.stage.entry_point.clone(),
873                        constants: task.stage.constants.clone(),
874                        zero_initialize_workgroup_memory: task
875                            .stage
876                            .zero_initialize_workgroup_memory,
877                    };
878                    Some(ResolvedTaskState { stage: state })
879                } else {
880                    None
881                };
882                let mesh_module = hub.shader_modules.get(mesh.stage.module);
883                let mesh_stage = ResolvedProgrammableStageDescriptor {
884                    module: mesh_module,
885                    entry_point: mesh.stage.entry_point.clone(),
886                    constants: mesh.stage.constants.clone(),
887                    zero_initialize_workgroup_memory: mesh.stage.zero_initialize_workgroup_memory,
888                };
889                RenderPipelineVertexProcessor::Mesh(
890                    task_module,
891                    ResolvedMeshState { stage: mesh_stage },
892                )
893            }
894        };
895
896        let fragment = if let Some(ref state) = desc.fragment {
897            let module = hub.shader_modules.get(state.stage.module);
898
899            let stage = ResolvedProgrammableStageDescriptor {
900                module,
901                entry_point: state.stage.entry_point.clone(),
902                constants: state.stage.constants.clone(),
903                zero_initialize_workgroup_memory: state.stage.zero_initialize_workgroup_memory,
904            };
905            Some(ResolvedFragmentState {
906                stage,
907                targets: state.targets.clone(),
908            })
909        } else {
910            None
911        };
912
913        let desc = ResolvedGeneralRenderPipelineDescriptor {
914            label: desc.label.clone(),
915            layout,
916            vertex,
917            primitive: desc.primitive,
918            depth_stencil: desc.depth_stencil.clone(),
919            multisample: desc.multisample,
920            fragment,
921            multiview_mask: desc.multiview_mask,
922            cache,
923        };
924
925        let (pipeline, error) = device.create_render_pipeline(desc);
926
927        let id = fid.assign(pipeline);
928
929        (id, error)
930    }
931
932    /// Get an ID of one of the bind group layouts. The ID adds a refcount,
933    /// which needs to be released by calling `bind_group_layout_drop`.
934    pub fn render_pipeline_get_bind_group_layout(
935        &self,
936        pipeline_id: id::RenderPipelineId,
937        index: u32,
938        id_in: Option<id::BindGroupLayoutId>,
939    ) -> (
940        id::BindGroupLayoutId,
941        Option<binding_model::GetBindGroupLayoutError>,
942    ) {
943        let hub = &self.hub;
944
945        let fid = hub.bind_group_layouts.prepare(id_in);
946
947        let pipeline = hub.render_pipelines.get(pipeline_id);
948
949        let (bgl, error) = pipeline.get_bind_group_layout(index);
950
951        let id = fid.assign(bgl);
952
953        (id, error)
954    }
955
956    pub fn render_pipeline_drop(&self, render_pipeline_id: id::RenderPipelineId) {
957        let hub = &self.hub;
958
959        let _pipeline = hub.render_pipelines.remove(render_pipeline_id);
960    }
961
962    pub fn device_create_compute_pipeline(
963        &self,
964        device_id: DeviceId,
965        desc: &pipeline::ComputePipelineDescriptor,
966        id_in: Option<id::ComputePipelineId>,
967    ) -> (
968        id::ComputePipelineId,
969        Option<pipeline::CreateComputePipelineError>,
970    ) {
971        let hub = &self.hub;
972
973        let fid = hub.compute_pipelines.prepare(id_in);
974
975        let device = self.hub.devices.get(device_id);
976
977        let layout = desc.layout.map(|layout| hub.pipeline_layouts.get(layout));
978
979        let cache = desc.cache.map(|cache| hub.pipeline_caches.get(cache));
980
981        let module = hub.shader_modules.get(desc.stage.module);
982
983        let stage = ResolvedProgrammableStageDescriptor {
984            module,
985            entry_point: desc.stage.entry_point.clone(),
986            constants: desc.stage.constants.clone(),
987            zero_initialize_workgroup_memory: desc.stage.zero_initialize_workgroup_memory,
988        };
989
990        let desc = ResolvedComputePipelineDescriptor {
991            label: desc.label.clone(),
992            layout,
993            stage,
994            cache,
995        };
996
997        let (pipeline, error) = device.create_compute_pipeline(desc);
998
999        let id = fid.assign(pipeline);
1000
1001        (id, error)
1002    }
1003
1004    /// Get an ID of one of the bind group layouts. The ID adds a refcount,
1005    /// which needs to be released by calling `bind_group_layout_drop`.
1006    pub fn compute_pipeline_get_bind_group_layout(
1007        &self,
1008        pipeline_id: id::ComputePipelineId,
1009        index: u32,
1010        id_in: Option<id::BindGroupLayoutId>,
1011    ) -> (
1012        id::BindGroupLayoutId,
1013        Option<binding_model::GetBindGroupLayoutError>,
1014    ) {
1015        let hub = &self.hub;
1016
1017        let fid = hub.bind_group_layouts.prepare(id_in);
1018
1019        let pipeline = hub.compute_pipelines.get(pipeline_id);
1020
1021        let (bgl, error) = pipeline.get_bind_group_layout(index);
1022
1023        let id = fid.assign(bgl);
1024
1025        (id, error)
1026    }
1027
1028    pub fn compute_pipeline_drop(&self, compute_pipeline_id: id::ComputePipelineId) {
1029        let hub = &self.hub;
1030
1031        let _pipeline = hub.compute_pipelines.remove(compute_pipeline_id);
1032    }
1033
1034    /// # Safety
1035    /// The `data` argument of `desc` must have been returned by
1036    /// [Self::pipeline_cache_get_data] for the same adapter
1037    pub unsafe fn device_create_pipeline_cache(
1038        &self,
1039        device_id: DeviceId,
1040        desc: &pipeline::PipelineCacheDescriptor<'_>,
1041        id_in: Option<id::PipelineCacheId>,
1042    ) -> (
1043        id::PipelineCacheId,
1044        Option<pipeline::CreatePipelineCacheError>,
1045    ) {
1046        let hub = &self.hub;
1047
1048        let fid = hub.pipeline_caches.prepare(id_in);
1049        let device = self.hub.devices.get(device_id);
1050
1051        let (cache, error) = unsafe { device.create_pipeline_cache(desc) };
1052
1053        let id = fid.assign(cache);
1054
1055        (id, error)
1056    }
1057
1058    pub fn pipeline_cache_drop(&self, pipeline_cache_id: id::PipelineCacheId) {
1059        let hub = &self.hub;
1060
1061        let _cache = hub.pipeline_caches.remove(pipeline_cache_id);
1062    }
1063
1064    pub fn surface_configure(
1065        &self,
1066        surface_id: SurfaceId,
1067        device_id: DeviceId,
1068        config: &wgt::SurfaceConfiguration<Vec<TextureFormat>>,
1069    ) -> Option<present::ConfigureSurfaceError> {
1070        let device = self.hub.devices.get(device_id);
1071        let surface = self.surfaces.get(surface_id);
1072
1073        surface.configure(&device, config)
1074    }
1075
1076    /// Check `device_id` for freeable resources and completed buffer mappings.
1077    ///
1078    /// Return `queue_empty` indicating whether there are more queue submissions still in flight.
1079    pub fn device_poll(
1080        &self,
1081        device_id: DeviceId,
1082        poll_type: wgt::PollType<crate::SubmissionIndex>,
1083    ) -> Result<wgt::PollStatus, WaitIdleError> {
1084        let device = self.hub.devices.get(device_id);
1085
1086        device.poll(poll_type)
1087    }
1088
1089    /// Poll all devices on all backends.
1090    ///
1091    /// This is the implementation of `wgpu::Instance::poll_all`.
1092    ///
1093    /// Return `all_queue_empty` indicating whether there are more queue
1094    /// submissions still in flight.
1095    pub fn poll_all_devices(&self, force_wait: bool) -> Result<bool, WaitIdleError> {
1096        self.instance.poll_all_devices(force_wait)
1097    }
1098
1099    /// # Safety
1100    ///
1101    /// - See [wgpu::Device::start_graphics_debugger_capture][api] for details the safety.
1102    ///
1103    /// [api]: ../../wgpu/struct.Device.html#method.start_graphics_debugger_capture
1104    pub unsafe fn device_start_graphics_debugger_capture(&self, device_id: DeviceId) {
1105        unsafe {
1106            self.hub
1107                .devices
1108                .get(device_id)
1109                .start_graphics_debugger_capture();
1110        }
1111    }
1112
1113    /// # Safety
1114    ///
1115    /// - See [wgpu::Device::stop_graphics_debugger_capture][api] for details the safety.
1116    ///
1117    /// [api]: ../../wgpu/struct.Device.html#method.stop_graphics_debugger_capture
1118    pub unsafe fn device_stop_graphics_debugger_capture(&self, device_id: DeviceId) {
1119        unsafe {
1120            self.hub
1121                .devices
1122                .get(device_id)
1123                .stop_graphics_debugger_capture();
1124        }
1125    }
1126
1127    pub fn pipeline_cache_get_data(&self, id: id::PipelineCacheId) -> Option<Vec<u8>> {
1128        let hub = &self.hub;
1129
1130        hub.pipeline_caches.get(id).get_data()
1131    }
1132
1133    pub fn device_drop(&self, device_id: DeviceId) {
1134        self.hub.devices.remove(device_id);
1135    }
1136
1137    /// `device_lost_closure` might never be called.
1138    pub fn device_set_device_lost_closure(
1139        &self,
1140        device_id: DeviceId,
1141        device_lost_closure: DeviceLostClosure,
1142    ) {
1143        let device = self.hub.devices.get(device_id);
1144
1145        device.set_device_lost_closure(device_lost_closure);
1146    }
1147
1148    pub fn device_destroy(&self, device_id: DeviceId) {
1149        let device = self.hub.devices.get(device_id);
1150        device.destroy();
1151    }
1152
1153    pub fn device_get_internal_counters(&self, device_id: DeviceId) -> wgt::InternalCounters {
1154        let device = self.hub.devices.get(device_id);
1155        device.get_internal_counters()
1156    }
1157
1158    pub fn device_generate_allocator_report(
1159        &self,
1160        device_id: DeviceId,
1161    ) -> Option<wgt::AllocatorReport> {
1162        let device = self.hub.devices.get(device_id);
1163        device.generate_allocator_report()
1164    }
1165
1166    #[cfg(feature = "trace")]
1167    pub fn device_take_trace(
1168        &self,
1169        device_id: DeviceId,
1170    ) -> Option<Box<dyn trace::Trace + Send + Sync + 'static>> {
1171        let device = self.hub.devices.get(device_id);
1172        device.take_trace()
1173    }
1174
1175    pub fn queue_drop(&self, queue_id: QueueId) {
1176        self.hub.queues.remove(queue_id);
1177    }
1178
1179    /// `op.callback` is always called, even in case of errors.
1180    pub fn buffer_map_async(
1181        &self,
1182        buffer_id: id::BufferId,
1183        offset: BufferAddress,
1184        size: Option<BufferAddress>,
1185        op: BufferMapOperation,
1186    ) -> Result<crate::SubmissionIndex, BufferAccessError> {
1187        let hub = &self.hub;
1188
1189        let buffer = hub.buffers.get(buffer_id);
1190
1191        buffer.map_async(offset, size, op)
1192    }
1193
1194    pub fn buffer_get_mapped_range(
1195        &self,
1196        buffer_id: id::BufferId,
1197        offset: BufferAddress,
1198        size: Option<BufferAddress>,
1199    ) -> Result<(NonNull<u8>, u64), BufferAccessError> {
1200        let hub = &self.hub;
1201
1202        let buffer = hub.buffers.get(buffer_id);
1203
1204        buffer.get_mapped_range(offset, size)
1205    }
1206
1207    pub fn buffer_unmap(&self, buffer_id: id::BufferId) -> BufferAccessResult {
1208        let hub = &self.hub;
1209
1210        let buffer = hub.buffers.get(buffer_id);
1211
1212        buffer.unmap()
1213    }
1214}