nannou_wgpu/
device_map.rs1use std::collections::HashMap;
2use std::hash::{Hash, Hasher};
3use std::ops::Deref;
4use std::sync::{Arc, Mutex, Weak};
5
6use crate as wgpu;
7
8#[derive(Default)]
17pub struct AdapterMap {
18 map: Mutex<HashMap<AdapterMapKey, Arc<ActiveAdapter>>>,
19}
20
21#[derive(Clone, Debug, Eq, Hash, PartialEq)]
26pub struct AdapterMapKey {
27 power_preference: wgpu::PowerPreference,
28}
29
30pub struct ActiveAdapter {
32 adapter: wgpu::Adapter,
33 device_map: DeviceMap,
34}
35
36#[derive(Default)]
45pub struct DeviceMap {
46 map: Mutex<HashMap<DeviceMapKey, Weak<DeviceQueuePair>>>,
47}
48
49#[derive(Clone, Debug)]
54pub struct DeviceMapKey {
55 descriptor: wgpu::DeviceDescriptor<'static>,
56}
57
58#[derive(Debug)]
60pub struct DeviceQueuePair {
61 device: wgpu::Device,
62 queue: wgpu::Queue,
63}
64
65impl AdapterMap {
66 #[cfg(not(target_os = "unknown"))]
67 pub fn get_or_request<'a, 'b>(
74 &'a self,
75 options: wgpu::RequestAdapterOptions<'b>,
76 instance: &'a wgpu::Instance,
77 ) -> Option<Arc<ActiveAdapter>> {
78 let rt = tokio::runtime::Handle::current();
79 rt.block_on(self.get_or_request_async(options, instance))
80 }
81
82 #[cfg(not(target_os = "unknown"))]
83 pub fn request<'a, 'b>(
91 &'a self,
92 options: wgpu::RequestAdapterOptions<'b>,
93 instance: &'a wgpu::Instance,
94 ) -> Option<Arc<ActiveAdapter>> {
95 let rt = tokio::runtime::Handle::current();
96 rt.block_on(self.request_async(options, instance))
97 }
98
99 pub async fn get_or_request_async<'a, 'b>(
101 &'a self,
102 options: wgpu::RequestAdapterOptions<'b>,
103 instance: &'a wgpu::Instance,
104 ) -> Option<Arc<ActiveAdapter>> {
105 let power_preference = options.power_preference;
106 let key = AdapterMapKey { power_preference };
107 let mut map = self
108 .map
109 .lock()
110 .expect("failed to acquire `AdapterMap` lock");
111 if let Some(adapter) = map.get(&key) {
112 return Some(adapter.clone());
113 }
114 if let Some(adapter) = instance.request_adapter(&options).await {
115 let device_map = Default::default();
116 let adapter = Arc::new(ActiveAdapter {
117 adapter,
118 device_map,
119 });
120 return Some(map.entry(key).or_insert(adapter).clone());
121 }
122 None
123 }
124
125 pub async fn request_async<'a, 'b>(
127 &'a self,
128 options: wgpu::RequestAdapterOptions<'b>,
129 instance: &'b wgpu::Instance,
130 ) -> Option<Arc<ActiveAdapter>> {
131 let adapter = instance.request_adapter(&options).await?;
132 let device_map = Default::default();
133 let adapter = Arc::new(ActiveAdapter {
134 adapter,
135 device_map,
136 });
137 let power_preference = options.power_preference;
138 let key = AdapterMapKey { power_preference };
139 let mut map = self
140 .map
141 .lock()
142 .expect("failed to acquire `AdapterMap` lock");
143 map.insert(key, adapter.clone());
144 Some(adapter)
145 }
146
147 pub fn clear_inactive_adapters_and_devices(&self) {
151 let mut map = self
152 .map
153 .lock()
154 .expect("failed to acquire `AdapterMap` lock");
155 map.retain(|_, adapter| {
156 adapter.clear_inactive_devices();
157 adapter.device_count() > 0
158 });
159 }
160
161 pub(crate) fn _poll_all_devices(&self, maintain: wgpu::Maintain) {
163 let map = self
164 .map
165 .lock()
166 .expect("failed to acquire `AdapterMap` lock");
167 for adapter in map.values() {
168 adapter._poll_all_devices(maintain.clone()); }
170 }
171}
172
173impl ActiveAdapter {
174 #[cfg(not(target_os = "unknown"))]
175 pub fn get_or_request_device(
180 &self,
181 descriptor: wgpu::DeviceDescriptor<'static>,
182 ) -> Arc<DeviceQueuePair> {
183 let rt = tokio::runtime::Handle::current();
184 rt.block_on(self.get_or_request_device_async(descriptor))
185 }
186
187 #[cfg(not(target_os = "unknown"))]
188 pub fn request_device(
194 &self,
195 descriptor: wgpu::DeviceDescriptor<'static>,
196 ) -> Arc<DeviceQueuePair> {
197 let rt = tokio::runtime::Handle::current();
198 rt.block_on(self.request_device_async(descriptor))
199 }
200
201 pub async fn get_or_request_device_async(
206 &self,
207 descriptor: wgpu::DeviceDescriptor<'static>,
208 ) -> Arc<DeviceQueuePair> {
209 let key = DeviceMapKey { descriptor };
210 let mut map = self
211 .device_map
212 .map
213 .lock()
214 .expect("failed to acquire `AdapterMap` lock");
215 if let Some(device_ref) = map.get(&key) {
216 if let Some(device) = device_ref.upgrade() {
217 return device;
218 }
219 }
220 let (device, queue) = self
221 .adapter
222 .request_device(&key.descriptor, None)
223 .await
224 .expect("could not get or request device");
225 let device = Arc::new(DeviceQueuePair { device, queue });
226 map.insert(key, Arc::downgrade(&device));
227 device
228 }
229
230 pub async fn request_device_async(
236 &self,
237 descriptor: wgpu::DeviceDescriptor<'static>,
238 ) -> Arc<DeviceQueuePair> {
239 let (device, queue) = self
240 .adapter
241 .request_device(&descriptor, None)
242 .await
243 .expect("could not request device async");
244 let device = Arc::new(DeviceQueuePair { device, queue });
245 let key = DeviceMapKey { descriptor };
246 let mut map = self
247 .device_map
248 .map
249 .lock()
250 .expect("failed to acquire `DeviceMap` lock");
251 map.insert(key, Arc::downgrade(&device));
252 device
253 }
254
255 pub fn device_count(&self) -> usize {
257 let map = self
258 .device_map
259 .map
260 .lock()
261 .expect("failed to acquire `DeviceMap` lock");
262 map.len()
263 }
264
265 pub fn clear_inactive_devices(&self) {
267 let mut map = self
268 .device_map
269 .map
270 .lock()
271 .expect("failed to acquire `DeviceMap` lock");
272 map.retain(|_, pair| pair.upgrade().is_some());
273 }
274
275 fn _poll_all_devices(&self, maintain: wgpu::Maintain) {
277 let map = self
278 .device_map
279 .map
280 .lock()
281 .expect("failed to acquire `DeviceMap` lock");
282 for weak in map.values() {
283 if let Some(pair) = weak.upgrade() {
284 pair.device().poll(maintain.clone()); }
286 }
287 }
288}
289
290impl DeviceQueuePair {
291 pub fn device(&self) -> &wgpu::Device {
293 &self.device
294 }
295
296 pub fn queue(&self) -> &wgpu::Queue {
301 &self.queue
302 }
303}
304
305impl Deref for ActiveAdapter {
306 type Target = wgpu::Adapter;
307 fn deref(&self) -> &Self::Target {
308 &self.adapter
309 }
310}
311
312impl Hash for DeviceMapKey {
313 fn hash<H: Hasher>(&self, state: &mut H) {
314 hash_device_descriptor(&self.descriptor, state);
315 }
316}
317
318impl PartialEq for DeviceMapKey {
319 fn eq(&self, other: &Self) -> bool {
320 eq_device_descriptor(&self.descriptor, &other.descriptor)
321 }
322}
323
324impl Eq for DeviceMapKey {}
325
326fn eq_device_descriptor(
328 a: &wgpu::DeviceDescriptor<'static>,
329 b: &wgpu::DeviceDescriptor<'static>,
330) -> bool {
331 a.label == b.label && a.features == b.features && a.limits == b.limits
332}
333
334fn hash_device_descriptor<H>(desc: &wgpu::DeviceDescriptor<'static>, state: &mut H)
336where
337 H: Hasher,
338{
339 desc.label.hash(state);
340 desc.features.hash(state);
341 desc.limits.hash(state);
342}