srs2dge_core/target/
catcher.rs1use crate::target::Target;
2use std::sync::{
3 atomic::{AtomicBool, Ordering},
4 mpsc::{channel, Receiver},
5 Arc,
6};
7use wgpu::Device;
8
9pub struct Catcher {
12 error_receiver: Receiver<String>,
13 error_listening: Arc<AtomicBool>,
14}
15
16impl Catcher {
19 pub fn new(device: &Device) -> Self {
20 let (error_sender, error_receiver) = channel();
22 let listening = Arc::new(AtomicBool::new(false));
23 let error_listening = listening.clone();
24 device.on_uncaptured_error(move |err| match err {
25 wgpu::Error::OutOfMemory { source } => log::error!("Out of memory: {source}"),
26 wgpu::Error::Validation {
27 source,
28 description,
29 } => {
30 if listening.load(Ordering::SeqCst) {
31 log::warn!("Handled validation error: {source} {description}");
32 error_sender.send(description).unwrap();
33 } else {
34 panic!("Unhandled validation error: {source} {description}")
35 }
36 }
37 });
38
39 Self {
40 error_receiver,
41 error_listening,
42 }
43 }
44
45 pub fn catch_error<T, F: FnOnce(&Target) -> T>(target: &Target, f: F) -> Result<T, String> {
46 let s = &target.catcher;
47 s.error_listening.store(true, Ordering::SeqCst);
48 let result = f(target);
49 s.error_listening.store(false, Ordering::SeqCst);
50
51 if let Ok(err) = s.error_receiver.try_recv() {
52 Err(err)
53 } else {
54 Ok(result)
55 }
56 }
57}