mirror of
https://github.com/Zenithsiz/zsw.git
synced 2026-02-04 18:20:44 +00:00
Made SurfaceLock a generic Lock type.
This commit is contained in:
parent
908da8931c
commit
f2f053df48
@ -58,6 +58,7 @@
|
||||
|
||||
// Modules
|
||||
mod display_wrapper;
|
||||
mod lock;
|
||||
mod rect;
|
||||
mod scan_dir;
|
||||
mod side_effect;
|
||||
@ -66,6 +67,7 @@ mod thread;
|
||||
// Exports
|
||||
pub use {
|
||||
display_wrapper::DisplayWrapper,
|
||||
lock::Lock,
|
||||
rect::Rect,
|
||||
scan_dir::dir_files_iter,
|
||||
side_effect::{extse, MightBlock, MightLock, SideEffect, WithSideEffect},
|
||||
|
||||
41
zsw-util/src/lock.rs
Normal file
41
zsw-util/src/lock.rs
Normal file
@ -0,0 +1,41 @@
|
||||
//! Locks
|
||||
|
||||
// Imports
|
||||
use parking_lot::MutexGuard;
|
||||
|
||||
/// Lock with an associated guard
|
||||
// TODO: Use `lock_api` to make this cleaner
|
||||
#[derive(Debug)]
|
||||
pub struct Lock<'a, Data, Source> {
|
||||
/// Guard
|
||||
guard: MutexGuard<'a, Data>,
|
||||
|
||||
/// Source pointer
|
||||
// Note: This is just to ensure caller only passes a
|
||||
// lock that came from the same instance that locked it.
|
||||
source: *const Source,
|
||||
}
|
||||
|
||||
impl<'a, Data, Source> Lock<'a, Data, Source> {
|
||||
/// Creates a new lock
|
||||
pub fn new(guard: MutexGuard<'a, Data>, source: &Source) -> Self {
|
||||
Self { guard, source }
|
||||
}
|
||||
|
||||
/// Returns the inner data
|
||||
pub fn get(&self, source: &Source) -> &Data {
|
||||
self.assert_source(source);
|
||||
&self.guard
|
||||
}
|
||||
|
||||
/// Returns the inner data
|
||||
pub fn get_mut(&mut self, source: &Source) -> &mut Data {
|
||||
self.assert_source(source);
|
||||
&mut self.guard
|
||||
}
|
||||
|
||||
/// Asserts that the correct `wgpu` instance was passed
|
||||
fn assert_source(&self, source: &Source) {
|
||||
assert_eq!(self.source, source as *const _, "Lock had the wrong source then used");
|
||||
}
|
||||
}
|
||||
@ -60,7 +60,7 @@
|
||||
use {
|
||||
anyhow::Context,
|
||||
crossbeam::atomic::AtomicCell,
|
||||
parking_lot::{Mutex, MutexGuard},
|
||||
parking_lot::Mutex,
|
||||
pollster::FutureExt,
|
||||
std::marker::PhantomData,
|
||||
wgpu::TextureFormat,
|
||||
@ -136,6 +136,9 @@ pub struct Wgpu<'window> {
|
||||
/// Window lifetime
|
||||
// Note: Our surface must outlive the window, so we make sure of it using the `'window` lifetime
|
||||
window_phantom: PhantomData<&'window Window>,
|
||||
|
||||
/// Lock source
|
||||
lock_source: LockSource,
|
||||
}
|
||||
|
||||
impl<'window> Wgpu<'window> {
|
||||
@ -163,6 +166,7 @@ impl<'window> Wgpu<'window> {
|
||||
surface_texture_format,
|
||||
queued_resize: AtomicCell::new(None),
|
||||
window_phantom: PhantomData,
|
||||
lock_source: LockSource,
|
||||
})
|
||||
}
|
||||
|
||||
@ -181,13 +185,11 @@ impl<'window> Wgpu<'window> {
|
||||
/// # Blocking
|
||||
/// Will block until any existing surface locks are dropped
|
||||
#[side_effect(MightLock<SurfaceLock>)]
|
||||
pub fn lock_surface(&self) -> SurfaceLock<'window, '_> {
|
||||
pub fn lock_surface(&self) -> SurfaceLock {
|
||||
// DEADLOCK: Caller is responsible to ensure we don't deadlock
|
||||
// We don't lock it outside of this method
|
||||
SurfaceLock {
|
||||
guard: self.surface.lock_se().allow::<MightBlock>(),
|
||||
wgpu: self as *const _,
|
||||
}
|
||||
let guard = self.surface.lock_se().allow::<MightBlock>();
|
||||
SurfaceLock::new(guard, &self.lock_source)
|
||||
}
|
||||
|
||||
/// Returns the current surface's size
|
||||
@ -197,7 +199,7 @@ impl<'window> Wgpu<'window> {
|
||||
/// use it on `wgpu` operations that might panic on wrong surface
|
||||
/// sizes.
|
||||
pub fn surface_size(&self, surface_lock: &SurfaceLock) -> PhysicalSize<u32> {
|
||||
surface_lock.get(self).size
|
||||
surface_lock.get(&self.lock_source).size
|
||||
}
|
||||
|
||||
/// Returns the surface texture format
|
||||
@ -230,10 +232,10 @@ impl<'window> Wgpu<'window> {
|
||||
// TODO: Remove size from passed parameters
|
||||
pub fn render(
|
||||
&self,
|
||||
surface_lock: &mut SurfaceLock<'window, '_>,
|
||||
surface_lock: &mut SurfaceLock,
|
||||
f: impl FnOnce(&mut wgpu::CommandEncoder, &wgpu::TextureView, PhysicalSize<u32>) -> Result<(), anyhow::Error>,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
let surface = surface_lock.get_mut(self);
|
||||
let surface = surface_lock.get_mut(&self.lock_source);
|
||||
|
||||
// Check for resizes
|
||||
if let Some(size) = self.queued_resize.take() {
|
||||
@ -274,37 +276,14 @@ impl<'window> Wgpu<'window> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Source for all locks
|
||||
// Note: This is to ensure user can't create the locks themselves
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[non_exhaustive]
|
||||
pub struct LockSource;
|
||||
|
||||
/// Surface lock
|
||||
#[derive(Debug)]
|
||||
pub struct SurfaceLock<'window, 'a> {
|
||||
/// Guard
|
||||
guard: MutexGuard<'a, Surface>,
|
||||
|
||||
/// `Wgpu` pointer
|
||||
// Note: This is just to ensure caller only passes a
|
||||
// lock that came from the same instance
|
||||
wgpu: *const Wgpu<'window>,
|
||||
}
|
||||
|
||||
impl<'window, 'a> SurfaceLock<'window, 'a> {
|
||||
/// Returns the guard after ensuring the correct `wgpu` instance was passed
|
||||
pub fn get(&self, wgpu: &Wgpu<'window>) -> &Surface {
|
||||
self.assert_source(wgpu);
|
||||
&self.guard
|
||||
}
|
||||
|
||||
/// Returns the guard mutable after ensuring the correct `wgpu` instance was passed
|
||||
pub fn get_mut(&mut self, wgpu: &Wgpu<'window>) -> &mut Surface {
|
||||
self.assert_source(wgpu);
|
||||
&mut self.guard
|
||||
}
|
||||
|
||||
/// Asserts that the correct `wgpu` instance was passed
|
||||
fn assert_source(&self, wgpu: &Wgpu<'window>) {
|
||||
assert_eq!(self.wgpu, wgpu, "Wrong `wgpu` instance was passed to method");
|
||||
}
|
||||
}
|
||||
|
||||
pub type SurfaceLock<'a> = zsw_util::Lock<'a, Surface, LockSource>;
|
||||
|
||||
/// Configures the window surface and returns the preferred surface texture format
|
||||
fn configure_window_surface(
|
||||
|
||||
@ -30,7 +30,7 @@ impl Renderer {
|
||||
///
|
||||
/// # Locking
|
||||
/// Locks the `zsw_wgpu::SurfaceLock` lock on `wgpu`
|
||||
#[side_effect(MightLock<zsw_wgpu::SurfaceLock<'window, 'wgpu>>)]
|
||||
#[side_effect(MightLock<zsw_wgpu::SurfaceLock<'wgpu>>)]
|
||||
pub async fn run<'window, 'wgpu>(
|
||||
&self,
|
||||
window: &Window,
|
||||
@ -81,7 +81,7 @@ impl Renderer {
|
||||
///
|
||||
/// # Locking
|
||||
/// Locks the `zsw_wgpu::SurfaceLock` lock on `wgpu`
|
||||
#[side_effect(MightLock<zsw_wgpu::SurfaceLock<'window, 'wgpu>>)]
|
||||
#[side_effect(MightLock<zsw_wgpu::SurfaceLock<'wgpu>>)]
|
||||
async fn render<'window, 'wgpu>(
|
||||
window: &Window,
|
||||
wgpu: &'wgpu Wgpu<'window>,
|
||||
@ -93,7 +93,7 @@ impl Renderer {
|
||||
// DEADLOCK: We don't hold the `wgpu::SurfaceLock` lock from `wgpu`.
|
||||
// Caller ensures we can lock it.
|
||||
let paint_jobs = settings_window
|
||||
.paint_jobs()
|
||||
.paint_jobs(wgpu)
|
||||
.await
|
||||
.allow::<MightLock<zsw_wgpu::SurfaceLock>>();
|
||||
|
||||
|
||||
@ -72,10 +72,10 @@ impl SettingsWindow {
|
||||
///
|
||||
/// # Locking
|
||||
/// Locks the `zsw_wgpu::SurfaceLock` lock on `wgpu`
|
||||
#[side_effect(MightLock<zsw_wgpu::SurfaceLock<'_, '_>>)]
|
||||
pub async fn run(
|
||||
#[side_effect(MightLock<zsw_wgpu::SurfaceLock<'wgpu>>)]
|
||||
pub async fn run<'wgpu>(
|
||||
&self,
|
||||
wgpu: &Wgpu<'_>,
|
||||
wgpu: &'wgpu Wgpu<'_>,
|
||||
egui: &Egui,
|
||||
window: &Window,
|
||||
panels: &Panels,
|
||||
@ -126,8 +126,8 @@ impl SettingsWindow {
|
||||
/// Locks the `zsw_wgpu::SurfaceLock` lock on `wgpu`
|
||||
// Note: Doesn't literally lock it, but the other side of the channel
|
||||
// needs to lock it in order to progress, so it's equivalent
|
||||
#[side_effect(MightLock<zsw_wgpu::SurfaceLock<'_, '_>>)]
|
||||
pub async fn paint_jobs(&self) -> Vec<egui::epaint::ClippedMesh> {
|
||||
#[side_effect(MightLock<zsw_wgpu::SurfaceLock<'wgpu>>)]
|
||||
pub async fn paint_jobs<'wgpu>(&self, _wgpu: &'wgpu Wgpu<'_>) -> Vec<egui::epaint::ClippedMesh> {
|
||||
// Note: This can't return an `Err` because `self` owns a sender
|
||||
self.paint_jobs_rx.recv().await.expect("Paint jobs sender was closed")
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user