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 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 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 pub unsafe fn instance_as_hal<A: hal::Api>(&self) -> Option<&A::Instance> {
73 unsafe { self.instance.as_hal::<A>() }
74 }
75
76 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
96impl Global {
98 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 pub fn resolve_adapter_id(&self, adapter_id: AdapterId) -> Arc<Adapter> {
107 self.hub.adapters.get(adapter_id)
108 }
109
110 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 pub fn resolve_device_id(&self, device_id: DeviceId) -> Arc<Device> {
119 self.hub.devices.get(device_id)
120 }
121
122 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 pub fn resolve_queue_id(&self, queue_id: QueueId) -> Arc<Queue> {
131 self.hub.queues.get(queue_id)
132 }
133
134 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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}