use std::marker::PhantomData;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex};
#[derive(Clone, Copy, Debug, Default)]
pub struct WgpuFilterStats {
pub frames: u64,
pub upload_secs: f64,
pub gpu_secs: f64,
pub download_secs: f64,
pub hw_import_frames: u64,
pub hw_download_frames: u64,
pub hw_download_secs: f64,
}
pub struct WgpuParamsHandle<P: bytemuck::Pod> {
pub(crate) bytes: Arc<Mutex<Vec<u8>>>,
pub(crate) dirty: Arc<AtomicBool>,
pub(crate) _marker: PhantomData<P>,
}
impl<P: bytemuck::Pod> WgpuParamsHandle<P> {
pub fn set(&self, value: P) {
let mut bytes = self
.bytes
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
bytes.clear();
bytes.extend_from_slice(bytemuck::bytes_of(&value));
self.dirty.store(true, Ordering::Release);
}
pub fn update(&self, f: impl FnOnce(&mut P)) {
let mut bytes = self
.bytes
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
let mut value: P = bytemuck::pod_read_unaligned(&bytes);
f(&mut value);
bytes.clear();
bytes.extend_from_slice(bytemuck::bytes_of(&value));
self.dirty.store(true, Ordering::Release);
}
}
pub(crate) struct SharedParams {
pub(crate) bytes: Arc<Mutex<Vec<u8>>>,
pub(crate) dirty: Arc<AtomicBool>,
pub(crate) len: usize,
}
impl SharedParams {
pub(crate) fn new(initial: Vec<u8>) -> Self {
Self {
len: initial.len(),
bytes: Arc::new(Mutex::new(initial)),
dirty: Arc::new(AtomicBool::new(true)),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[repr(C)]
#[derive(Clone, Copy, PartialEq, Debug, bytemuck::Pod, bytemuck::Zeroable)]
struct Pair {
a: f32,
b: f32,
}
#[test]
fn update_reads_modifies_and_marks_dirty() {
let shared = SharedParams::new(bytemuck::bytes_of(&Pair { a: 1.0, b: 2.0 }).to_vec());
let handle = WgpuParamsHandle::<Pair> {
bytes: Arc::clone(&shared.bytes),
dirty: Arc::clone(&shared.dirty),
_marker: PhantomData,
};
shared.dirty.store(false, Ordering::Release);
handle.update(|p| p.b += 40.0);
assert!(shared.dirty.load(Ordering::Acquire));
let bytes = shared
.bytes
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner);
let read: Pair = bytemuck::pod_read_unaligned(&bytes);
assert_eq!(read, Pair { a: 1.0, b: 42.0 });
}
}