memkit-gpu 0.2.0-beta.1

Backend-agnostic GPU memory management for memkit
//! GPU memory pools.

use crate::backend::MkGpuBackend;
use crate::buffer::{MkDeviceBuffer, MkBufferUsage};
use crate::memory::MkMemoryType;
use std::collections::VecDeque;

/// A pool of GPU buffers for efficient reuse.
pub struct MkGpuPool<B: MkGpuBackend> {
    memory_type: MkMemoryType,
    buffer_size: usize,
    usage: MkBufferUsage,
    free_buffers: VecDeque<B::BufferHandle>,
    max_buffers: usize,
}

impl<B: MkGpuBackend> MkGpuPool<B> {
    /// Create a new GPU buffer pool.
    pub fn new(
        memory_type: MkMemoryType,
        buffer_size: usize,
        usage: MkBufferUsage,
        max_buffers: usize,
    ) -> Self {
        Self {
            memory_type,
            buffer_size,
            usage,
            free_buffers: VecDeque::new(),
            max_buffers,
        }
    }

    /// Acquire a buffer from the pool or create a new one.
    pub fn acquire(&mut self, backend: &B) -> Result<MkDeviceBuffer<B>, B::Error> {
        if let Some(handle) = self.free_buffers.pop_front() {
            Ok(MkDeviceBuffer::new(handle, self.buffer_size, self.usage))
        } else {
            let handle = backend.create_buffer(self.buffer_size, self.usage, self.memory_type)?;
            Ok(MkDeviceBuffer::new(handle, self.buffer_size, self.usage))
        }
    }

    /// Return a buffer to the pool.
    pub fn release(&mut self, buffer: MkDeviceBuffer<B>, backend: &B) {
        if self.free_buffers.len() < self.max_buffers {
            self.free_buffers.push_back(buffer.handle().clone());
        } else {
            backend.destroy_buffer(buffer.handle());
        }
    }

    /// Get the number of free buffers.
    pub fn free_count(&self) -> usize {
        self.free_buffers.len()
    }

    /// Clear all pooled buffers.
    pub fn clear(&mut self, backend: &B) {
        for handle in self.free_buffers.drain(..) {
            backend.destroy_buffer(&handle);
        }
    }
}