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 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 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 pub unsafe fn instance_as_hal<A: hal::Api>(&self) -> Option<&A::Instance> {
74 unsafe { self.instance.as_hal::<A>() }
75 }
76
77 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
97impl Global {
99 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 pub fn resolve_adapter_id(&self, adapter_id: AdapterId) -> Arc<Adapter> {
108 self.hub.adapters.get(adapter_id)
109 }
110
111 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 pub fn resolve_device_id(&self, device_id: DeviceId) -> Arc<Device> {
120 self.hub.devices.get(device_id)
121 }
122
123 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 pub fn resolve_queue_id(&self, queue_id: QueueId) -> Arc<Queue> {
132 self.hub.queues.get(queue_id)
133 }
134
135 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 pub fn resolve_buffer_id(&self, buffer_id: BufferId) -> Arc<Buffer> {
274 self.hub.buffers.get(buffer_id)
275 }
276
277 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 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}