diff options
author | Samson <16504129+sagudev@users.noreply.github.com> | 2024-06-17 14:47:25 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-17 12:47:25 +0000 |
commit | cbc9304c2002fb0d5c8cdade39eddfe117b12053 (patch) | |
tree | ffb9afd683f8ec9d6eda26e3ba395d3214718b72 /components/webgpu/poll_thread.rs | |
parent | 3381f2a70442aa6a6c31a0bc4a4c3601299631f5 (diff) | |
download | servo-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.rs | 26 |
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 { |