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