use std::sync::{Arc, Mutex};
#[derive(Debug, Default)]
pub(crate) struct PendingPick {
in_flight: Option<(u32, u32)>,
completed: Option<((u32, u32), Option<f32>)>,
}
impl PendingPick {
pub(crate) fn request(&mut self, x: u32, y: u32) -> bool {
if self.in_flight.is_some() {
return false;
}
self.in_flight = Some((x, y));
true
}
pub(crate) fn complete(&mut self, depth: Option<f32>) {
if let Some(px) = self.in_flight.take() {
self.completed = Some((px, depth));
}
}
pub(crate) fn latest(&self) -> Option<((u32, u32), Option<f32>)> {
self.completed
}
pub(crate) fn is_in_flight(&self) -> bool {
self.in_flight.is_some()
}
}
#[derive(Debug)]
pub(crate) struct AsyncPickState {
pub(crate) pending: PendingPick,
pub(crate) map_result: Arc<Mutex<Option<Result<(), wgpu::BufferAsyncError>>>>,
pub(crate) staging: Option<wgpu::Buffer>,
}
impl Default for AsyncPickState {
fn default() -> Self {
Self {
pending: PendingPick::default(),
map_result: Arc::new(Mutex::new(None)),
staging: None,
}
}
}
#[cfg(test)]
mod tests {
use super::PendingPick;
#[test]
fn request_complete_rearm_cycle() {
let mut p = PendingPick::default();
assert!(p.latest().is_none(), "nothing completed yet");
assert!(p.request(3, 4), "idle: submit");
assert!(p.is_in_flight());
assert!(p.latest().is_none(), "still nothing completed");
p.complete(Some(12.5));
assert!(!p.is_in_flight());
assert_eq!(p.latest(), Some(((3, 4), Some(12.5))));
assert!(p.request(7, 8), "idle again: submit");
assert_eq!(p.latest(), Some(((3, 4), Some(12.5))));
p.complete(None); assert_eq!(p.latest(), Some(((7, 8), None)));
}
#[test]
fn in_flight_coalesces_further_requests() {
let mut p = PendingPick::default();
assert!(p.request(1, 1));
assert!(!p.request(2, 2), "in flight: coalesced");
assert!(!p.request(3, 3), "still coalesced");
p.complete(Some(5.0));
assert_eq!(p.latest(), Some(((1, 1), Some(5.0))));
assert!(p.request(4, 4), "idle again after harvest");
}
#[test]
fn complete_without_in_flight_is_noop() {
let mut p = PendingPick::default();
p.complete(Some(9.0));
assert!(p.latest().is_none());
}
#[test]
fn sky_completion_clears_in_flight() {
let mut p = PendingPick::default();
assert!(p.request(0, 0));
p.complete(None);
assert!(!p.is_in_flight());
assert_eq!(p.latest(), Some(((0, 0), None)));
}
}