aboutsummaryrefslogtreecommitdiffstats
path: root/components/webgpu/poll_thread.rs
diff options
context:
space:
mode:
authorSamson <16504129+sagudev@users.noreply.github.com>2024-06-17 14:47:25 +0200
committerGitHub <noreply@github.com>2024-06-17 12:47:25 +0000
commitcbc9304c2002fb0d5c8cdade39eddfe117b12053 (patch)
treeffb9afd683f8ec9d6eda26e3ba395d3214718b72 /components/webgpu/poll_thread.rs
parent3381f2a70442aa6a6c31a0bc4a4c3601299631f5 (diff)
downloadservo-cbc9304c2002fb0d5c8cdade39eddfe117b12053.tar.gz
servo-cbc9304c2002fb0d5c8cdade39eddfe117b12053.zip
webgpu: Implement device lost (#32354)
* device lost promise should be init at creation of device object * device lost impl * lock for device poll workaround for wgpu deadlocks * expect * Less lost reason reasoning in script
Diffstat (limited to 'components/webgpu/poll_thread.rs')
-rw-r--r--components/webgpu/poll_thread.rs26
1 files changed, 22 insertions, 4 deletions
diff --git a/components/webgpu/poll_thread.rs b/components/webgpu/poll_thread.rs
index 9239f41e60c..060b5171ffb 100644
--- a/components/webgpu/poll_thread.rs
+++ b/components/webgpu/poll_thread.rs
@@ -7,7 +7,7 @@
//! This is roughly based on <https://github.com/LucentFlux/wgpu-async/blob/1322c7e3fcdfc1865a472c7bbbf0e2e06dcf4da8/src/wgpu_future.rs>
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
-use std::sync::Arc;
+use std::sync::{Arc, Mutex, MutexGuard};
use std::thread::JoinHandle;
use log::warn;
@@ -40,14 +40,25 @@ pub(crate) struct Poller {
is_done: Arc<AtomicBool>,
/// Handle to the WGPU poller thread (to be used for unparking the thread)
handle: Option<JoinHandle<()>>,
+ /// Lock for device maintain calls (in poll_all_devices and queue_submit)
+ ///
+ /// This is workaround for wgpu deadlocks: https://github.com/gfx-rs/wgpu/issues/5572
+ lock: Arc<Mutex<()>>,
}
#[inline]
-fn poll_all_devices(global: &Arc<Global>, more_work: &mut bool, force_wait: bool) {
+fn poll_all_devices(
+ global: &Arc<Global>,
+ more_work: &mut bool,
+ force_wait: bool,
+ lock: &Mutex<()>,
+) {
+ let _guard = lock.lock().unwrap();
match global.poll_all_devices(force_wait) {
Ok(all_queue_empty) => *more_work = !all_queue_empty,
Err(e) => warn!("Poller thread got `{e}` on poll_all_devices."),
}
+ // drop guard
}
impl Poller {
@@ -56,9 +67,11 @@ impl Poller {
let is_done = Arc::new(AtomicBool::new(false));
let work = work_count.clone();
let done = is_done.clone();
+ let lock = Arc::new(Mutex::new(()));
Self {
work_count,
is_done,
+ lock: Arc::clone(&lock),
handle: Some(
std::thread::Builder::new()
.name("WGPU poller".into())
@@ -69,9 +82,9 @@ impl Poller {
// so every `ẁake` (even spurious) will do at least one poll.
// this is mostly useful for stuff that is deferred
// to maintain calls in wgpu (device resource destruction)
- poll_all_devices(&global, &mut more_work, false);
+ poll_all_devices(&global, &mut more_work, false, &lock);
while more_work || work.load(Ordering::Acquire) != 0 {
- poll_all_devices(&global, &mut more_work, true);
+ poll_all_devices(&global, &mut more_work, true, &lock);
}
std::thread::park(); //TODO: should we use timeout here
}
@@ -101,6 +114,11 @@ impl Poller {
.thread()
.unpark();
}
+
+ /// Lock for device maintain calls (in poll_all_devices and queue_submit)
+ pub(crate) fn lock(&self) -> MutexGuard<()> {
+ self.lock.lock().unwrap()
+ }
}
impl Drop for Poller {