dynamis-gpu 0.6.0

GPU-driven physics engine
Documentation
use crate::pipeline::{ComputeLayout, ComputeProgram, PipelineHandle};
use std::collections::{HashMap, VecDeque};
use std::sync::Arc;
use std::time::Duration;
use wgpu::Device;

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum WarmupBudget {
    All,
    Within(Duration),
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct WarmupProgress {
    pub ready: usize,
    pub total: usize,
}

impl WarmupProgress {
    pub fn complete(&self) -> bool {
        self.ready == self.total
    }
}

pub(crate) struct PipelineLibrary {
    entries: HashMap<Arc<ComputeProgram>, PipelineHandle>,
    pending: VecDeque<PipelineHandle>,
}

impl PipelineLibrary {
    pub(crate) fn new() -> Self {
        Self {
            entries: HashMap::new(),
            pending: VecDeque::new(),
        }
    }

    pub(crate) fn declare(&mut self, device: &Device, program: ComputeProgram) -> PipelineHandle {
        let program = Arc::new(program);
        if let Some(handle) = self.entries.get(&program) {
            return handle.clone();
        }
        let handle = PipelineHandle::new(program.clone(), ComputeLayout::new(device, &program));
        self.entries.insert(program, handle.clone());
        self.pending.push_back(handle.clone());
        handle
    }

    pub(crate) fn drain_pending(&mut self) -> Vec<PipelineHandle> {
        self.pending.drain(..).collect()
    }

    pub(crate) fn take_pending(&mut self) -> Option<PipelineHandle> {
        self.pending.pop_front()
    }

    pub(crate) fn progress(&self) -> WarmupProgress {
        WarmupProgress {
            ready: self
                .entries
                .values()
                .filter(|handle| handle.is_warmed())
                .count(),
            total: self.entries.len(),
        }
    }
}