wgpu_core/
global.rs

1use crate::{
2    hal_api::HalApi,
3    hub::{HubReport, Hubs},
4    id,
5    identity::GlobalIdentityHandlerFactory,
6    instance::{Instance, Surface},
7    registry::Registry,
8    storage::{Element, StorageReport},
9};
10
11#[derive(Debug)]
12pub struct GlobalReport {
13    pub surfaces: StorageReport,
14    #[cfg(all(feature = "vulkan", not(target_arch = "wasm32")))]
15    pub vulkan: Option<HubReport>,
16    #[cfg(all(feature = "metal", any(target_os = "macos", target_os = "ios")))]
17    pub metal: Option<HubReport>,
18    #[cfg(all(feature = "dx12", windows))]
19    pub dx12: Option<HubReport>,
20    #[cfg(all(feature = "dx11", windows))]
21    pub dx11: Option<HubReport>,
22    #[cfg(feature = "gles")]
23    pub gl: Option<HubReport>,
24}
25
26pub struct Global<G: GlobalIdentityHandlerFactory> {
27    pub instance: Instance,
28    pub surfaces: Registry<Surface, id::SurfaceId, G>,
29    pub(crate) hubs: Hubs<G>,
30}
31
32impl<G: GlobalIdentityHandlerFactory> Global<G> {
33    pub fn new(name: &str, factory: G, instance_desc: wgt::InstanceDescriptor) -> Self {
34        profiling::scope!("Global::new");
35        Self {
36            instance: Instance::new(name, instance_desc),
37            surfaces: Registry::without_backend(&factory, "Surface"),
38            hubs: Hubs::new(&factory),
39        }
40    }
41
42    /// # Safety
43    ///
44    /// Refer to the creation of wgpu-hal Instance for every backend.
45    pub unsafe fn from_hal_instance<A: HalApi>(
46        name: &str,
47        factory: G,
48        hal_instance: A::Instance,
49    ) -> Self {
50        profiling::scope!("Global::new");
51        Self {
52            instance: A::create_instance_from_hal(name, hal_instance),
53            surfaces: Registry::without_backend(&factory, "Surface"),
54            hubs: Hubs::new(&factory),
55        }
56    }
57
58    /// # Safety
59    ///
60    /// - The raw instance handle returned must not be manually destroyed.
61    pub unsafe fn instance_as_hal<A: HalApi>(&self) -> Option<&A::Instance> {
62        A::instance_as_hal(&self.instance)
63    }
64
65    /// # Safety
66    ///
67    /// - The raw handles obtained from the Instance must not be manually destroyed
68    pub unsafe fn from_instance(factory: G, instance: Instance) -> Self {
69        profiling::scope!("Global::new");
70        Self {
71            instance,
72            surfaces: Registry::without_backend(&factory, "Surface"),
73            hubs: Hubs::new(&factory),
74        }
75    }
76
77    pub fn clear_backend<A: HalApi>(&self, _dummy: ()) {
78        let mut surface_guard = self.surfaces.data.write();
79        let hub = A::hub(self);
80        // this is used for tests, which keep the adapter
81        hub.clear(&mut surface_guard, false);
82    }
83
84    pub fn generate_report(&self) -> GlobalReport {
85        GlobalReport {
86            surfaces: self.surfaces.data.read().generate_report(),
87            #[cfg(all(feature = "vulkan", not(target_arch = "wasm32")))]
88            vulkan: if self.instance.vulkan.is_some() {
89                Some(self.hubs.vulkan.generate_report())
90            } else {
91                None
92            },
93            #[cfg(all(feature = "metal", any(target_os = "macos", target_os = "ios")))]
94            metal: if self.instance.metal.is_some() {
95                Some(self.hubs.metal.generate_report())
96            } else {
97                None
98            },
99            #[cfg(all(feature = "dx12", windows))]
100            dx12: if self.instance.dx12.is_some() {
101                Some(self.hubs.dx12.generate_report())
102            } else {
103                None
104            },
105            #[cfg(all(feature = "dx11", windows))]
106            dx11: if self.instance.dx11.is_some() {
107                Some(self.hubs.dx11.generate_report())
108            } else {
109                None
110            },
111            #[cfg(feature = "gles")]
112            gl: if self.instance.gl.is_some() {
113                Some(self.hubs.gl.generate_report())
114            } else {
115                None
116            },
117        }
118    }
119}
120
121impl<G: GlobalIdentityHandlerFactory> Drop for Global<G> {
122    fn drop(&mut self) {
123        profiling::scope!("Global::drop");
124        log::info!("Dropping Global");
125        let mut surface_guard = self.surfaces.data.write();
126
127        // destroy hubs before the instance gets dropped
128        #[cfg(all(feature = "vulkan", not(target_arch = "wasm32")))]
129        {
130            self.hubs.vulkan.clear(&mut surface_guard, true);
131        }
132        #[cfg(all(feature = "metal", any(target_os = "macos", target_os = "ios")))]
133        {
134            self.hubs.metal.clear(&mut surface_guard, true);
135        }
136        #[cfg(all(feature = "dx12", windows))]
137        {
138            self.hubs.dx12.clear(&mut surface_guard, true);
139        }
140        #[cfg(all(feature = "dx11", windows))]
141        {
142            self.hubs.dx11.clear(&mut surface_guard, true);
143        }
144        #[cfg(feature = "gles")]
145        {
146            self.hubs.gl.clear(&mut surface_guard, true);
147        }
148
149        // destroy surfaces
150        for element in surface_guard.map.drain(..) {
151            if let Element::Occupied(surface, _) = element {
152                self.instance.destroy_surface(surface);
153            }
154        }
155    }
156}
157
158#[cfg(all(
159    test,
160    any(
161        not(target_arch = "wasm32"),
162        all(
163            feature = "fragile-send-sync-non-atomic-wasm",
164            not(target_feature = "atomics")
165        )
166    )
167))]
168fn _test_send_sync(global: &Global<crate::identity::IdentityManagerFactory>) {
169    fn test_internal<T: Send + Sync>(_: T) {}
170    test_internal(global)
171}