Skip to main content

wgpu_core/
global.rs

1use alloc::{borrow::ToOwned as _, sync::Arc};
2use core::fmt;
3
4use crate::{
5    hub::{Hub, HubReport},
6    instance::{Instance, Surface},
7    registry::{Registry, RegistryReport},
8    resource_log,
9};
10
11#[derive(Debug, PartialEq, Eq)]
12pub struct GlobalReport {
13    pub surfaces: RegistryReport,
14    pub hub: HubReport,
15}
16
17impl GlobalReport {
18    pub fn surfaces(&self) -> &RegistryReport {
19        &self.surfaces
20    }
21    pub fn hub_report(&self) -> &HubReport {
22        &self.hub
23    }
24}
25
26pub struct Global {
27    pub(crate) surfaces: Registry<Arc<Surface>>,
28    pub(crate) hub: Hub,
29    // the instance must be dropped last
30    pub instance: Instance,
31}
32
33impl Global {
34    pub fn new(
35        name: &str,
36        instance_desc: wgt::InstanceDescriptor,
37        telemetry: Option<hal::Telemetry>,
38    ) -> Self {
39        profiling::scope!("Global::new");
40        Self {
41            instance: Instance::new(name, instance_desc, telemetry),
42            surfaces: Registry::new(),
43            hub: Hub::new(),
44        }
45    }
46
47    /// # Safety
48    ///
49    /// Refer to the creation of wgpu-hal Instance for every backend.
50    pub unsafe fn from_hal_instance<A: hal::Api>(name: &str, hal_instance: A::Instance) -> Self {
51        profiling::scope!("Global::new");
52
53        Self {
54            instance: Instance::from_hal_instance::<A>(name.to_owned(), hal_instance),
55            surfaces: Registry::new(),
56            hub: Hub::new(),
57        }
58    }
59
60    /// # Safety
61    ///
62    /// - The raw instance handle returned must not be manually destroyed.
63    pub unsafe fn instance_as_hal<A: hal::Api>(&self) -> Option<&A::Instance> {
64        unsafe { self.instance.as_hal::<A>() }
65    }
66
67    /// # Safety
68    ///
69    /// - The raw handles obtained from the Instance must not be manually destroyed
70    pub unsafe fn from_instance(instance: Instance) -> Self {
71        profiling::scope!("Global::new");
72        Self {
73            instance,
74            surfaces: Registry::new(),
75            hub: Hub::new(),
76        }
77    }
78
79    pub fn generate_report(&self) -> GlobalReport {
80        GlobalReport {
81            surfaces: self.surfaces.generate_report(),
82            hub: self.hub.generate_report(),
83        }
84    }
85}
86
87impl fmt::Debug for Global {
88    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89        f.debug_struct("Global").finish()
90    }
91}
92
93impl Drop for Global {
94    fn drop(&mut self) {
95        profiling::scope!("Global::drop");
96        resource_log!("Global::drop");
97    }
98}
99
100// Cranpose fork: the compiler proves an auto trait through every field, and
101// for `Global` that proof runs through the nested resource registries of
102// `Hub`, deeper than the default recursion limit, in every crate that needs a
103// wgpu object to be `Send` or `Sync` (nightly reports it as a future error).
104// These impls end the proof here. `_test_send_sync` checks each field, so
105// they hold exactly where the derived impls would.
106#[cfg(send_sync)]
107// SAFETY: every field is `Send`, which `_test_send_sync` checks.
108unsafe impl Send for Global {}
109#[cfg(send_sync)]
110// SAFETY: every field is `Sync`, which `_test_send_sync` checks.
111unsafe impl Sync for Global {}
112
113#[cfg(send_sync)]
114fn _test_send_sync(global: &Global) {
115    fn test_internal<T: Send + Sync>(_: &T) {}
116    let Global {
117        surfaces,
118        hub,
119        instance,
120    } = global;
121    test_internal(surfaces);
122    test_internal(hub);
123    test_internal(instance);
124}