wgpu_core/
global.rs

1use alloc::{borrow::ToOwned as _, sync::Arc};
2use core::fmt;
3
4use crate::{
5    binding_model::{BindGroupLayout, PipelineLayout},
6    command::{CommandBuffer, CommandEncoder},
7    device::{queue::Queue, Device},
8    hub::{Hub, HubReport},
9    id::{
10        AdapterId, BindGroupLayoutId, CommandBufferId, CommandEncoderId, ComputePipelineId,
11        DeviceId, PipelineLayoutId, QuerySetId, QueueId, RenderPipelineId, TextureId,
12    },
13    instance::{Adapter, Instance, Surface},
14    pipeline::{ComputePipeline, RenderPipeline},
15    registry::{Registry, RegistryReport},
16    resource::{QuerySet, Texture},
17    resource_log,
18};
19
20#[derive(Debug, PartialEq, Eq)]
21pub struct GlobalReport {
22    pub surfaces: RegistryReport,
23    pub hub: HubReport,
24}
25
26impl GlobalReport {
27    pub fn surfaces(&self) -> &RegistryReport {
28        &self.surfaces
29    }
30    pub fn hub_report(&self) -> &HubReport {
31        &self.hub
32    }
33}
34
35pub struct Global {
36    pub(crate) surfaces: Registry<Arc<Surface>>,
37    pub(crate) hub: Hub,
38    // the instance must be dropped last
39    pub instance: Instance,
40}
41
42impl Global {
43    pub fn new(
44        name: &str,
45        instance_desc: wgt::InstanceDescriptor,
46        telemetry: Option<hal::Telemetry>,
47    ) -> Self {
48        profiling::scope!("Global::new");
49        Self {
50            instance: Instance::new(name, instance_desc, telemetry),
51            surfaces: Registry::new(),
52            hub: Hub::new(),
53        }
54    }
55
56    /// # Safety
57    ///
58    /// Refer to the creation of wgpu-hal Instance for every backend.
59    pub unsafe fn from_hal_instance<A: hal::Api>(name: &str, hal_instance: A::Instance) -> Self {
60        profiling::scope!("Global::new");
61
62        Self {
63            instance: Instance::from_hal_instance::<A>(name.to_owned(), hal_instance),
64            surfaces: Registry::new(),
65            hub: Hub::new(),
66        }
67    }
68
69    /// # Safety
70    ///
71    /// - The raw instance handle returned must not be manually destroyed.
72    pub unsafe fn instance_as_hal<A: hal::Api>(&self) -> Option<&A::Instance> {
73        unsafe { self.instance.as_hal::<A>() }
74    }
75
76    /// # Safety
77    ///
78    /// - The raw handles obtained from the Instance must not be manually destroyed
79    pub unsafe fn from_instance(instance: Instance) -> Self {
80        profiling::scope!("Global::new");
81        Self {
82            instance,
83            surfaces: Registry::new(),
84            hub: Hub::new(),
85        }
86    }
87
88    pub fn generate_report(&self) -> GlobalReport {
89        GlobalReport {
90            surfaces: self.surfaces.generate_report(),
91            hub: self.hub.generate_report(),
92        }
93    }
94}
95
96// methods to import and resolve resources in the global hub
97impl Global {
98    /// Import [`Arc<Adapter>`] into the global hub,
99    /// returning an [`AdapterId`] under which the adapter is stored.
100    pub fn import_adapter(&self, adapter: Arc<Adapter>, id_in: Option<AdapterId>) -> AdapterId {
101        let fid = self.hub.adapters.prepare(id_in);
102        fid.assign(adapter)
103    }
104
105    /// Resolve an [`AdapterId`] to the corresponding [`Arc<Adapter>`] in the global hub.
106    pub fn resolve_adapter_id(&self, adapter_id: AdapterId) -> Arc<Adapter> {
107        self.hub.adapters.get(adapter_id)
108    }
109
110    /// Import [`Arc<Device>`] into the global hub,
111    /// returning a [`DeviceId`] under which the device is stored.
112    pub fn import_device(&self, device: Arc<Device>, id_in: Option<DeviceId>) -> DeviceId {
113        let fid = self.hub.devices.prepare(id_in);
114        fid.assign(device)
115    }
116
117    /// Resolve a [`DeviceId`] to the corresponding [`Arc<Device>`] in the global hub.
118    pub fn resolve_device_id(&self, device_id: DeviceId) -> Arc<Device> {
119        self.hub.devices.get(device_id)
120    }
121
122    /// Import [`Arc<Queue>`] into the global hub,
123    /// returning a [`QueueId`] under which the queue is stored.
124    pub fn import_queue(&self, queue: Arc<Queue>, id_in: Option<QueueId>) -> QueueId {
125        let fid = self.hub.queues.prepare(id_in);
126        fid.assign(queue)
127    }
128
129    /// Resolve a [`QueueId`] to the corresponding [`Arc<Queue>`] in the global hub.
130    pub fn resolve_queue_id(&self, queue_id: QueueId) -> Arc<Queue> {
131        self.hub.queues.get(queue_id)
132    }
133
134    /// Import [`Arc<PipelineLayout>`] into the global hub,
135    /// returning a [`PipelineLayoutId`] under which the pipeline layout is stored.
136    pub fn import_pipeline_layout(
137        &self,
138        pipeline_layout: Arc<PipelineLayout>,
139        id_in: Option<PipelineLayoutId>,
140    ) -> PipelineLayoutId {
141        let fid = self.hub.pipeline_layouts.prepare(id_in);
142        fid.assign(pipeline_layout)
143    }
144
145    /// Resolve a [`PipelineLayoutId`] to the corresponding [`Arc<PipelineLayout>`] in the global hub.
146    pub fn resolve_pipeline_layout_id(
147        &self,
148        pipeline_layout_id: PipelineLayoutId,
149    ) -> Arc<PipelineLayout> {
150        self.hub.pipeline_layouts.get(pipeline_layout_id)
151    }
152
153    /// Import [`Arc<BindGroupLayout>`] into the global hub,
154    /// returning a [`BindGroupLayoutId`] under which the bind group layout is stored.
155    pub fn import_bind_group_layout(
156        &self,
157        bind_group_layout: Arc<BindGroupLayout>,
158        id_in: Option<BindGroupLayoutId>,
159    ) -> BindGroupLayoutId {
160        let fid = self.hub.bind_group_layouts.prepare(id_in);
161        fid.assign(bind_group_layout)
162    }
163
164    /// Resolve a [`BindGroupLayoutId`] to the corresponding [`Arc<BindGroupLayout>`] in the global hub.
165    pub fn resolve_bind_group_layout_id(
166        &self,
167        bind_group_layout_id: BindGroupLayoutId,
168    ) -> Arc<BindGroupLayout> {
169        self.hub.bind_group_layouts.get(bind_group_layout_id)
170    }
171
172    /// Import [`Arc<CommandEncoder>`] into the global hub,
173    /// returning a [`CommandEncoderId`] under which the command encoder is stored.
174    pub fn import_command_encoder(
175        &self,
176        command_encoder: Arc<CommandEncoder>,
177        id_in: Option<CommandEncoderId>,
178    ) -> CommandEncoderId {
179        let fid = self.hub.command_encoders.prepare(id_in);
180        fid.assign(command_encoder)
181    }
182
183    /// Resolve a [`CommandEncoderId`] to the corresponding [`Arc<CommandEncoder>`] in the global hub.
184    pub fn resolve_command_encoder_id(
185        &self,
186        command_encoder_id: CommandEncoderId,
187    ) -> Arc<CommandEncoder> {
188        self.hub.command_encoders.get(command_encoder_id)
189    }
190
191    /// Import [`Arc<CommandBuffer>`] into the global hub,
192    /// returning a [`CommandBufferId`] under which the command buffer is stored.
193    pub fn import_command_buffer(
194        &self,
195        command_buffer: Arc<CommandBuffer>,
196        id_in: Option<CommandBufferId>,
197    ) -> CommandBufferId {
198        let fid = self.hub.command_buffers.prepare(id_in);
199        fid.assign(command_buffer)
200    }
201
202    /// Resolve a [`CommandBufferId`] to the corresponding [`Arc<CommandBuffer>`] in the global hub.
203    pub fn resolve_command_buffer_id(
204        &self,
205        command_buffer_id: CommandBufferId,
206    ) -> Arc<CommandBuffer> {
207        self.hub.command_buffers.get(command_buffer_id)
208    }
209
210    /// Import [`Arc<RenderPipeline>`] into the global hub,
211    /// returning a [`RenderPipelineId`] under which the render pipeline is stored.
212    pub fn import_render_pipeline(
213        &self,
214        render_pipeline: Arc<RenderPipeline>,
215        id_in: Option<RenderPipelineId>,
216    ) -> RenderPipelineId {
217        let fid = self.hub.render_pipelines.prepare(id_in);
218        fid.assign(render_pipeline)
219    }
220
221    /// Resolve a [`RenderPipelineId`] to the corresponding [`Arc<RenderPipeline>`] in the global hub.
222    pub fn resolve_render_pipeline_id(
223        &self,
224        render_pipeline_id: RenderPipelineId,
225    ) -> Arc<RenderPipeline> {
226        self.hub.render_pipelines.get(render_pipeline_id)
227    }
228
229    /// Import [`Arc<ComputePipeline>`] into the global hub,
230    /// returning a [`ComputePipelineId`] under which the compute pipeline is stored.
231    pub fn import_compute_pipeline(
232        &self,
233        compute_pipeline: Arc<ComputePipeline>,
234        id_in: Option<ComputePipelineId>,
235    ) -> ComputePipelineId {
236        let fid = self.hub.compute_pipelines.prepare(id_in);
237        fid.assign(compute_pipeline)
238    }
239
240    /// Resolve a [`ComputePipelineId`] to the corresponding [`Arc<ComputePipeline>`] in the global hub.
241    pub fn resolve_compute_pipeline_id(
242        &self,
243        compute_pipeline_id: ComputePipelineId,
244    ) -> Arc<ComputePipeline> {
245        self.hub.compute_pipelines.get(compute_pipeline_id)
246    }
247
248    /// Import [`Arc<QuerySet>`] into the global hub,
249    /// returning a [`QuerySetId`] under which the query set is stored.
250    pub fn import_query_set(
251        &self,
252        query_set: Arc<QuerySet>,
253        id_in: Option<QuerySetId>,
254    ) -> QuerySetId {
255        let fid = self.hub.query_sets.prepare(id_in);
256        fid.assign(query_set)
257    }
258
259    /// Resolve a [`QuerySetId`] to the corresponding [`Arc<QuerySet>`] in the global hub.
260    pub fn resolve_query_set_id(&self, query_set_id: QuerySetId) -> Arc<QuerySet> {
261        self.hub.query_sets.get(query_set_id)
262    }
263
264    /// Import [`Arc<Texture>`] into the global hub,
265    /// returning a [`TextureId`] under which the texture is stored.
266    pub fn import_texture(&self, texture: Arc<Texture>, id_in: Option<TextureId>) -> TextureId {
267        let fid = self.hub.textures.prepare(id_in);
268        fid.assign(texture)
269    }
270
271    /// Resolve a [`TextureId`] to the corresponding [`Arc<Texture>`] in the global hub.
272    pub fn resolve_texture_id(&self, texture_id: TextureId) -> Arc<Texture> {
273        self.hub.textures.get(texture_id)
274    }
275}
276
277impl fmt::Debug for Global {
278    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
279        f.debug_struct("Global").finish()
280    }
281}
282
283impl Drop for Global {
284    fn drop(&mut self) {
285        profiling::scope!("Global::drop");
286        resource_log!("Global::drop");
287    }
288}
289
290#[cfg(send_sync)]
291fn _test_send_sync(global: &Global) {
292    fn test_internal<T: Send + Sync>(_: T) {}
293    test_internal(global)
294}